Hard-coded passwords are authentication credentials embedded directly in source code, configuration files, or compiled binaries. This weakness exposes…
Hard-coded passwords are authentication credentials embedded directly in source code, configuration files, or compiled binaries. This weakness exposes sensitive credentials to anyone with access to the codebase, version control history, or compiled application — turning a secret into a discoverable constant. Even if the code is private, hard-coded passwords create a single point of failure: changing the password requires recompiling and redeploying the entire application.
02How It Happens
Developers hard-code passwords for convenience during development or to simplify deployment, intending to "fix it later." Common scenarios include database connection strings, API keys, service account credentials, and encryption keys embedded in source files or checked into version control. Once committed, the credential persists in repository history even if later deleted from the current branch. Compiled binaries and container images can be reverse-engineered to extract these strings. The weakness is compounded when the same hard-coded credential is used across multiple environments (development, staging, production), making a single leaked copy a master key.
03Real-World Impact
An attacker who gains read access to source code, a compiled binary, or a container image can extract the hard-coded password and use it to authenticate as the application itself — accessing databases, calling internal APIs, or impersonating the service to other systems. This bypasses normal access controls and audit trails. If the credential grants administrative privileges, the attacker gains full control over the protected resource. Rotating the password becomes a major operational burden, requiring code changes, recompilation, and redeployment across all instances.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import sqlite3
def connect_to_database():
# Hard-coded password embedded in source code
connection = sqlite3.connect(":memory:")
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?",
("admin", "SuperSecret123"))
return cursor.fetchall()
Why it's vulnerable: The password "SuperSecret123" is visible in the source code and will be present in version control history, compiled bytecode, and any deployed copy of the application. Anyone with read access to the codebase can extract it.
Fixed pattern
import sqlite3
import os
def connect_to_database():
# Read password from environment variable at runtime
password = os.getenv("DB_PASSWORD")
if not password:
raise ValueError("DB_PASSWORD environment variable not set")
connection = sqlite3.connect(":memory:")
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?",
("admin", password))
return cursor.fetchall()
Why it's vulnerable: The database password is visible in the PHP file and will be exposed if the source code is accessed, backed up, or included in a container image. It cannot be changed without modifying and redeploying the code.
Fixed pattern
<?php
// Read credentials from environment variables or secure configuration
$db_host = getenv("DB_HOST") ?: "localhost";
$db_user = getenv("DB_USER");
$db_password = getenv("DB_PASSWORD");
if (!$db_user || !$db_password) {
die("Database credentials not configured via environment variables");
}
$mysqli = new mysqli($db_host, $db_user, $db_password, "app_db");
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
?>
05Prevention Checklist
Use environment variables or secure vaults — Store all credentials (database passwords, API keys, encryption keys) in environment variables, secrets management systems (e.g., HashiCorp Vault, AWS Secrets Manager), or encrypted configuration files loaded at runtime, never in source code.
Rotate credentials regularly — Use a secrets management system that allows credential rotation without code changes or redeployment.
Audit version control history — Search Git history for common credential patterns (e.g., password=, api_key=, secret=) and remove any found; use tools like git-secrets or truffleHog to prevent future commits.
Exclude sensitive files from version control — Add .env, config/secrets.yml, and similar files to .gitignore and document the required environment variables in a template file (e.g., .env.example).
Use different credentials per environment — Never reuse the same password across development, staging, and production; each environment should have its own isolated credentials.
Review compiled artifacts and container images — Scan built binaries and Docker images for embedded strings that resemble credentials before deployment.
06Signs You May Already Be Affected
Search your codebase and version control history for patterns like password=, api_key=, secret=, or token= followed by quoted strings. Check .env files, configuration files, and comments for any credentials. Review container image layers and compiled binaries using tools like strings to see if credentials are embedded. If you find hard-coded credentials, assume they have been exposed to anyone with repository access and rotate them immediately.