no-hardcoded-credentials
Disallow literal database passwords in TypeORM connection configuration, including credentials embedded in a connection URL.
CWE: CWE-798 OWASP: A07:2021 – Identification and Authentication Failures
Detects a database password written as a literal — as a config property, or embedded in a connection URL. This rule is part of eslint-plugin-typeorm-security.
💼 This rule is set to error in the strict config.
Quick Summary
| Aspect | Details |
|---|---|
| CWE Reference | CWE-798 (Use of Hard-coded Credentials) |
| Severity | Critical (CVSS 9.8) |
| Auto-Fix | ❌ No auto-fix available |
| Category | Security |
Why this matters
A password in source is a password in git history, in every fork and clone, in every CI log that prints the file, and in every layer of the built image.
That is what separates it from most findings: it does not stop being true when
you fix it. Deleting the line in a follow-up commit changes nothing — the
secret is still one git log -p away for anyone who has ever had read access. A
real fix means rotating the credential and rewriting history, which is
expensive enough that in practice it does not happen. The only cheap moment is
before the line is committed, which is where this rule sits.
❌ Incorrect
// ❌ literal password
new DataSource({ type: 'postgres', host, username, password: 'hunter2' });
// ❌ the same secret, hidden in a URL
new DataSource({ type: 'postgres', url: 'postgres://app:s3cret@db.internal/app' });✅ Correct
// ✅ read from the environment
new DataSource({ type: 'postgres', host, username, password: process.env.DB_PASSWORD });What this rule deliberately does not report
- A connection URL with no credentials in it.
postgres://localhost:5432/appandpostgres://app@db.internal/appare safe to commit. Only theuser:pass@userinfo form is a finding. - An empty password.
password: ''is the "no password" sentinel for local trust-auth setups. Reporting it teaches people the rule cries wolf. - Any runtime value —
process.env.DB_PASSWORD(the fix), a template literal, a variable. If the analyzer cannot see the value, there is no secret in the file. - A login or signup form.
{ user, password }and{ password, confirm }are not connection configs. The credential cannot be its own evidence that an object connects to a database — the object has to name somewhere to connect to (host,port,database,connectionString) before its password counts. Without that rule, every app with a login form and a database reports. - A file that never imports typeorm. The driver import is the gate that keeps this rule inside its own plugin; generic secret scanning belongs to a dedicated tool.
When Not To Use It
There is no configuration in which committing a database password is correct, so this rule has no options.
If a specific line is genuinely a throwaway — a docker-compose fixture, an integration test against an ephemeral container — disable it there with a reason rather than switching the rule off:
// eslint-disable-next-line typeorm-security/no-hardcoded-credentials -- ephemeral test container
new DataSource({ type: 'postgres', host, username, password: 'hunter2' });Further Reading
- CWE-798: Use of Hard-coded Credentials
- OWASP A07:2021 – Identification and Authentication Failures
- OWASP: Use of hard-coded password
Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.