CWE-321: Use of Hard-coded Cryptographic Key
Overview
Hard-coded cryptographic keys embedded in source code, configuration files, or binaries are exposed to anyone with access to the codebase, version control, compiled binaries, or backups. Anything encrypted under such a key can be decrypted by whoever finds it, and the key cannot be rotated without redeploying code.
Relationship to Other CWEs
- CWE-321 (this page) - a cryptographic key embedded in source, configuration, or a binary, so anything encrypted under it can be decrypted by whoever finds it and the key cannot be rotated without redeploying code.
- CWE-798 (Use of Hard-coded Credentials) - the parent of this CWE. CWE-798 covers any hard-coded secret - passwords, API keys, tokens, connection strings - and carries the full secrets-management remediation path; this page is the cryptographic-key variant of it.
- CWE-259 (Use of Hard-coded Password) - a peer weakness: the same root problem applied to a password instead of a cryptographic key. Fix it the same way, with an external secrets store rather than an embedded literal.
- CWE-656 (Reliance on Security Through Obscurity) - can precede this weakness, where a key is embedded on the assumption that nobody will look inside the shipped artifact for it.
- CWE-526 (Cleartext Storage of Sensitive Information in an Environment Variable) - MITRE lists no relationship between the two, but it is where a key often lands next: moving the literal into a
.envfile or a deployment manifest relocates the exposure instead of removing it.
OWASP Classification
A04:2025 - Cryptographic Failures
Risk
Critical: Anyone who obtains a hard-coded key can decrypt everything it protects, and the key cannot be rotated without a code change. It is exposed in version control history, decompiled binaries, and backups, gives no key separation between environments, and breaches compliance requirements such as PCI DSS and HIPAA.
Remediation Steps
Core Principle: Never embed cryptographic keys in application artifacts (source code, binaries, images, or client-accessible configuration); keys must be provided to the application at runtime from a dedicated key-management boundary and treated as replaceable secrets.
Locate the hard-coded cryptographic key
- Start from the file, line, and variable name the finding reports
- Search the codebase for patterns such as "const KEY =", "SECRET_KEY =", "private static final", "AES_KEY =", and long alphanumeric literals that look like base64-encoded keys
- Check configuration files committed to version control - application.properties, config.json, .env - for encryption keys
- Inspect compiled artifacts such as Docker images, JAR files, and binaries where keys may be embedded
- Search git history for keys committed earlier that still exist in old commits
Treat the key as already disclosed (Do This First)
Removing the literal does not un-expose it. The key is in every clone and fork of the repository, in CI caches and build logs, in shipped binaries and container image layers, and in backups - and rewriting git history reaches none of those. A scan finding for a hard-coded key is a disclosure to be handled, not only a line to be edited.
- Generate a replacement key in the KMS or vault before touching the source
- Re-encrypt or re-wrap everything protected by the old key. With envelope encryption this is a re-wrap of the data keys rather than a full re-encryption of the data, which is the main practical argument for a key hierarchy
- Retire the old key once nothing decrypts under it, and keep it only as long as some archive still needs reading
- Then remove the literal and move key loading to the mechanism below
Scheduled rotation is a separate, weaker control and appears further down; it does not substitute for rotating a key that is known to be out.
Use external key management (Primary Defense)
- Use a cloud KMS - AWS KMS, Azure Key Vault, GCP Cloud KMS - for key storage, envelope encryption, and audited cryptographic operations
- HashiCorp Vault provides centralized secret management with access control and audit logging
- Keep keys out of version control: add key files to .gitignore. A key that was already committed is disclosed whatever is done to the history, and is handled as described above
- Do not bake keys into container images - inject them at runtime
- Treat environment variables as an injection mechanism, not a storage location: Reading the key with
os.environ.get('ENCRYPTION_KEY')is fine when a runtime or orchestrator fetched it from a KMS or vault and placed it there at process start. Writing it into a deployment manifest, a.envfile, or a shell profile moves the hard-coded key to another file rather than removing it, and a key left sitting in the process environment has its own exposures - see CWE-526
Generate keys at deployment/runtime
- Generate a distinct key for each installation: each environment, customer, or tenant
- Use a cryptographically secure random source:
secrets.token_bytes()(Python),SecureRandom(Java),crypto.randomBytes()(Node.js) - Store generated keys in a KMS, vault, or encrypted configuration, not in code
- Rotate keys on a schedule (quarterly, annually), automated where possible
Implement proper key separation and derivation
- Separate keys for dev, staging, and production
- Per-tenant keys in multi-tenant applications
- Separate encryption and signing keys; do not reuse one key for different purposes
- A key hierarchy, where a master key encrypts data keys (envelope encryption)
- Per-tenant or per-user keys derived from the master key with HKDF (RFC 5869) or a NIST SP 800-108 KDF, binding the tenant or user identifier into the
info/context parameter. Password-based KDFs - PBKDF2, Argon2, scrypt - exist to make low-entropy input expensive to guess; against a high-entropy master key their cost buys nothing and adds latency to every request
Monitor and audit key usage
- Track key access and usage (log encryption/decryption operations with key metadata)
- Alert on unauthorized key access attempts
- Confirm keys are rotated on schedule
- Catch hard-coded keys in new code with secret scanning in CI/CD
- Review key management practices regularly, for example in quarterly security audits
Test the key management fix
- Verify no hard-coded keys remain in code, with grep and secret scanning tools
- Confirm the application loads keys from the external source (environment, KMS, vault)
- Confirm encryption and decryption work with externally managed keys
- Exercise the rotation process: re-encrypt data with a new key
- Verify different environments use different keys
- Re-scan with the security scanner to confirm the finding is resolved
Common Vulnerable Patterns
const KEY = "hardcoded-secret-key"- Keys in application.properties
- AES keys as string literals
- Encryption keys in source code
- Secrets in Docker images