{"slug": "your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review", "title": "Your AI Assistant Ships Insecure Code Almost Half the Time. Catching It in Review Is Too Late.", "summary": "Veracode's Spring GenAI Code Security Update found that 45% of code generated by 150 large language models across 80 tasks contained known vulnerabilities, with security pass rates stuck at about 55% for two years. Weakness classes like SQL injection had high pass rates (82%) while log injection (13%) and cross-site scripting (15%) were low, indicating models reproduce training data security postures rather than reason about security. A Stanford study by Neil Perry showed AI-assisted developers wrote less secure code but were more confident, and skepticism mitigated issues but doesn't scale.", "body_md": "*By Sangyeon Park — creator of Cencurity, an open-source security gateway for LLM coding agents*\n\nIn March 2026, Veracode published its Spring GenAI Code Security Update. The team ran more than 150 large language models through 80 code-generation tasks in Java, JavaScript, C#, and Python, then tested every output against four common weakness categories.\n\nThe syntax was excellent. Over 95% of the generated code compiled and ran.\n\nThe security was not. Forty-five percent of it contained a known vulnerability.\n\nThe raw number is not what should worry you. What should worry you is that the number has not moved. Veracode's phrasing is unusually blunt for a vendor report: security pass rates \"remain stubbornly stuck at approximately 55%\" — virtually identical to where they stood two years ago. Two years of longer context windows, better reasoning traces, and steadily climbing SWE-bench scores, and the security line is flat.\n\nBreak the results down by weakness class and the shape gets strange:\n\n| Weakness class | Security pass rate |\n|---|---|\n| Insecure crypto (CWE-327) | 86% |\n| SQL injection (CWE-89) | 82% |\n| Cross-site scripting (CWE-80) | 15% |\n| Log injection (CWE-117) | 13% |\n\nSQL injection has been the canonical example in every introductory security tutorial written since roughly 2005. Parameterized queries are everywhere in the training corpus. Log injection has almost no pedagogical footprint by comparison — a real weakness that simply never became a teaching example.\n\nThe models are not reasoning about security. They are reproducing the security posture of whatever code they saw most of.\n\nWhere the corpus was well-taught, output is safe. Where it wasn't, output is not. That is a training-data artifact, and it is not the kind of thing a bigger model fixes on its own — which is precisely what Veracode observed. The reasoning-tuned models did better, reaching 70–72%, and still fell short of anything you would ship.\n\nLanguage matters too, and not the way most teams assume. Python scored 62%, C# 58%, JavaScript 57%. Java came in at 29%.\n\nNeil Perry and colleagues at Stanford ran a controlled user study on exactly this question. Participants with access to an AI assistant (OpenAI's `codex-davinci-002`\n\n) \"wrote significantly less secure code than those without access.\"\n\nThen the finding that should reshape how you think about tooling: those same participants \"were more likely to believe they wrote secure code.\"\n\nWorse output, higher confidence. Those two effects compound, and they compound in the place where your last line of defense lives — human review. A reviewer who assumes the generated code is fine reads it faster and more charitably than one who wrote it themselves at 2 a.m. and knows where the shortcuts are.\n\nPerry's team also found the mitigating factor, which complicates the doom narrative: participants who distrusted the assistant and actively rewrote their prompts produced fewer vulnerabilities. Skepticism worked. Skepticism just does not scale to a team of thirty engineers with a sprint deadline.\n\nFocusing only on generated code understates the problem, and this is the part I got wrong when I started building in this space.\n\nWhen you put an agent in your development loop, you are not just receiving code from a model. You are sending it things. Repository contents, environment values, error output pasted from a terminal, sometimes credentials sitting in a config file the agent decided to read. And the agent acts on what comes back — writing files, running commands, calling tools.\n\nThat surface has four distinct failure modes, and traditional application security covers none of them well: prompt injection, unsafe tool calls, data leakage on the outbound path, and actions taken with no record that they happened.\n\nScanning the code the model produced addresses one of those four.\n\nThe industry's standard answer to \"vulnerabilities are found too late\" has been shift-left: move scanning earlier — pre-commit hooks, IDE linters, CI gates. SAST reads source at rest. DAST hits a running application. IAST instruments runtime. All three are good tools, and all three share one assumption that generative AI just broke.\n\nThey all assume the code already exists.\n\nWith an agent in the loop, there is a window between the model emitting a token stream and that stream landing in your editor — and in agentic setups, between the stream landing and the agent executing it. In a Roo Code or Claude Code session running semi-autonomously, that window can close before any human looks at anything. A `subprocess.run(user_input, shell=True)`\n\ncan be written, saved, and executed inside one turn. Your pre-commit hook fires afterward, if it fires at all.\n\nThat gap is the problem I built [Cencurity](https://github.com/cencurity/cencurity) to close.\n\nThe architecture is deliberately unremarkable, because unremarkable is what gets adopted:\n\n```\nIDE / Agent  →  Cencurity Gateway (127.0.0.1:38180)  →  LLM Provider\n```\n\nA local gateway binds to loopback. Your agent points its provider base URL at it instead of at `api.openai.com`\n\n. Outbound requests pass through a policy engine that redacts secrets — API keys, credentials — before they leave the machine. Inbound responses are inspected for dangerous constructs like `eval`\n\nand `subprocess`\n\nbefore the editor renders them. Everything runs locally; nothing is shipped to a third party for analysis.\n\nThe part that took the longest to get right is that this happens on the stream. Waiting for a complete response and then scanning it is a much easier problem, and it gives up the thing that makes the approach worth building — enforcement has to land while the model is still producing tokens, or you are back to inspecting code that already exists.\n\nI call the category CAST — Code-Aware Security Transformation. The distinguishing property is not the analysis technique, which is comparatively conventional. It is the moment of intervention: policy is enforced inline, while the model is still writing the code.\n\nTwo design decisions carried more weight than the detection logic itself.\n\n**API keys never leave the IDE.** The gateway forwards credentials; it never stores them. This closes the first objection in any security review, and it rules out an entire class of features — no cross-session budget enforcement, no org-wide key rotation.\n\n**Only violations get logged.** This one I reversed. Cencurity launched recording all traffic as audit logs, which is the obvious design if you are thinking about compliance, and the wrong one if you are thinking about adoption. Full logging gives you far better policy tuning and a real audit trail. It also means a security tool is now recording every prompt a developer writes, which makes it both a morale problem and a fresh exfiltration target. A security product that creates a new breach surface has negative value. Current builds record policy violations and security events; normal traffic passes through unrecorded. I took the worse telemetry.\n\nCencurity sits in front of Roo Code, Continue, Claude Code, and Gemini CLI, routing to OpenAI, Anthropic, Gemini, OpenRouter, and OpenAI-compatible endpoints.\n\n**\"How is this different from having an LLM review the generated code?\"** This is the first question almost everyone asks, and it deserves a real answer rather than a slogan. A model reviewing output is a probabilistic check on a probabilistic system — you are asking the thing that produced the vulnerability to notice it, with no guarantee it notices the same one twice. A gateway does policy-based enforcement with structured extraction at the infrastructure layer. Same rule, same verdict, every time, and you can read the rule. Determinism is the entire argument. Where the model approach wins is semantic nuance, and I would not claim otherwise.\n\n**\"This is just a proxy. I can write a proxy.\"** Yes. The proxy is the easy half. The policy set, the masking rules, and the false-positive tuning are the part that takes months, and they decide whether the thing survives contact with a real team.\n\n**\"Another network hop in my inner loop.\"** Fair. Local loopback keeps this small relative to a round trip to a hosted model, but it is not zero, and I have not published p99 numbers under load because I do not yet have measurements I would stand behind.\n\n**\"False positives will train my developers to ignore it.\"** The strongest objection, and I do not have a complete answer. A gateway that blocks legitimate `subprocess`\n\ncalls in a DevOps repository is worse than no gateway. Policy tuning is genuine, ongoing work, and it is the thing most likely to decide whether this approach is viable at all.\n\nNone of this argues that runtime interception replaces code review, SAST, or the security engineer who actually reads the diff. It argues that a control which fires *after* generation is structurally the wrong shape for a workflow where generation and execution now happen in the same breath.\n\nVeracode's flat two-year line is the strongest available evidence that this will not resolve itself through model improvement. If the pass rate were climbing, waiting would be a defensible strategy. It isn't, so it isn't.\n\nThe gap is real, it is measurable, and it sits in a place where nothing you currently run is watching.\n\n*Cencurity is open source under Apache-2.0 on GitHub and launched on Product Hunt.*", "url": "https://wpnews.pro/news/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review", "canonical_source": "https://dev.to/sangyeonpark/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review-is-too-late-4ml", "published_at": "2026-08-21 19:24:32+00:00", "updated_at": "2026-08-21 19:45:16.400016+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-safety", "ai-ethics", "ai-tools"], "entities": ["Veracode", "Cencurity", "Sangyeon Park", "Neil Perry", "Stanford", "OpenAI", "codex-davinci-002"], "alternates": {"html": "https://wpnews.pro/news/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review", "markdown": "https://wpnews.pro/news/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review.md", "text": "https://wpnews.pro/news/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review.txt", "jsonld": "https://wpnews.pro/news/your-ai-assistant-ships-insecure-code-almost-half-the-time-catching-it-in-review.jsonld"}}