Auth Bypass: Top Vulnerability in Web Apps
NeuroStrike Research
Security Research Team
Across 300+ penetration tests in the past year, authentication bypass has been the most common critical finding. Not injection. Not XSS. Auth bypass. It accounts for 34% of all critical-severity vulnerabilities in our dataset, and it's the most likely path to full account takeover.
Most of these aren't exotic attacks. They're logical errors — the kind that happen when developers implement auth from tutorials, trust framework defaults, or let AI generate the flow.
Pattern 1: JWT None Algorithm
The classic. Despite being a known issue since 2015, we still find applications that accept JWTs with the "none" algorithm. This lets an attacker forge any token without knowing the signing key.
// Forged JWT — no signature needed
// Header: { "alg": "none", "typ": "JWT" }
// Payload: { "sub": "admin", "role": "admin" }
// Signature: (empty)
const forgedToken = btoa('{"alg":"none","typ":"JWT"}') + '.' +
btoa('{"sub":"admin","role":"admin"}') + '.';The fix: always specify the expected algorithm when verifying tokens.
// Fixed: explicit algorithm whitelist
import jwt from "jsonwebtoken";
const decoded = jwt.verify(token, publicKey, {
algorithms: ["RS256"], // Only accept RS256
});Find what scanners miss
NeuroStrike runs autonomous breach simulations that go beyond checkbox security testing.
Start FreePattern 2: Password Reset Token Reuse
68% of applications in our dataset allow password reset tokens to be used multiple times. An attacker who intercepts or brute-forces a reset token can use it hours or days later, even after the user has already reset their password.
The fix: invalidate the token immediately after first use and enforce a short expiration (15-30 minutes).
Pattern 3: OAuth State Parameter Missing
OAuth 2.0 requires a state parameter to prevent CSRF attacks during the authorization flow. We find it missing or static in 41% of OAuth implementations. Without it, an attacker can trick a user into linking the attacker's OAuth account to the victim's session.
// Vulnerable: no state parameter
const authUrl = `https://accounts.google.com/o/oauth2/auth?
client_id=${CLIENT_ID}&
redirect_uri=${REDIRECT_URI}&
response_type=code&
scope=email profile`;// Fixed: generate and validate state
import { randomBytes } from "crypto";
const state = randomBytes(32).toString("hex");
await redis.set(`oauth:state:${state}`, session.userId, { ex: 600 });
const authUrl = `https://accounts.google.com/o/oauth2/auth?
client_id=${CLIENT_ID}&
redirect_uri=${REDIRECT_URI}&
response_type=code&
scope=email profile&
state=${state}`;Find what scanners miss
NeuroStrike runs autonomous breach simulations that go beyond checkbox security testing.
Start FreePattern 4: Session Fixation After Login
The application assigns a session token before authentication and doesn't rotate it after successful login. An attacker sets a known session ID (via a XSS, a URL parameter, or a subdomain cookie) and waits for the victim to log in. The attacker's known session is now authenticated.
Every auth library handles this differently. NextAuth v5 rotates sessions correctly by default. Express-session does not — you must call req.session.regenerate() manually after login.
Pattern 5: Email Verification Bypass
23% of applications allow unverified accounts to access protected features. The email verification check exists on the frontend (showing a "verify your email" banner) but the API doesn't enforce it. An attacker can register with any email and immediately access the application.
// Vulnerable: only checks on the frontend
// Server-side: no verification check
export async function getProtectedData(userId: string) {
return db.data.findMany({ where: { userId } });
}// Fixed: server-side verification check
export async function getProtectedData(userId: string) {
const user = await db.user.findUnique({ where: { id: userId } });
if (!user?.emailVerified) {
throw new TRPCError({ code: "FORBIDDEN", message: "Email not verified" });
}
return db.data.findMany({ where: { userId } });
}Pattern 6: Rate Limiting Absence on OTP/2FA
OTP codes are typically 6 digits — one million possibilities. Without rate limiting, an attacker can brute-force the code in minutes. We find missing rate limits on 2FA verification in 78% of applications that implement TOTP or email-based OTP.
The fix: limit to 5 attempts per code, lock the account after 10 consecutive failures across codes, and implement exponential backoff.
Why Auth Bypass Is So Common
Authentication is complex state management across multiple flows: registration, login, password reset, OAuth, 2FA, session management, and account recovery. Each flow has its own security requirements, and a mistake in any one creates a bypass path. Frameworks handle the common case well, but every application has at least one custom auth flow where the developer made a logical error.
The best auth is the auth you don't write. Use a managed service (Clerk, Auth0, Supabase Auth) or a well-tested library (NextAuth, Lucia). When you must customize, test every flow adversarially.
Automated testing for auth bypass requires multi-session testing: the scanner needs to understand the auth flow well enough to create accounts, log in, and test the boundaries between them. This is the core capability we built into NeuroStrike's agent — it reasons about auth as a system, not just individual endpoints.
Find what scanners miss
NeuroStrike runs autonomous breach simulations that go beyond checkbox security testing.
Start Free