AI coding tools write insecure code by default: here's the evidence
By Seaworthy · 10 June 2026
Photo by Google DeepMind on Unsplash
The pattern nobody wants to talk about
There's a generous framing of this problem that goes something like: "AI tools write code at the level of the prompt they receive." That's partly true. But it papers over something more uncomfortable: even when you write a perfectly reasonable prompt, the default output of most AI coding assistants carries security anti-patterns that a code reviewer would flag on day one.
This is not a hot take. It's documented.
A 2023 study from Stanford's Human-Computer Interaction Group found that participants using GitHub Copilot were significantly more likely to produce insecure code than those without it, and, more interestingly, were more confident their code was secure. That second part is the dangerous bit.
What actually gets generated
Let me be specific, because vague claims about "AI security risks" are useless. Here are categories of real problems that appear repeatedly in the research and in production codebases:
Hardcoded secrets and credentials. This is the most common. AI models trained on GitHub have absorbed a lot of code that predates secret-scanning tooling. When you ask an assistant to "add a database connection", a non-trivial number of completions will include a literal connection string with placeholder credentials in a format that looks plausible enough to ship. Copilot, ChatGPT, and Claude all do this in certain contexts.
SQL injection via string concatenation. Ask an AI to write a search endpoint and there's a reasonable chance you get something like this:
const query = `SELECT * FROM users WHERE name = '${req.query.name}'`;
db.run(query);
Parametrised queries are well-documented in training data. But the AI is optimising for "code that looks like it works", and raw string interpolation satisfies that constraint.
Disabled TLS verification. When users ask assistants to fix SSL errors in development, the path of least resistance is rejectUnauthorized: false or the Python equivalent verify=False. That fix makes it into production more than it should.
import requests
response = requests.get(url, verify=False) # AI wrote this to fix a local cert error
Overly permissive CORS. A common AI-generated Express setup:
app.use(cors({ origin: '*' }));
Fine for a quick demo. Not fine when that demo becomes a product.
Missing authentication on generated routes. If you ask an AI to "add an admin endpoint", it will often give you the endpoint without middleware. The assumption seems to be that auth is your problem to add later.
Why it happens
The models are not malicious. They're doing something specific: they're completing the statistical next token given the context. Security constraints are not automatically part of that context unless you explicitly introduce them.
There's a training data problem too. Public GitHub repositories are full of tutorial code, prototype code, and legacy code. This code is functional. It is also frequently insecure. A model trained on it will reproduce its patterns.
OpenAI, Anthropic, and GitHub have all made improvements. System prompts for coding assistants increasingly include security guidance. But the output is probabilistic, and the guidance competes with every insecure example in the training data. You are not always going to win that coin flip.
The vibe coding problem
"Vibe coding" is the practice of using AI to generate most of your codebase without deeply reading what gets produced. I'm not condemning it. A lot of genuinely useful software gets built this way, and the productivity gains are real.
The problem is that the security properties of vibe-coded software are opaque in a way that even inexperienced traditionally-written code is not. When a junior dev writes bad code, there's usually a clear author who made a specific decision. When an AI writes bad code, the author is a distribution over millions of training examples, and nobody in the room necessarily knows what trade-offs were made.
A separate, automated analysis pass matters a lot here. Not because it catches everything, but because it runs unconditionally. You don't have to remember to check for verify=False if a tool flags it automatically every time.
What the research says you should do
The Stanford paper's conclusion was essentially: use AI assistants, but add a verification step. More recent work from Cybersecurity researchers at New York University found that prompt engineering alone ("write secure code") reduced but did not eliminate vulnerable outputs. The researchers who got the best results combined improved prompts with post-generation static analysis.
That's the honest answer: the tools are useful and you should keep using them, but "AI wrote it" is not a security review. Running a static analysis pass over generated code, specifically one that looks for the patterns AI tools tend to produce, closes most of the gap.
Seaworthy is a static analysis tool built specifically around the patterns that appear in AI-generated and vibe-coded repositories, runnable via npx seaworthycode against any local repo.
This article was generated by AI and summarises publicly available sources.
Seaworthy scans your repo for the issues covered in articles like this one.
Security gaps, exposed secrets, and misconfigurations — caught before you deploy. Free to run, no account needed.