When touching any code, configuration, or infrastructure, apply the threat-modelling principles below before making changes. Think attacker-first: assume hostile input, compromised dependencies, and least-privilege as defaults.
Before writing or modifying code, ask:
- What crosses a trust boundary here? (user input → backend, service A → service B, CLI arg → shell, etc.)
- Is data validated and sanitised at the boundary, not deep inside?
- Are return paths (errors, logs, responses) leaking data back across the boundary?
Rule: Never trust data that crosses a boundary without explicit validation.
For every input surface (HTTP, CLI, env vars, files, IPC, DB results used as queries):
- Prefer allowlists over denylists.
- Parameterise queries; never concatenate user data into SQL, shell commands, or templates.
- Validate type, length, format, and range before use.
- Treat file paths as untrusted — resolve and jail to an expected root.
Red flags to flag and fix:
- String interpolation into SQL, LDAP, XPath, HTML, or shell
- Unvalidated redirects or forwards
When writing auth-related code:
- Verify authentication (who are you?) and authorisation (are you allowed?) separately.
- Default to deny; explicit grants only.
- Never roll custom crypto or auth schemes — use established libraries.
- Session tokens must be random, long (≥128 bits), and invalidated server-side on logout.
- Enforce authorisation checks close to the resource, not only at the entry point.
Rule: If a function touches a protected resource, it must verify permissions itself, not rely solely on callers to have done so.
- Never hardcode secrets, API keys, passwords, or tokens in source code or config files.
- Use environment variables or a secrets manager; reference them by name only.
- Rotate secrets if exposure is suspected; flag any found in existing code.
- Exclude secret-carrying files from version control (
.gitignore,.claudeignore). - Mask secrets in logs — never log credentials or tokens.
When creating or modifying:
- File permissions: default to
600/640; never777. - DB accounts: grant only the tables/operations the service needs.
- Cloud IAM: scope roles to the minimum required actions and resources.
- Process privilege: drop privileges as early as possible; never run as root unless unavoidable.
- Network: services should bind only to required interfaces; block unused ports.
When adding or updating dependencies:
- Prefer well-maintained packages with a track record.
- Pin versions in lock files; do not use version ranges in production manifests.
- Flag packages that require unusual permissions (filesystem, network, exec) for review.
- Never
curl | bashor equivalent without explicit user approval and review. Rule: Treat every new dependency as a potential attack vector.
- Use modern algorithms only: AES-256-GCM, ChaCha20-Poly1305, RSA-2048+, ECDSA P-256+, SHA-256+.
- Never use: MD5, SHA-1, DES, RC4, ECB mode.
- Always use authenticated encryption (AEAD) for confidential data.
- Generate IVs/nonces with a CSPRNG; never reuse them.
- Store passwords with a memory-hard KDF: Argon2id, bcrypt (cost ≥12), or scrypt.
- Fail closed: on error, deny the operation and return a generic message to the caller.
- Log the detailed error server-side only; never expose stack traces, internal paths, or DB schemas to clients.
- Structured logs must not contain PII or secrets.
- Rate-limit and alert on repeated auth failures or unexpected error spikes.
When asked to refactor large chunk of code or when completing a significant change, work through:
[ ] Identified all entry points (HTTP, CLI, events, files, queues, etc.)
[ ] Identified all trust boundaries crossed
[ ] Identified sensitive data flows (PII, credentials, keys, health data, etc.)
[ ] Validated inputs at each boundary
[ ] Verified authN/authZ on each protected resource
[ ] Confirmed no secrets in code or logs
[ ] Confirmed least-privilege for all roles and permissions
[ ] Checked for injection vectors (SQL, shell, template, SSRF, etc.)
[ ] Reviewed third-party dependencies introduced
[ ] Confirmed error paths fail closed and leak nothing
[ ] Added or updated security-relevant tests
Where available, run before committing:
- SAST:
bandit(Python),semgrep,eslint-plugin-security(JS/TS),gosec(Go) - Dependency audit:
pip-audit,npm audit,cargo audit,trivy - Secret scanning:
gitleaks,trufflehog - Container:
trivy image,docker scout
- Ask before acting on anything that touches auth, crypto, payments, PII, or infra.
- Prefer reversible changes — migrations, feature flags, soft deletes.
- Document security assumptions inline with
# SECURITY:comments so reviewers see them.