Skip to content

Database credentials

An application needs a database URL, a username and a password, and none of the three should be readable from the source tree, the build artefact, a process listing or a log line.

Bind the connection settings from the environment rather than writing them into a checked-in configuration file. In Spring Boot that is a placeholder in application.yml with no default:

spring:
datasource:
driver-class-name: org.postgresql.Driver
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}

Omitting the :default part is deliberate — the application should fail to start if the value is absent rather than silently fall back to something.

The environment variables themselves should be populated at deploy time from a secret store rather than being set by hand: AWS Secrets Manager or SSM Parameter Store (SecureString) for services we run on AWS, or the platform’s own secret mechanism elsewhere. A managed database that supports IAM authentication removes the password entirely, which is better again: the application requests a short-lived token at connection time and there is nothing long-lived to leak.

Do not decrypt credentials inside the application. A pattern that shows up in older code is a @PostConstruct method that reads an encrypted URL, username and password from configuration and decrypts them at startup. It moves the problem rather than solving it: the decryption key has to reach the same process, by the same means, and now sits in memory next to the plaintext it protects. If a value can be injected securely, inject the credential; if it cannot, the encrypted blob is no safer.

Do not pass passwords as command-line arguments. Anything in argv is visible to any local ps, and lands in shell history. Use the tool’s file- or environment-based mechanism instead — ~/.pgpass or PGPASSWORD exported from a secret lookup for psql, sqlplus /nolog with a wallet-backed CONNECT for Oracle.

Do not log the datasource configuration. Frameworks that dump their resolved environment at DEBUG will print the password with it. See the logging section of Secure coding.

Credentials fetched at startup are pinned for the life of the process, so rotation means a restart unless the application re-reads them. Where a secret store offers managed rotation, either adopt a client that refreshes on failure, or accept the restart and make it part of the rotation runbook — an unrotatable credential in practice is the usual outcome of leaving this undecided.