highExposed Secrets

JWT Signing Secret Hardcoded in Application Source

What Is This Vulnerability?

The secret key used to sign and verify JSON Web Tokens (JWTs) is written directly into the source code. An attacker who obtains this secret can forge valid tokens, impersonate any user, escalate privileges to admin, and bypass all authentication and authorization controls in the application.

Why It Happens

JWT libraries require a secret or key for signing, and tutorials often show inline string examples. Developers copy these patterns and never refactor them to use environment variables. In some cases, the same secret string (like 'secret' or 'jwt-secret') is used across all environments.

Example Code

Vulnerableauth.ts
import jwt from "jsonwebtoken";

const JWT_SECRET = "my-super-secret-jwt-key-2024";

export function generateToken(userId: string, role: string) {
  return jwt.sign({ userId, role }, JWT_SECRET, { expiresIn: "24h" });
}

export function verifyToken(token: string) {
  return jwt.verify(token, JWT_SECRET);
}
Fixedauth.ts
import jwt from "jsonwebtoken";

const JWT_SECRET = process.env.JWT_SECRET;

export function generateToken(userId: string, role: string) {
  if (!JWT_SECRET) {
    throw new Error("JWT_SECRET environment variable must be set");
  }
  return jwt.sign({ userId, role }, JWT_SECRET, { expiresIn: "24h" });
}

export function verifyToken(token: string) {
  if (!JWT_SECRET) {
    throw new Error("JWT_SECRET environment variable must be set");
  }
  return jwt.verify(token, JWT_SECRET);
}

How Hackers Exploit It

With the JWT secret, an attacker can craft tokens with arbitrary claims, such as setting their role to admin or impersonating another user. They can also modify the expiration time to create tokens that never expire. Since the server trusts any token signed with the correct secret, forged tokens are indistinguishable from legitimate ones.

How to Fix It

Move the JWT secret to an environment variable and ensure it is a long, randomly generated string (at least 256 bits of entropy). Consider using asymmetric signing (RS256) with a private key stored in a secrets manager and a public key for verification. Rotate the secret periodically and implement token revocation for compromised sessions.

Frequently Asked Questions

What happens if my JWT secret is leaked?
An attacker can create valid tokens for any user, including admins. They can bypass all authentication, access any account, and perform any action the application allows. You must rotate the secret immediately, which will invalidate all existing tokens and force users to re-authenticate.
Should I use symmetric or asymmetric JWT signing?
Asymmetric signing (RS256 or ES256) is more secure for distributed systems because only the authentication server holds the private key, while other services use the public key to verify tokens. Symmetric signing (HS256) is simpler but requires every service that verifies tokens to have the same secret.
How long should my JWT secret be?
For HS256, use at least a 256-bit (32-byte) random string. For HS384 and HS512, match the key length to the hash output (48 and 64 bytes respectively). Generate secrets with a cryptographically secure random generator, not a human-chosen passphrase.

Related Security Topics

Check Your Code for This Vulnerability

Run a free scan to check if your site is affected by jwt signing secret hardcoded in application source.