Registry
Ccodemod avatar

codemod/secure-jwt-secret-keys

Identifies hardcoded JWT signing secrets in jsonwebtoken.sign() calls and replaces with env vars

codemod0 executions

  • security
  • jwt
  • jsonwebtoken
  • hardcoded-credentials
  • environment-variables
Connect a repo
npx codemod @codemod/secure-jwt-secret-keys

@codemod/secure-jwt-secret-keys

Hardcoded JWT secret keys in jsonwebtoken.sign() calls pose a critical security vulnerability. When JWT signing secrets are embedded directly in source code, they can be exposed through version control, logs, or other means, allowing attackers to forge authentication tokens and completely bypass application security.

This codemod identifies hardcoded secrets and replaces them with secure environment variable references.

🚨 Security Issue

CWE-798: Use of Hard-coded Credentials

Hardcoded JWT secrets allow attackers to:

  • Forge authentication tokens
  • Bypass application security
  • Impersonate users
  • Access unauthorized resources

What it does

This codemod automatically transforms hardcoded JWT secrets to use environment variables:

Before

javascript
import jwt from 'jsonwebtoken';

// ❌ Hardcoded secret - security vulnerability
const token = jwt.sign(payload, 'my-super-secret-key', { expiresIn: '1h' });

After

javascript
import jwt from 'jsonwebtoken';

// ✅ Uses environment variable - secure
const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });

Supported patterns

The codemod handles all common JWT signing patterns:

  • Default imports: jwt.sign()
  • Named imports: sign() from { sign }
  • Namespace imports: jsonwebtoken.sign()
  • CommonJS: require('jsonwebtoken')
  • String literals: 'secret' and "secret"
  • Template literals: `secret-${env}`

Installation

bash
# Run directly (recommended)
npx codemod@latest run @codemod/secure-jwt-secret-keys

# Or install globally
npm install -g @codemod/secure-jwt-secret-keys
codemod run @codemod/secure-jwt-secret-keys

Usage

The codemod will scan your JavaScript/TypeScript files and:

  1. Detect hardcoded secrets in jwt.sign() calls
  2. Transform them to use process.env.JWT_SECRET
  3. Preserve all other function parameters and formatting
  4. Skip files that don't use jsonwebtoken

What gets transformed

✅ Will transform:

javascript
jwt.sign(payload, 'hardcoded-secret')
jsonwebtoken.sign(data, "my-secret-key", options)
sign(user, `secret-${env}-key`)

❌ Will NOT transform:

javascript
jwt.sign(payload, process.env.JWT_SECRET)  // Already secure
jwt.sign(payload, config.jwtSecret)       // Using config object
jwt.verify(token, 'secret')               // Not a sign() call

Configuration

After running the codemod, make sure to:

  1. Set the environment variable:
bash
export JWT_SECRET="your-super-secure-random-secret-key"
  1. Add to your .env file:
text
JWT_SECRET=your-super-secure-random-secret-key
  1. Use a strong secret:
bash
# Generate a secure random secret
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"

File patterns

The codemod processes these file types:

  • **/*.js - JavaScript files
  • **/*.ts - TypeScript files
  • **/*.jsx - React JavaScript files
  • **/*.tsx - React TypeScript files

Excluded patterns:

  • node_modules/ - Third-party dependencies
  • Test files (*.test.*, *.spec.*, __tests__/)
  • Configuration files (*.config.*)
  • Build outputs (dist/, build/)

Examples

React/Express app

javascript
// Before
app.post('/login', (req, res) => {
  const token = jwt.sign({ userId: user.id }, 'hardcoded-secret');
  res.json({ token });
});

// After  
app.post('/login', (req, res) => {
  const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET);
  res.json({ token });
});

Multiple import styles

javascript
// Before
import jwt from 'jsonwebtoken';
import { sign } from 'jsonwebtoken';
import * as jsonwebtoken from 'jsonwebtoken';

jwt.sign(data, 'secret1');
sign(data, 'secret2');
jsonwebtoken.sign(data, 'secret3');

// After
import jwt from 'jsonwebtoken';
import { sign } from 'jsonwebtoken';
import * as jsonwebtoken from 'jsonwebtoken';

jwt.sign(data, process.env.JWT_SECRET);
sign(data, process.env.JWT_SECRET);
jsonwebtoken.sign(data, process.env.JWT_SECRET);

Security References

Development

bash
# Run tests
pnpm test

# Test specific case
pnpm test --filter positive-default-import

# Update test snapshots
pnpm test -u

# Type check
pnpm check-types

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add test cases for your changes
  4. Run pnpm test to ensure all tests pass
  5. Submit a pull request

License

MIT

Ready to evolve your codebase?

Build tailored, compiler-aware skills to assess, plan, and automate complex codebase changes.