no-plaintext-secrets
API keys and passwords written literally in a Compose file end up in version control. Where to put Compose secrets instead: interpolation, env_file, or secrets.
On this page
A Compose file is code: it gets committed, reviewed, forked, and pushed to template registries. A literal OPENAI_API_KEY: sk-… in environment: therefore publishes the credential to everyone with repo access, and to every clone, mirror, and backup, forever. This rule flags environment entries (map or list syntax) whose key looks like a credential (PASSWORD, SECRET, TOKEN, API_KEY, …) and whose value is a literal rather than a ${VAR} interpolation.
What the rule catches
services:
agent:
image: my-agent:1.2.0
environment:
OPENAI_API_KEY: sk-proj-abc123
DB_PASSWORD: hunter2Scanning this file reports:
⚠ WARN [docker-doctor/no-plaintext-secrets]
Potential secret in service 'agent' environment: 'OPENAI_API_KEY'. A literal value here lives in version control in plain text.Why it matters
Committed credentials are one of the most common real-world breach vectors, and compose files travel further than people expect: they get pasted into issues, copied into starter templates, and pushed to public forks. Agent stacks concentrate the risk, since one file often holds keys for a model provider, a search API, and a database at once. The rule only inspects the key name, so it cannot tell a real key from a placeholder; treat a hit on a placeholder as a prompt to switch to interpolation before the placeholder becomes real.
How to fix it
Move the value to an env_file kept out of version control, interpolate it from the host environment (${VAR}), or use Compose secrets:.
services:
agent:
image: my-agent:1.2.0
environment:
# resolved from the host environment / .env at compose up time
OPENAI_API_KEY: ${OPENAI_API_KEY}
env_file:
- .env.local # gitignoredPick the mechanism by how sensitive the value is:
${VAR}interpolation: Compose resolves it from the host environment or a.envfile atcompose uptime; the compose file carries only the reference.env_file: point it at a gitignored file to keep whole blocks of configuration out of version control.- Compose
secrets: mounts the value as a file rather than an environment variable, which also keeps it out ofdocker inspectoutput and crash dumps.
If a real credential has already been committed, rotate it. Removing the line only hides it from the working tree, not from git history.
Rule details
- Rule key —
docker-doctor/no-plaintext-secrets - Category — Compose
- Default severity —
warning - Applies to — Docker Compose files
Explain this rule from the CLI:
npx @docker-doctor/cli@latest rules explain docker-doctor/no-plaintext-secretsChange its severity — or turn it off — in your config file:
// docker-doctor.config.ts
export default {
rules: {
"docker-doctor/no-plaintext-secrets": "off",
},
};Severity affects the health score: error findings cost more points than warning, and info costs the least.