← Back to Automation foundation team
See how it helps
Secure application development
Checks how your application handles sign-ins, forms, uploads and sensitive data. Helps prevent malicious input and unintended data exposure.
secure-coding
Team members using this skill
When is it useful?
Use this skill when code handles user input, authentication, files or sensitive data. It starts from concrete ways a feature could be misused and applies protections using the project’s existing framework.
What does it help you do?
- Validates input and safely handles database queries and output to reduce injection and cross-site scripting risks.
- Checks server-side permissions, session handling and record ownership rather than relying on hidden buttons.
- Constrains uploads, file paths and outbound URLs, and keeps credentials and personal information out of logs and error responses.
Try asking this
Review the applicant document upload feature. Check file validation, record-level access, storage paths and error messages, then add tests for the relevant abuse cases. Try a disguised executable and another applicant's record ID. Reject both without leaking file paths, and confirm a legitimate owner can still upload an allowed document.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Secure Coding
Threat model first
Spend five minutes thinking like an attacker before adding controls:
- Trust boundaries: where untrusted data enters (requests, forms, uploads, webhooks, third-party APIs, queues, model output, files or paths from other processes). Trust follows who wrote a value, not the channel that delivered it.
- Assets: credentials, personal data, payment data, admin actions, money movement.
- For each boundary ask: can someone impersonate a user or service, alter data, deny an action later, read data they should not, overwhelm it, or gain rights? Name the mitigation for each.
- Write the abuse case next to the use case and make it a test.
Ask a human first
New or changed authentication flows, storing a new kind of sensitive data, a new external integration, CORS changes, new upload handlers, changes to rate limits, granting elevated roles.
Secrets
- Never put secrets, API keys, tokens, passwords or private keys in source, tests, fixtures, logs, commit messages or client bundles.
- Read them from the environment or the repo's secret mechanism; add placeholders, never real values, to the example env file.
- Do not log tokens, cookies, auth headers, full request bodies or personal data. Redact.
- If you find a committed secret, do not repeat its value; report it so it can be rotated.
Input and output
- Treat all external data as untrusted: params, bodies, headers, cookies, files, webhooks, third-party API responses.
- Validate on the server with allowlists: type, length, format, range, enum. Client-side validation is only UX.
- Encode output for its context (HTML, attribute, URL, JS). Prefer the framework's auto-escaping; justify every raw render.
- Never build shell commands, eval, regexes or templates from user input. Pass process arguments as arrays.
- Deserialize only safe formats such as JSON; never unserialize or unpickle untrusted data.
Database
- Use parameterized queries or the ORM/query builder bindings. Never concatenate input into SQL.
- Identifiers (columns, sort direction, table names) cannot be bound: map them through an allowlist.
Authentication and authorization
- Check authorization server-side on every endpoint, action and query, not only in the UI.
- Verify the current user may access the specific record (prevent IDOR); scope queries by user or tenant.
- Deny by default: new routes must not become public by accident.
- Use the framework's sessions, password hashing (bcrypt, argon2) and CSRF protection. Never roll your own crypto.
- Session cookies: HttpOnly, Secure, SameSite.
Files and URLs
- Never join user input into file paths without normalizing and confirming the result stays inside the allowed base directory.
- Uploads: enforce size limits, check type by content not only extension, generate the stored name, store outside the web root or without execute permission.
- When the server fetches user-supplied URLs, allowlist hosts and block internal addresses (SSRF).
Dependencies and privileges
- Add dependencies only when needed; prefer maintained, widely used packages, locked through the lockfile.
- Do not disable TLS verification, CSP, security headers or CORS restrictions to make something work. Never reflect any origin with credentials.
- Least privilege: minimal API scopes, roles, file permissions and database grants.
Errors
- Show users generic messages; log details server-side. No stack traces, SQL or internal paths in responses.
- Fail closed: if an auth or validation check errors, deny.
Before you finish
- No secrets or personal data in code, logs, tests or commits.
- New input validated server-side; output encoded for its context.
- Queries parameterized; dynamic identifiers allowlisted.
- Every new or changed endpoint checks authentication and record-level permission.
- File paths, uploads and outbound URLs constrained.
- Error responses leak nothing internal.
Included files 2
LICENSE.txtSKILL.md
