v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.nextauth.hardcoded-secret

The NextAuth/Auth.js secret is set to a hard-coded string literal.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

This value signs and encrypts every session JWT and CSRF token. Committed to git it is one search away from compromise, letting an attacker forge sessions for any user. Read it from the environment instead: secret: process.env.AUTH_SECRET (or NEXTAUTH_SECRET) and add the variable to .env.example with a placeholder.

VULNERABLE
vulnerable.ts
import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import type { NextAuthConfig } from 'next-auth';

// ruleid: auth.nextauth.hardcoded-secret
const { handlers } = NextAuth({
  providers: [Credentials({})],
  secret: 'sk_live_8f3kd92jfh38dPq0aabbccddeeff',
});

// ruleid: auth.nextauth.hardcoded-secret
export const authOptions = {
  providers: [Credentials({})],
  secret: 'hunter2-super-secret-signing-key-zzzz',
};

// ruleid: auth.nextauth.hardcoded-secret
const authConfig: NextAuthConfig = {
  providers: [],
  secret: 'aGVsbG8td29ybGQtc2lnbmluZy1zZWNyZXQ=',
};

// ruleid: auth.nextauth.hardcoded-secret
export default NextAuth(req, res, {
  providers: [],
  secret: 'pages-router-hardcoded-secret-value-9',
});
SAFE
safe.ts
import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import type { NextAuthConfig } from 'next-auth';

// ok: auth.nextauth.hardcoded-secret -- read from the environment
const { handlers } = NextAuth({
  providers: [Credentials({})],
  secret: process.env.AUTH_SECRET,
});

// ok: auth.nextauth.hardcoded-secret -- legacy env var name, still safe
export const authOptions = {
  providers: [Credentials({})],
  secret: process.env.NEXTAUTH_SECRET,
};

// ok: auth.nextauth.hardcoded-secret -- documentation placeholder, not a real leak
const authConfig: NextAuthConfig = {
  providers: [],
  secret: 'your-auth-secret-here',
};

// ok: auth.nextauth.hardcoded-secret -- unrelated object, not a NextAuth config
const telemetry = {
  secret: 'this-is-not-an-auth-config-at-all',
};

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.nextauth.hardcoded-secret -- <reason>

References

https://authjs.dev/getting-started/deployment#auth_secret ↗https://cwe.mitre.org/data/definitions/798.html ↗