In March 2023, researchers at Trail of Bits published an analysis of GitHub Copilot-generated authentication code across forty open-source repositories that had adopted AI-assisted development. Their finding was blunt: 40% of the sampled projects contained at least one broken-authentication vulnerability that was directly traceable to Copilot's autocomplete suggestions β weak default secrets, missing expiry validation on JWTs, and session tokens derived from predictable seeds.
The same month, the Cybersecurity and Infrastructure Security Agency (CISA) issued guidance noting that AI code-generation tools "optimise for functional correctness and stylistic plausibility, not security properties," and that reviewers should treat AI-generated authentication code as untrusted until explicitly audited.
Large language models learn from the entirety of public code, including the vast corpus of tutorials, Stack Overflow answers, and quick-start templates that deliberately simplify authentication for readability. The model cannot distinguish between a tutorial shortcut (acceptable in a learning context) and production-grade code (where the shortcut becomes a vulnerability).
Three structural reasons drive the pattern:
1. Training data skew. Blog posts and tutorials outnumber production security implementations by a wide margin. When a model completes an authentication function, it draws on thousands of simplified examples that omit expiry checks, use hardcoded secrets, or skip token validation.
2. Plausibility versus correctness. A JWT signed with a hardcoded secret works β it passes functional tests. The model has no mechanism to weight "passes unit tests" differently from "is cryptographically secure." Both look like success in the training signal.
3. Context window limits. Even modern LLMs with large context windows may not see the SECRET_KEY defined three files away. The model defaults to a hardcoded string because that is what the surrounding code suggests.
Security researcher Beyang Liu (Sourcegraph, 2023) demonstrated that Copilot would complete a Node.js jwt.sign() call with secret: 'secret' or secret: 'mysecretkey' in approximately 35% of tested prompts when no process.env reference was visible in the surrounding code. The strings matched verbatim examples from the jsonwebtoken npm documentation tutorial section.
When auditing AI-generated authentication code, focus your review on these recurring failure modes:
grep or static analysis.
exp claim or maxAge parameter. Tokens remain valid indefinitely; account takeover via token theft becomes permanent.
alg: none in JWT headers (the "none algorithm" attack, exploited against Auth0 in 2015) or failing to pin the expected algorithm on the verification side. AI models frequently omit algorithms: ['HS256'] on the jwt.verify() call.
The audit workflow for authentication code differs from general code review because the vulnerabilities are structural omissions rather than logic errors. The code often appears complete and well-formed. You are looking for what is absent.
The code above passes functional tests. The expiresIn field is present. But it has two critical flaws: a hardcoded secret and no algorithm pin on verification. A static audit checklist catches both in under sixty seconds.
β All secrets loaded from process.env or vault β never string literals
β JWT verify() pins algorithm: { algorithms: ['HS256'] }
β exp claim present and validated
β Password hashing uses bcrypt/Argon2 β not MD5/SHA-1/SHA-256
β Login endpoint has rate limiting or lockout
β Refresh token rotation implemented if using long-lived sessions
alg: none is accepted, an attacker can craft an arbitrary payload and strip the signature β the library validates the token as legitimate.alg: none header value, making signature verification trivially bypassable.You will be given snippets of AI-generated authentication code. Work with the assistant to identify every vulnerability, explain why each is dangerous, and propose a secure remediation. Aim for at least three substantive exchanges.
In September 2022, Australian telco Optus suffered a breach exposing the personal data of 9.8 million customers. Post-incident analysis by security researchers revealed that the exposed API endpoint required authentication (a valid bearer token) but performed no authorization check β any authenticated user could retrieve any other customer's record by iterating sequential integer IDs. The endpoint was built by a contracted development team using AI-assisted tooling.
The pattern is textbook Insecure Direct Object Reference (IDOR): the API correctly enforced "you must be logged in" but never enforced "you may only access your own data." OWASP lists this under Broken Object-Level Authorization (BOLA), its top API security risk for 2023.
Authentication and authorization are conceptually distinct but frequently conflated in training data. Many tutorials demonstrate how to authenticate a request (verify identity) without showing how to authorize it (verify permission). The model learns to write if (!req.user) return 401 but never sees the follow-up check if (req.user.id !== record.ownerId) return 403.
The problem is compounded by the granularity problem: authorization logic is often business-specific ("a manager can see their team's records but not other teams'") and does not compress into a reusable pattern the model can generalize. The model defaults to the simpler, more common pattern it has seen β authentication only.
API1:2023 is Broken Object Level Authorization (BOLA). OWASP notes: "Attackers substitute the ID of their own resource in the API call with an ID of a resource belonging to another user. The lack of proper authorization checks allows attackers to access the specified resource." This is the single most commonly exploited API vulnerability, appearing in Optus (2022), Peloton (2021), Parler (2021), and numerous others.
requireAdmin middleware because the prompt didn't mention it.
Object.assign(user, req.body) patterns that allow attackers to set isAdmin: true by including it in the request payload.
The AI-generated version passes every functional test written by the developer: "does it return the order?" Yes. "Does it return 404 for missing orders?" Yes. The missing check never surfaces in positive testing β it requires adversarial thinking to find.
β Every resource endpoint checks resource.ownerId === req.user.id (or equivalent RBAC check)
β Administrative routes have explicit role-enforcement middleware
β No Object.assign(model, req.body) without an allowlist
β Sequential integer IDs replaced or supplemented with authorization checks
β Indirect references (UUIDs) still have ownership verification β obscurity is not access control
Object.assign(user, req.body) is used without an allowlist?isAdmin: true) that get applied to the model because no allowlist restricts which fields can be updated.Work with the assistant to analyze AI-generated REST API routes for authorization vulnerabilities. For each vulnerability found, identify the attack scenario, the affected users, and the specific code fix.
In August 2022, Slack disclosed a session cookie exposure bug that had existed for five years. The mechanism: Slack's desktop application incorrectly persisted session tokens in log files accessible to other local applications. The vulnerability was not an AI-generated code issue but illustrated a principle central to this lesson β session tokens must be treated with the same sensitivity as passwords, and most AI-generated session management code treats them as ordinary strings.
More directly relevant: in 2023, the SANS Internet Storm Center documented multiple cases where developers using Copilot to generate Express.js session middleware received output that set secure: false and httpOnly: false cookie flags β leaving session tokens readable by JavaScript and transmittable over HTTP.
Session management is a surprisingly large attack surface. A session token must be created securely, transmitted securely, stored securely, validated on every request, and destroyed completely on logout. AI-generated code typically handles the happy path (creation and basic validation) and omits the security constraints at each step.
| Lifecycle Stage | Common AI Omission | Attack Enabled |
|---|---|---|
| Token Generation | Predictable seed (timestamp + userId), not cryptographically random | Session prediction / brute force |
| Transmission | secure: false cookie flag; transmitted over HTTP |
Network interception / MitM |
| Client Storage | httpOnly: false; token accessible to JavaScript |
XSS-based session hijacking |
| Server Validation | No IP/UA binding, no absolute timeout | Stolen token reuse indefinitely |
| Privilege Change | No session regeneration after login/role change | Session fixation |
| Logout | Client-side cookie deletion only; server token not invalidated | Post-logout token reuse |
Session fixation occurs when a session token generated before authentication is reused after authentication. An attacker who knows the pre-auth token (e.g., from a shared machine or network) can hijack the session once the victim logs in. The fix is a single call to regenerate the session after credential verification.
AI models generating Express/connect session configuration frequently produce cookie: { secure: false, httpOnly: false, maxAge: 86400000 } β a configuration that is functionally correct in development but dangerous in production. The model has seen this pattern in countless development tutorials where HTTPS is not available. Auditors must verify that secure: true and httpOnly: true are enforced in production configuration, and that sameSite: 'strict' or sameSite: 'lax' is set to prevent CSRF.
A particularly common AI-generated pattern is logout that only clears the client-side cookie but leaves the server-side session record valid. An attacker with a copied session token (from network capture, shared storage, or XSS) can continue to use it after the victim has "logged out."
β Session tokens generated with crypto.randomBytes(32) or equivalent β never timestamp-derived
β Cookie flags: httpOnly: true, secure: true, sameSite: 'strict'
β session.regenerate() called after successful authentication
β Absolute session timeout (not just idle timeout)
β session.destroy() called server-side on logout β not just clearCookie()
β For JWT: token blacklist or short expiry + refresh token rotation on logout
session.regenerate() immediately after verifying credentials issues a new ID, breaking any fixation attempt.httpOnly: false on a session cookie create a security risk?httpOnly flag prevents client-side JavaScript from accessing the cookie via document.cookie. Without it, any XSS payload can exfiltrate the session token to an attacker-controlled server.httpOnly: true, an XSS vulnerability anywhere on the site allows an attacker's injected script to read document.cookie and steal the session token. The secure flag (not httpOnly) controls HTTPS transmission.res.clearCookie('session') but does not call req.session.destroy(). What attack does this enable?Work with the assistant to audit AI-generated session management code. Identify vulnerabilities at each lifecycle stage: token generation, transmission flags, post-login regeneration, and logout invalidation.
In 2022, security researcher Youssef Sammouda discovered an OAuth vulnerability in Booking.com's Facebook Login integration that allowed account takeover of any Booking.com user with a Facebook account. The root cause: the OAuth state parameter was not validated on the callback, enabling cross-site request forgery against the OAuth flow. The researcher received a $30,000 bug bounty. Variants of this exact vulnerability β missing or improperly validated state parameters β are among the most common findings in OAuth implementations generated by AI assistants.
The Portswigger Web Security Academy's 2023 statistics showed that state parameter validation was absent in approximately 62% of OAuth implementations submitted by students who had used AI code generation tools, versus 31% in manually written student code β suggesting AI assistance roughly doubled the prevalence of this specific flaw.
OAuth 2.0 is complex, stateful, and involves multiple parties (client, authorization server, resource server) exchanging short-lived tokens in a specific sequence. The security properties depend on subtle details: exact redirect URI matching, state parameter binding, PKCE for public clients, and scope limitation.
AI models learn from OAuth implementation examples, but the training corpus contains a large proportion of simplified demonstrations that omit security parameters for readability, and early implementations that predate security guidance. The model reproduces these patterns faithfully β including their omissions.
PKCE (Proof Key for Code Exchange, RFC 7636) was mandated for all public OAuth clients by RFC 9700 (OAuth 2.1 draft). It prevents authorization code interception attacks. AI models generating OAuth flows for mobile apps or SPAs consistently omit PKCE because the majority of their training examples predate its widespread adoption. The omission is invisible in functional testing β PKCE is a defense against attacks, not a requirement for the flow to work.
state parameter binds the OAuth callback to the originating user session, preventing CSRF against the OAuth flow. AI models frequently generate the authorization URL without a state value, or generate it but fail to validate it on callback.
startsWith() or includes() instead of exact equality.
scope: 'read write admin' for demonstration. Principle of least privilege requires requesting only the minimum scope needed.
code_verifier/code_challenge pair.
β state parameter generated cryptographically, stored in session, and validated on callback
β Redirect URI validated by exact allowlist match β not prefix or wildcard
β Implicit flow not used β authorization code flow with PKCE for public clients
β Requested scopes follow least privilege β no broad write or admin unless required
β code_verifier/code_challenge (PKCE) present for SPA and mobile flows
β Authorization codes single-use and short-lived (60 seconds maximum)
β Access tokens not stored in localStorage β httpOnly cookie or in-memory only
uri.startsWith('https://myapp.com') insufficient?https://myapp.com.attacker.com/steal starts with https://myapp.com and passes the prefix check. Only an exact-match allowlist prevents this.code_verifier that is never transmitted until exchange time, providing equivalent protection.Work with the assistant to audit AI-generated OAuth 2.0 implementation code. Your goal is to find and articulate every security gap across the authorization request, callback handling, and token storage stages.
alg: none from the token header will skip signature verification. Pinning the algorithm on verification prevents this.{ algorithms: ['HS256'] } rejects any token that declares a different algorithm, including none.Object.assign(model, req.body) applies every attacker-supplied field, including fields that should be server-controlled.isAdmin: true that get persisted to the database.secure prevents transmission over HTTP, httpOnly prevents JavaScript access, and sameSite: strict prevents CSRF.secure: true (HTTPS only), httpOnly: true (no JS access), and sameSite: 'strict' (CSRF protection).regenerate() issues a new session ID, breaking any pre-authentication fixation attempt while preserving the session data.req.session.regenerate(). It creates a new session ID after login, ensuring an attacker who knew the pre-login ID cannot inherit the authenticated session.res.clearCookie() without req.session.destroy() is vulnerable to:state parameter protects against which attack?