E11082: hardcoded private key material detected

Category: E11xxx Code quality and IR analysis · Reported in phase: PRE_IR_CHECKS · Classification: HARDCODED_SECRET_PRIVATE_KEY · All error codes

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

  • E11080: hardcoded cloud provider credential detected
  • E11081: hardcoded platform token detected
  • E11083: hardcoded database credential detected
  • E11084: hardcoded JWT token detected
  • E11086: hardcoded API key detected

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: