Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Academy Key Management Failures
Intermediate · 20 min

Key Management Failures

Learn the dangers of hard-coded keys, keys in source control, and how to use secrets managers properly.

1 Hard-Coded Keys and Keys in Source Control

Cryptographic keys hard-coded in source code or committed to version control are one of the most common and easily exploitable security failures. Git history is permanent — even deleted files remain accessible.

Vulnerable patterns:

# Hard-coded in source (NEVER do this)
AES_KEY = b"mysupersecretkey16"
JWT_SECRET = "my-jwt-secret-key"
API_KEY = "sk_live_abcdef123456"
// In JavaScript config file
const config = {
  stripeKey: "sk_live_AbCdEfGhIjKlMnOp",  // Committed to public repo!
  dbPassword: "admin123"
};

Git history exposure:

# Key "deleted" in latest commit is still visible
git log --all --full-history -- secrets.py
git show abc123:secrets.py  # Key is still there!

Automated scanners (GitGuardian, truffleHog) continuously monitor public repositories and identify exposed secrets within seconds of a commit.

Key rotation absence: Even if a key is not in source control, never rotating keys means a single compromise is permanent. Keys should have defined lifetimes.

2 Secrets Managers and Environment Variables

Store secrets in environment variables at minimum, and use dedicated secrets managers for production systems.

Environment variables (minimum viable):

import os

AES_KEY = os.environ["AES_KEY"].encode()  # Fail loudly if not set
JWT_SECRET = os.environ["JWT_SECRET"]

# With a .env file locally (never commit .env!)
# .gitignore should include: .env, .env.local, *.key, *.pem

AWS Secrets Manager:

import boto3
import json

def get_secret(secret_name):
    client = boto3.client("secretsmanager", region_name="us-east-1")
    response = client.get_secret_value(SecretId=secret_name)
    return json.loads(response["SecretString"])

secrets = get_secret("prod/myapp/database")
DB_PASSWORD = secrets["password"]

Defense checklist:

  • Never hard-code keys, passwords, or tokens in source code
  • Add .env and *.key to .gitignore
  • Use environment variables for development
  • Use a secrets manager (Vault, AWS Secrets Manager, Azure Key Vault) for production
  • Rotate keys regularly and immediately after any suspected exposure
  • Scan git history with truffleHog or git-secrets before open-sourcing

Knowledge Check

0/3 correct
Q1

A developer removes an API key from source code and pushes a new commit. Is the key still exposed?

Q2

What is the advantage of a secrets manager over environment variables?

Q3

What should you do immediately upon discovering a secret was committed to a public repository?

Code Exercise

Move Secrets to Environment Variables

The application has hard-coded cryptographic keys. Move them to environment variables with proper error handling if they are not set.

python