E11083: hardcoded database credential detected

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

What went wrong

A string literal containing a database connection URL with an embedded password was found in source code. Detected patterns include PostgreSQL, MySQL, MongoDB, Redis, and JDBC URLs where credentials are included directly in the connection string (e.g., postgres://user:password@host).

Database credentials embedded in connection strings are a critical security vulnerability (CWE-798) — anyone with access to source code, version control history, or compiled artifacts can extract the credential and gain direct database access.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 705 (How do I migrate from hardcoded secrets to secure pattern...)
  • ek9 -q 704 (How does EK9 detect hardcoded secrets at compile time?)
  • ek9 -q 702 (How do I load secrets from environment variables in EK9?)

Rationale

Database credentials in connection URLs are particularly dangerous because they provide direct data access, bypassing application-level security controls entirely. Unlike API keys which may have scoped permissions, database credentials typically grant full read/write access to all data in the database.

The OWASP Top 10 (2021) lists "Identification and Authentication Failures" as a critical risk. Embedded database passwords are a primary vector for this vulnerability category.

How to fix it

Load the database URL from an environment variable using the Sensitive type, and pass it on to your own function that takes the Sensitive URL:

secret <- EnvVars().sensitiveGet("DATABASE_URL")
if secret?
  configureService(secret)

For local development, set the environment variable:

export DATABASE_URL="postgres://admin:local_pass@localhost:5432/mydb"

For production, use your platform's secrets management:

  • Kubernetes: External Secrets or sealed-secrets
  • Cloud: AWS Secrets Manager, GCP Secret Manager, Azure Key Vault
  • Docker: Docker secrets or --env-file

See also

  • E11080: hardcoded cloud provider credential detected
  • E11081: hardcoded platform token detected
  • E11082: hardcoded private key material 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 E11083: hardcoded database credential detected

#!ek9
defines module error.e11083.bad

  defines function

    <?-
      PostgreSQL URL with embedded password detected.
    -?>
    testPostgresUrl()
      dbUrl <- "postgres://admin:s3cretPass@db.example.com:5432/mydb"

      stdout <- Stdout()
      stdout.println(dbUrl)

    <?-
      MySQL URL with embedded password detected.
    -?>
    testMysqlUrl()
      dbUrl <- "mysql://root:hunter2@mysql.internal:3306/app"

      stdout <- Stdout()
      stdout.println(dbUrl)

    <?-
      MongoDB URL with embedded password detected.
    -?>
    testMongoUrl()
      dbUrl <- "mongodb://appuser:mongopass@cluster0.abc.mongodb.net/mydb"

      stdout <- Stdout()
      stdout.println(dbUrl)

    <?-
      MongoDB+SRV URL with embedded password detected.
    -?>
    testMongoSrvUrl()
      dbUrl <- "mongodb+srv://admin:secretpw@cluster.mongodb.net/db"

      stdout <- Stdout()
      stdout.println(dbUrl)

    <?-
      Redis URL with embedded password detected.
    -?>
    testRedisUrl()
      dbUrl <- "redis://:redisPassword@redis.example.com:6379"

      stdout <- Stdout()
      stdout.println(dbUrl)

    <?-
      JDBC URL with password parameter detected.
    -?>
    testJdbcUrl()
      dbUrl <- "jdbc:postgresql://localhost:5432/db?user=admin&password=secret123"

      stdout <- Stdout()
      stdout.println(dbUrl)

Fixed: Read the connection URL from the environment as a Sensitive

#!ek9
defines module error.e11083.good

  defines function

    configureService()
      -> databaseUrl as Sensitive
      stdout <- Stdout()
      stdout.println($(databaseUrl?))

    demo()
      secret <- EnvVars().sensitiveGet("DATABASE_URL")
      if secret?
        configureService(secret)

Questions and answers

These Q&A entries show E11083 and its fix: