Security-Aware Prompting
Bake security into prompts: demand input validation, safe secrets, least privilege, and a security pass, because AI defaults are insecure.
TL;DR
- AI code is insecure by default; make security an explicit, standing requirement in your prompts.
- Demand input validation, parameterized queries, safe secret handling, and least privilege.
- Run a dedicated security review pass; do not rely on the model to volunteer safety.
Assume Insecure
Default Is UnsafeTreat generated code as needing hardening until proven safe.
Works != safe. Harden before trust.Learned Bad PatternsModels echo insecure idioms common in public code.
String-built SQL, secrets in code
-> seen often, reproduced often.Make It ExplicitSecurity happens when you require it, not by default.
Unstated security = missing
security.Standing Requirements
Validate InputValidate and sanitize everything from outside the trust boundary.
"Validate all input; reject early;
never trust the client."Safe Data AccessParameterized queries and encoded output, always.
"Parameterized queries only; encode
output to stop XSS."Secrets & PrivilegeSecrets in env/secret manager; least privilege everywhere.
"No secrets in code or logs.
Least-privilege tokens."Threat-Focused Review
Name The ThreatsScope the security pass to the risks relevant to the code.
"Check: injection, authz, SSRF,
secret leakage."Exploit ScenarioRequire a concrete attack for each finding.
"For each: the exact input that
exploits it + a fix."Rank & VerifyWorst-first, and confirm each before you change code.
Reproduce, then fix. Don't fix
phantoms.Keep Humans & Tools
First Pass, Not FinalAI review speeds triage; a human owns the sign-off.
AI finds common issues ->
human decides.Run ScannersBack prompts with SAST and dependency scanning.
Add SAST + `npm audit` to CI.Never Weaken SecurityRefuse fixes that disable checks to 'make it work'.
No disabling TLS/auth to pass.
Fix the real issue.Tips
- Add a standing security block to your context file so every task inherits the rules.
- Name the threats that matter for the code at hand (injection, authz, SSRF) so the pass is focused.
Warnings
- Models reproduce insecure patterns from their training data; assume generated code needs hardening.
- Never let the model embed secrets, disable TLS checks, or log sensitive data to 'make it work'.
In Practice
Two moves: a security block you keep in your context file so every task inherits it, and a focused, threat-named review pass you run on sensitive code. Together they shift security from afterthought to default.
- The standing block encodes the non-negotiable rules for every prompt.
- It covers input, data access, secrets, privilege, and error handling.
- The review pass names the specific threats for a concrete, deep check.
- Findings require an exploit scenario and a fix, and a human signs off.
# In CLAUDE.md / AGENTS.md (applies to every task)
## Security (always)
- validate + sanitize all external input; reject early
- parameterized queries only; never build SQL by string
- secrets from env/secret manager; never in code or logs
- least privilege for tokens, roles, and file access
- encode output to prevent XSS; set safe headers
- errors return safe messages; log details server-side
- never disable TLS/cert/auth checks to make something work
# A focused review pass on sensitive code
Security review this payment handler. Threats to check:
injection, broken authorization, SSRF, insecure
deserialization, secret/PII leakage. For each finding:
file:line, a concrete exploit input, severity, and a fix.
Rank worst-first. If clean, say so.FAQ
Models optimize for code that works, not code that is safe, and they learned from vast amounts of public code that includes insecure patterns. Unless you ask for security, you often get the trusting happy path: unvalidated input, string-built queries, secrets in code, and over-broad permissions.
Validate and sanitize all external input, use parameterized queries, keep secrets in env/secret managers (never in code or logs), apply least privilege, encode output to prevent XSS, and handle errors without leaking internals. Put these in your context file so they apply standing.
Do a dedicated pass as in the code-review chapter, but security-only, naming the relevant threats (injection, broken authz, SSRF, insecure deserialization, secret leakage). Ask for ranked findings with a concrete exploit scenario and a fix, and verify each before acting.
Use it as a fast first pass, not an authority. It catches common issues well but misses context-specific risks and can be wrong. For anything sensitive, a human with security knowledge, and tools like SAST and dependency scanners, must own the sign-off.