Hardcoded passwords, API keys and secrets¶
A hardcoded secret is embedded in source, a distributed binary, image layer, or another artifact whose readers should not possess that credential. Anyone who obtains it may gain the permissions attached to it. Actual impact depends on the secret's validity, scope, exposure, and the target service; compromise is not inevitable merely because a string resembles a password.
Trust boundary: access to an application repository or public client must not grant access to production credentials. Keep service credentials in an approved secret-management system and give each workload access only to the secrets it needs. OWASP's secrets-management guidance covers provisioning, access, rotation, and lifecycle controls.
Unsafe example: a credential in source¶
# Fictional placeholder showing the pattern; not a usable credential.
service_token = 'DEMO_ONLY_NOT_A_REAL_TOKEN'
Encrypting a secret while shipping the decryption key beside it does not remove this exposure. Moving it into a committed .env, YAML, or JSON file also leaves it in the repository.
Safer example: require runtime injection¶
The deployment system supplies the value from an approved store. This Python helper takes an environment mapping explicitly so it can be tested without reading real credentials.
def required_secret(environment, name):
value = environment.get(name)
if not isinstance(value, str) or not value.strip():
raise RuntimeError(f'Missing required secret: {name}')
return value
# In application startup: required_secret(os.environ, 'SERVICE_API_TOKEN').
# Do not print the result, copy it into URLs, or provide an insecure fallback.
Environment variables are one delivery mechanism, not a secure store by themselves. Restrict runtime inspection, diagnostic dumps, inherited child-process environments, and deployment logs. A secret-manager SDK or mounted secret file may better fit the platform. Prefer short-lived workload identity where supported; avoid a static credential entirely when the service can authenticate the workload directly.
JavaScript / TypeScript: build a small credential object¶
function databaseCredentials(environment) {
function required(name) {
const value = environment[name];
if (typeof value !== 'string' || value.trim().length === 0) {
throw new Error(`Missing required secret: ${name}`);
}
return value;
}
return {
user: required('DB_USER'),
password: required('DB_PASSWORD'),
};
}
The caller supplies the protected startup environment and passes these fields to the database driver's supported authentication options. This helper does not establish TLS, database privileges, or connection policy; configure those separately. A missing value causes startup failure instead of falling back to a known password. The Node process environment reference documents the runtime interface.
Do not place credentials in HTTP query strings, redirects, or loggable connection URLs. Those values can enter history, proxies, telemetry, and error reports even when HTTPS is used. Send credentials only through the target protocol's supported authentication mechanism over a verified secure connection.
User passwords are a different problem¶
Store end-user passwords with a dedicated adaptive password-hashing facility, not reversible encryption or a shared secret-config entry. Verify them with the framework's password API. A database service password must usually be retrieved for outbound authentication; an end-user password should be verified against its stored password hash. See password hashing and password policy.
If a real secret was exposed¶
Revoke or rotate it, update authorized consumers, investigate use, and remove it from current files and public artifacts where feasible. Cleaning Git history alone does not invalidate copies or undo access. Include old image layers, build logs, caches, and release packages in the response. Avoid writing the secret into tickets or remediation reports.
Regression test¶
Pass only fictional mappings to the helpers. Confirm a present value is preserved exactly, while missing, empty, and whitespace-only values fail without revealing a secret. Test that startup has no default credential. Use a fictional marker to verify request URLs, logs, errors, and build artifacts do not contain the injected value. Test a rotation procedure in an isolated environment before relying on it operationally.
Related: sensitive logging, certificate verification, supply-chain security, and mobile credential handling.
References: CWE-798 — use of hardcoded credentials and CWE-259 — use of a hardcoded password.