Blog

Security review checklist for PRs touching authentication

Alex Mercer

Mar 5, 2026

Why authentication PRs require specialized security scrutiny, and how automated code review tools catch what manual reviews miss

The authentication code is the gateway to your entire system. A single overlooked vulnerability in a login flow, session handler, or token validator can compromise every user account in your application. Yet teams routinely ship authentication changes with the same review process they use for UI tweaks or database migrations.

The data tells an astonishing story. Authentication Failures rank #7 in OWASP Top 10 2025, spanning 36 Common Weakness Enumerations. In 2024 alone, over 500,000 Roku accounts were compromised through credential stuffing, Australian Super members lost AUD $500,000 to auth attacks, and even Norton's password manager was breached through credential-based vulnerabilities.

PRs that touch authentication deserve a closer look. This checklist provides the security controls that secure code review must enforce when authentication code changes.

TLDR

  • Authentication vulnerabilities in PRs often go unnoticed because reviewers focus on functionality rather than security edge cases. 

  • Critical issues include JWT signature bypass, session fixation, hardcoded credentials, improper token validation, and weak password policies. 

  • Code review automation platforms with continuous codebase scanning catch these vulnerabilities by analyzing authentication flows across your entire repository, not just the changed lines. 

  • Teams using AI-powered code review tools report finding 3-5x more authentication bugs before production compared to manual review alone.

Session management: The foundation

A general code review checklist is helpful, but authentication changes require more focused security checks, starting with how you handle sessions. Session tokens are the keys to your system. Get them wrong, and attackers can hijack user accounts.

Token generation requirements:

OWASP Session Management guidelines specify that session tokens must use cryptographically secure random generators with at least 64 bits of entropy (128+ recommended in modern systems). Here's what vulnerable token generation looks like:

// VULNERABLE: Predictable session ID

function generateSessionId() {

  return `sess_${Date.now()}_${Math.random()}`;

}



// SECURE: Cryptographically random with sufficient entropy

const crypto = require('crypto');

function generateSessionId() {

  return crypto.randomBytes(32).toString('hex'); // 256 bits entropy

}


The vulnerable version uses Date.now() (predictable timestamps) and Math.random() (not cryptographically secure). Attackers can predict or brute-force these tokens. The secure version uses crypto.randomBytes(), providing 256 bits of entropy - far exceeding the 64-bit minimum.

Session fixation prevention:

CWE-384 Session Fixation occurs when applications don't regenerate session IDs after authentication. Check for this pattern in authentication PRs:

// VULNERABLE: Reuses pre-login session ID

app.post('/login', (req, res) => {

  const user = authenticateUser(req.body);

  if (user) {

    req.session.userId = user.id; // Session ID unchanged!

    res.json({ success: true });

  }

});



// SECURE: Regenerates session post-login

app.post('/login', (req, res) => {

  const user = authenticateUser(req.body);

  if (user) {

    req.session.regenerate((err) => {

      req.session.userId = user.id;

      res.json({ success: true });

    });

  }

});

Cookie security attributes:

Every authentication cookie must include Secure, HttpOnly, and SameSite=Strict flags. Secure code review checklists emphasize these as non-negotiable:

// VULNERABLE: Missing security flags

res.cookie('session', sessionId);



// SECURE: All security attributes present

res.cookie('session', sessionId, {

  httpOnly: true,      // Prevents XSS from reading token

  secure: true,        // HTTPS only

  sameSite: 'strict',  // Prevents CSRF

  maxAge: 7200000      // 2 hour absolute timeout

});


JWT vulnerabilities: What to check

JSON Web Tokens power authentication in modern APIs, but JWT vulnerabilities are pervasive. Six critical CVEs targeting JWT libraries were disclosed in 2025 alone, affecting cloud platforms and enterprise systems.

Algorithm confusion and "none" bypass:

The most dangerous JWT vulnerability is accepting the "none" algorithm, which disables signature verification entirely. OWASP JWT Testing Guide documents this attack:

// VULNERABLE: Doesn't specify expected algorithms

const decoded = jwt.verify(token, secret);



// SECURE: Explicitly whitelists algorithms

const decoded = jwt.verify(token, secret, {

  algorithms: ['HS256', 'RS256'] // Rejects "none"

});


Signature validation bypass:

Developers sometimes use jwt.decode() instead of jwt.verify(), completely bypassing signature validation:

// CRITICAL VULNERABILITY: No signature verification

const payload = jwt.decode(token); // Just base64 decodes!

if (payload.userId) {

  // Attacker can forge any user ID

}



// SECURE: Verifies signature before trusting payload

try {

  const payload = jwt.verify(token, SECRET_KEY);

  if (payload.userId) {

    // Token cryptographically verified

  }

} catch (err) {

  // Invalid signature rejected

}

This exact bug enabled a B2B SaaS breach where attackers modified JWT payloads to access other users' data for four months before discovery.

Token expiration and claims validation:

JWTs must validate iat (issued-at), nbf (not-before), and exp (expiration) claims:

// VULNERABLE: No expiration enforcement

const payload = jwt.verify(token, secret);

// Old tokens work forever



// SECURE: Enforces expiration + reasonable lifetime

const payload = jwt.verify(token, secret, {

  maxAge: '2h', // Tokens expire after 2 hours

  clockTolerance: 30 // 30 second clock skew tolerance

});



// Verify claims explicitly

if (!payload.exp || payload.exp < Date.now() / 1000) {

  throw new Error('Token expired');

}


Password and credential security

CWE-798 Use of Hard-coded Credentials and CWE-259 Use of Hard-coded Password are among the 36 CWEs mapped to Authentication Failures.

Hardcoded secrets detection:

# CRITICAL: Hardcoded API key

API_KEY = "sk_live_4eC39HqLyjWDarjtT1zdp7dc"



# CRITICAL: Hardcoded database password

db = psycopg2.connect(

    host="db.prod.com",

    password="SuperSecret123!"

)



# SECURE: Environment variables

import os

API_KEY = os.getenv('API_KEY')

db = psycopg2.connect(

    host=os.getenv('DB_HOST'),

    password=os.getenv('DB_PASSWORD')

)


Code review platforms with secrets detection capabilities scan for these patterns automatically. 

cubic's codebase scans go further; they trace how credentials flow through your entire codebase, catching cases where secrets are passed through multiple files before being used insecurely.

Password hashing standards:

Never use deprecated algorithms. OWASP 2025 Cryptographic Failures (A04) explicitly disallows MD5, SHA-1, DES, 3DES, and RC4:

// VULNERABLE: Weak hashing

const hash = crypto.createHash('md5')

  .update(password).digest('hex');



// SECURE: bcrypt with appropriate cost

const bcrypt = require('bcrypt');

const hash = await bcrypt.hash(password, 12); // Cost factor 12

Authorization bypass patterns

Authentication handles who you are. Authorization handles what you can do. PRs touching auth often conflate these.

Missing ownership checks:

// VULNERABLE: No ownership verification

app.delete('/api/documents/:id', authenticateUser, async (req, res) => {

  await db.documents.delete(req.params.id);

  // Any authenticated user can delete ANY document!

});



// SECURE: Verifies ownership before action

app.delete('/api/documents/:id', authenticateUser, async (req, res) => {

  const doc = await db. documents.findOne({

    id: req.params.id,

    ownerId: req.user.id // Ownership check

  });

  if (!doc) return res.status(404).send('Not found');

  await db.documents.delete(req.params.id);

});


This is where AI-based coding analysis excels. Automated code review tools trace data flows across your entire repository, identifying where user input (like req.params.id) reaches sensitive operations without authorization checks.

What continuous codebase scanning catches

Manual PR review examines changed lines. But authentication vulnerabilities often exist in unchanged code that interacts with new changes. This is where continuous scanning becomes critical.

cubic's codebase scans run thousands of AI agents continuously across your full repository, finding:

  • Cross-file auth bypasses: Where a new API endpoint lacks authentication middleware that other endpoints use

  • Inconsistent token validation: Where some routes verify JWTs correctly, while others use vulnerable patterns

  • Session management drift: Where new code introduces different session handling than established patterns

In their OpenClaw security audit, cubic's continuous scanning found four critical authentication vulnerabilities, including an allowlist bypass and credential fallback logic that was too permissive, business logic errors that looked reasonable in isolation but broke under security scrutiny.

The difference between PR review and continuous scanning:

PR review: "Does this new login endpoint hash passwords correctly?"

Continuous scanning: "This new endpoint uses bcrypt cost 10, but your 47 other endpoints use cost 12. Also, three endpoints in /admin routes lack the requireAdmin middleware that all other admin routes use."

Implementing an authentication security checklist

For every PR touching authentication:

  1. Session tokens: 64+ bits entropy, regenerated post-login, secure cookie flags

  2. JWT validation: Explicit algorithm whitelist, signature verification, expiration enforcement

  3. Credentials: No hardcoded secrets, approved hashing algorithms (bcrypt ≥12, Argon2)

  4. Authorization: Ownership checks on all data access, role verification on privileged operations

  5. Cross-file consistency: New code follows established patterns across the repository

Manual review catches points 1-4 if reviewers remember to check. AI for code review catches point 5 automatically by analyzing your entire codebase for pattern violations.

The authentication security gap

Authentication vulnerabilities rank #7 in OWASP's top threats because they're simultaneously common and catastrophic. A single unvalidated JWT or a missing ownership check can compromise your entire user base.

Manual code review struggles with authentication security because reviewers must remember dozens of security rules while also evaluating functionality, performance, and maintainability. Critical checks get missed under deadline pressure.

Code review automation solves this by encoding security knowledge into specialized agents that never forget to check. These systems analyze authentication flows across your entire repository, catching vulnerabilities that only emerge from how multiple files interact.

Teams serious about authentication security use both manual review (for business logic and design decisions) and automated code review tools (for systematic security verification). The combination catches 3-5x more authentication bugs before production than either approach alone.

Ready to scan your authentication code for vulnerabilities?

Book a demo to see how continuous codebase scanning finds authentication bugs that PR reviews miss.

Table of contents