Why agentic code needs its own security pass
AI coding assistants optimise for "does it run", not "is it safe". They were trained on a public corpus where most code is insecure-but-functional, so a vibe-coded feature ships with the happy path working and the security path missing. A concrete example we saw last month: an internal admin tool scaffolded in two days by Cursor that accepted JSON straight into a Postgres query string. It worked. It was also a textbook SQLi. The fix is not to stop vibe coding, it is to add a security pass that the agent itself runs. When we consult, the first question we ask is: does anything check the AI output for security before it merges? The honest answer is usually no. That single missing step is where most of the risk lives. NIST SP 800-218A (the AI-specific extension to the Secure Software Development Framework, published 2024) names this as the foundational gap and is the document to put in front of a sceptical CTO.
Gap 1: No Content Security Policy
The most common miss, and the one we open every consult with. An AI-scaffolded web app ships with no CSP header, which means any injected script runs with full trust. Content Security Policy is the single highest-leverage security header: it tells the browser exactly which sources of script, style, and connection are allowed, so an injected payload simply does not execute. The fix is one header. Start in report-only mode (Content-Security-Policy-Report-Only) so you do not break the app, point report-uri at a free collector such as report-uri.com, watch the violation reports for a week, tighten the policy until it goes quiet, then enforce. Most frameworks set it in one config file: next.config.js for Next.js, helmet for Express, the SecurityMiddleware for Django. MDN Web Docs has the canonical CSP reference and the example policies are copy-pasteable. The Google web.dev "Strict CSP" guide is the best modern walkthrough; it argues for a nonce-based policy over allowlists, which is what we ship for any client touching authenticated routes.
Gap 2: Secrets in the code
AI assistants hardcode API keys, database URLs, and tokens, because the prompt said "make it work" and a literal string works. We find live credentials in AI-built repositories constantly. The 2024 GitGuardian "State of Secrets Sprawl" report documented over 23 million secrets leaked to public GitHub in a single year, with the growth curve tracking the adoption of AI assistants almost exactly. Two fixes, both free. First, a pre-commit secret scanner (gitleaks or trufflehog) so a secret never enters a commit. Second, a CI secret scan as a backstop in case someone skips the hook. Both are one GitHub Action away (gitleaks/gitleaks-action is the canonical one). Then move every secret to environment variables, a managed secrets store such as AWS Secrets Manager or HashiCorp Vault, or a sealed-secrets pattern if you are on Kubernetes. If you find a committed secret, rotate it immediately, do not just delete the line. Git history is forever, the repo is one accidental "public" toggle from being readable by everyone, and crawlers index new public repos within minutes.
Gap 3: Over-permissioned agents
When an agent has a tool that writes to the database, it usually has write access to the whole database. When it can call an API, it usually holds an admin key. The principle of least privilege says the agent gets the narrowest scope that still lets it do its job. A support agent that reads order status does not need write access to the orders table, and certainly does not need read access to the payments table. Scope the credential the tool uses, not just the tool definition. The pattern that works: a separate IAM role per agent, with read-only or write-narrow policies, and short-lived credentials issued through STS or its cloud equivalent. This is the gap that turns a contained prompt injection into a full breach: the injection is only as dangerous as the permissions behind the tool it reaches. Simon Willison has documented dozens of variants on his blog under the "prompt injection" tag since 2022, and the pattern is always the same: the model misbehaved, the tool obeyed, the credential had no limit.
Gap 4: Unvalidated input on AI-built endpoints
The AI builds an endpoint, wires it up, and ships. It rarely adds input validation, rate limiting, or output encoding on its own. Every endpoint an agent builds needs the same three controls: validate the shape of the input, limit the request rate, encode the output. A schema-validation library (zod for TypeScript, pydantic v2 for Python, valibot if bundle size matters) handles the first in a few lines and rejects malformed payloads before they ever touch business logic. A middleware (express-rate-limit, slowapi for FastAPI, the django-ratelimit package) handles the second. The framework usually handles the third if you let it render through the template system rather than concatenate strings. The OWASP Top 10 (2021 edition, still current as of 2025) is the checklist; A03 Injection and A01 Broken Access Control are still the entries that catch AI-built code. A worked counter-example: an endpoint that takes a "userId" from the query string and queries the database directly. Add zod with a uuid schema and a per-IP rate limit and you have closed two OWASP entries with eight lines of code.
Gap 5: Hallucinated dependencies (slopsquatting)
AI assistants suggest packages that do not exist. Researchers at the University of Texas published a 2024 paper showing that around 5 to 20 percent of package suggestions from major coding LLMs reference nonexistent packages, with consistent name patterns the model invents repeatedly. Attackers watch for the common hallucinations and register those exact names with malware inside, an attack now called slopsquatting (the name was coined by Seth Larson at the Python Software Foundation in early 2024). When the AI suggests installing a plausible-sounding package, verify it exists, check the download history on npm or PyPI, confirm the maintainer profile is real, and read the source of any recent release. Pin versions, commit a lockfile (package-lock.json, poetry.lock, Cargo.lock), and run a dependency audit in CI (npm audit, pip-audit, cargo audit). This gap is unique to agentic programming: a human developer rarely invents a package name, but a model will, confidently, several times a week.
The fix that compounds: a security linter in the agent loop
The highest-leverage move is to put a security linter (semgrep with the p/security-audit ruleset, the framework own linter such as ESLint with eslint-plugin-security, a CSP checker like csp-evaluator from Google) inside the agent loop, so when the agent iterates, it sees its own security findings and fixes them in the same session. The Anthropic and Cursor tool-use docs both show the pattern: register the linter as a tool, expose its output to the agent, and the agent reads the warning text the same way a human would. This turns security from a thing a human catches three weeks later into a thing the agent catches now, before the code is even reviewed. It is the difference between agentic programming that compounds risk and agentic programming that compounds quality. Set this up once and every future session inherits it. The biggest single-day improvement we have seen at a client came from adding semgrep to the agent loop on a Monday and watching the linter findings drop to single digits by Friday, with no human code review in between.
Further reading
Real, named sources the editor can swap in for specific URLs. We do not auto-link these because the right link changes over time. If you find a great primary source, write us and we will update the note.
- OWASP Top 10 for LLM Applications. The agent-specific security list. Prompt injection, insecure output handling, excessive agency. Read this before you ship any agent.
- OWASP Top 10 (web application security). The baseline. Injection and broken access control are still the entries that catch AI-built endpoints.
- MDN Web Docs: Content Security Policy (CSP). Canonical CSP reference. Start with the report-only directive and the example policies.
- NIST Secure Software Development Framework (SSDF, SP 800-218). The framework for building security into the SDLC, including AI-assisted development.
- gitleaks and trufflehog. Open-source secret scanners. Run as a pre-commit hook plus a CI backstop.
- Simon Willison's writing on prompt injection. The most-cited working source on prompt injection. Updated continuously since 2022.
- r/netsec and r/cybersecurity. Practitioner threads on AI-generated code risk, slopsquatting, and supply-chain attacks.
Comments