E11082: hardcoded private key material detected
What went wrong
A string literal containing a PEM private key header was found in source code. The pattern "-----BEGIN ... PRIVATE KEY" matches all PEM-encoded private key formats including RSA, EC, DSA, PKCS8, ENCRYPTED, and OPENSSH private keys.
Private keys are the most sensitive cryptographic material in any system. A leaked private key enables impersonation, decryption of encrypted data, forged digital signatures, and man-in-the-middle attacks.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 704 (How does EK9 detect hardcoded secrets at compile time?)
Rationale
Unlike tokens which can be rotated quickly, private key compromise often requires certificate revocation, key pair regeneration, and re-deployment across all systems that trust the corresponding public key. The blast radius of a private key leak is typically much larger than a token leak.
Private keys should never exist in source code under any circumstances.
How to fix it
Use a key management service or load from a secure file at runtime. Load it from an environment variable:
secret <- EnvVars().sensitiveGet("SERVICE_PRIVATE_KEY") if secret? configureService(secret)
Or use your platform's key management: AWS KMS, GCP Cloud KMS, Azure Key Vault, HashiCorp Vault.
For development:
- Generate development-only keys (never share with production)
- Store in a local file outside the repository
- Add key file patterns to .gitignore: *.pem, *.key, *.p12
For production:
- Use hardware security modules (HSMs) where possible
- Rotate keys on a regular schedule
- Use certificate managers for TLS (Let's Encrypt, AWS ACM)
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E11082: hardcoded private key material detected
#!ek9 defines module error.e11082.bad defines function <?- RSA private key PEM header detected. -?> testRsaPrivateKey() key <- "-----BEGIN RSA PRIVATE KEY-----" stdout <- Stdout() stdout.println(key) <?- EC (Elliptic Curve) private key PEM header detected. -?> testEcPrivateKey() key <- "-----BEGIN EC PRIVATE KEY-----" stdout <- Stdout() stdout.println(key) <?- DSA private key PEM header detected. -?> testDsaPrivateKey() key <- "-----BEGIN DSA PRIVATE KEY-----" stdout <- Stdout() stdout.println(key) <?- PKCS8 generic private key PEM header detected. -?> testPkcs8PrivateKey() key <- "-----BEGIN PRIVATE KEY-----" stdout <- Stdout() stdout.println(key) <?- Encrypted private key PEM header detected. -?> testEncryptedPrivateKey() key <- "-----BEGIN ENCRYPTED PRIVATE KEY-----" stdout <- Stdout() stdout.println(key) <?- OpenSSH private key header detected. -?> testOpensshPrivateKey() key <- "-----BEGIN OPENSSH PRIVATE KEY-----" stdout <- Stdout() stdout.println(key)
Fixed: Load the key at run time as a Sensitive, never as a literal
#!ek9 defines module error.e11082.good defines function configureService() -> privateKey as Sensitive stdout <- Stdout() stdout.println($(privateKey?)) demo() secret <- EnvVars().sensitiveGet("SERVICE_PRIVATE_KEY") if secret? configureService(secret)
Questions and answers
These Q&A entries show E11082 and its fix: