Security Insights

The Vulnerabilities I Keep Finding in AI-Generated Code

7 min read
John, Founder of EliteSec By John Svazic
Close-up over the shoulder of a developer's hand on a laptop keyboard, a code editor filling the screen under warm desk-lamp light

AI is writing a fast-growing share of the code reaching production today, and not just in prototypes or internal tooling. Customer-facing applications handling real data and real transactions are increasingly built this way.

I’ve spent years running CREST-accredited penetration tests, and AI-assisted code now makes up a growing share of what I’m asked to test. Clear patterns are already emerging in what I find. The same categories of vulnerability appear repeatedly, across different teams, stacks, and industries. Authorization gaps are the class I see most consistently.

This isn’t trend commentary. This is what I actually find.

If your team is shipping AI-assisted code, and at this point, most are, the categories below are worth auditing before an external tester arrives. The issues aren’t exotic. That’s what makes them consistent.


Business Logic Gaps

AI code generators are good at producing syntactically correct implementations of clearly stated requirements. They are poor at reasoning about what the code should not allow.

The gaps I find most reliably are not in the logic that was written, they’re in the logic that was never considered. Flows that assume a specific sequence of user actions. State transitions that the UI enforces but the API doesn’t. Operations that are designed for one user but never validated against another’s data.

These aren’t input validation failures. They’re missing rules. The code does exactly what it was prompted to do and nothing more. The problem is that real users, and real attackers, don’t follow the intended path. Across every category in this piece, the pattern is the same: the failure is rarely in what the AI generated. It’s in what nobody thought to ask for.

What to audit internally: Walk your critical user flows with the assumption that every step is independently accessible. If your business logic lives only in the UI or in documented user journeys, it’s not enforced.


Authorization Assumptions

This is the category I find most consistently damaging. AI-generated code tends to implement authentication reasonably well and authorization poorly.

The distinction matters. Authentication answers “who are you?” Authorization answers “what are you allowed to do?” Verifying a valid session token and verifying that the requesting user has permission to act on a specific resource are different checks. In AI-generated codebases, the second check is often missing, partial, or present in some endpoints and absent in others.

The result is predictable: authenticated users accessing records that belong to other users, lower-privilege accounts triggering admin-only functions, actions that the application front-end restricts but the underlying API does not.

AI tools learn authorization patterns from training data. But authorization is inherently contextual, it depends on your data model, your permission structure, your business rules. A model generating plausible-looking code can’t know what it doesn’t know about your system.

I’ve seen this play out directly. One system I tested had an authentication layer built on JSON Web Tokens, a common, reliable choice. The token itself was basic, holding user identity and a handful of claims, nothing unusual. But the actual authorization check, the piece that decides whether the logged-in user is allowed to perform the specific action they’re requesting, relied on a separate mechanism entirely. And when that mechanism was unreachable, the application defaulted to allowing the action. Any authenticated user could act as a full admin simply by having a valid login and hitting the system at the right moment.

Asking an AI tool to build JWT-based authentication is a well-scoped, well-represented prompt. Asking it to also wire those tokens into every authorization decision, and to fail closed when the authorization check can’t complete, is a different and much easier thing to leave out. Nobody wrote broken code here. A necessary piece was simply never specified.

What to audit internally: For every API endpoint, ask whether the server independently verifies that the authenticated user is permitted to act on the specific resource being requested. Not just that they’re logged in, that they can touch that object.


Input Validation Patterns

Input validation failures in AI-generated code present differently than in traditional hand-written code. The issue isn’t complete absence of validation, it’s inconsistency.

AI generators apply validation where they’ve seen it modeled in similar contexts. A field that looks like an email gets validated like an email. A field that’s novel, internal, or less common in training data often gets no validation at all. The result is a codebase where some inputs are well-defended and others are completely open, and the distribution is unpredictable without systematic review.

The more consequential pattern: server-side validation that was correctly implemented, then regenerated or modified in a later prompt without preserving the original controls. Each generation pass is stateless. It doesn’t carry memory of what was there before.

What to audit internally: Validate that every input reaching your server is validated on the server. Client-side validation is a user experience feature, not a security control.


Error Handling Failures

Poorly handled errors are a reliable source of information for anyone mapping a system’s internals. Stack traces, internal paths, database identifiers, and configuration details have no business appearing in responses to end users, and in AI-generated codebases, they appear with notable frequency.

The pattern I see: error handling is added for expected failure cases and omitted for unexpected ones. The paths a developer thought about are covered. The edge conditions are not. AI-generated code will often handle the nominal failure gracefully and bubble raw exceptions for anything outside that envelope.

Verbose errors don’t compromise a system on their own. They accelerate everything else. They confirm whether an injection attempt landed. They expose internal structure that makes subsequent steps faster. In a well-tested system, this information is withheld by design, not as an afterthought.

What to audit internally: Review what your application returns on unexpected errors across every endpoint. If the answer is “it depends on the exception,” that’s worth closing before an assessment.


A Note on Pattern vs. Cause

None of what’s described here is unique to AI-generated code in isolation. Business logic gaps, broken object-level authorization, inconsistent input validation, and verbose error handling all appeared in codebases long before AI tools existed.

What changes with AI-assisted development is the distribution of these issues. Code can be generated, modified, and shipped faster than security review has traditionally operated. The volume increases. The patterns stay the same.

When I test these systems, I’m not looking for AI-specific vulnerabilities. I’m applying the same methodology I’d apply anywhere. The difference is that the categories above show up with higher density and less internal consistency than codebases built through slower, more iterative human review.

Part of that is pace, and part of it is who’s holding the pen. As teams lean more heavily on AI tools and shift toward less experienced developers who’ve never had to write these checks by hand, the muscle memory for secure-by-default patterns, like failing closed when an authorization check can’t complete, is easy to skip. That’s not a knock on newer developers. It’s a gap in what the tooling and the team’s review process catch together.

The practical implication: if your team is using AI tools to accelerate delivery, your security review cadence needs to match that pace. An annual penetration test designed for slower release cycles underserves a codebase that’s regenerating significant functionality every quarter.


If you’re shipping AI-assisted code into a production environment and want to understand where the real exposure is, that’s a conversation worth having before testing begins, not after. Reach out to EliteSec and I can talk through what an engagement scoped to your environment would look like.

Explore Our Penetration Testing Services

Certified testing with five free re‑tests

View Penetration Testing

Curious how EliteSec stacks up against the competition? See our comparison with large consulting firms.

Related Posts