Use of Hard-coded Credentials
Description
Use of Hard-coded Credentials occurs when a product contains hard-coded credentials such as passwords, cryptographic keys, or API tokens embedded directly in source code, configuration files, or compiled binaries. These credentials may be used for inbound authentication (allowing external parties to authenticate to the software) or outbound authentication (the software authenticating to external services). Hard-coded credentials create a significant security risk because they cannot be easily changed, are often discoverable through reverse engineering or source code access, and are typically shared across all installations of the software.
Risk
Hard-coded credentials consistently rank among the most dangerous software weaknesses. CVE-2025-2538 in Esri Portal for ArcGIS (CVSS 9.8 Critical) allows unauthenticated attackers to gain administrative access through hard-coded credentials, affecting government, utilities, and transportation sectors. CVE-2025-36087 in IBM Security Verify Access exposes hard-coded credentials in versions 10.0.0-10.0.9 and 11.0.0. Over 40% of data breaches involve weak or exposed credentials. The Mirai botnet exploited IoT devices with factory-default hard-coded credentials to launch massive DDoS attacks. Developers frequently commit code with embedded credentials to public repositories.
Solution
Never embed credentials in source code. Use environment variables, configuration files with restricted permissions, or secrets management solutions (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). Implement credential rotation mechanisms. Use unique credentials per installation. For IoT devices, require credential change on first use. Scan code repositories for accidentally committed credentials. Use pre-commit hooks to prevent credential commits. Implement runtime credential injection. For API keys, use short-lived tokens with automatic rotation.
Common Consequences
| Impact | Details |
|---|---|
| Authentication | Scope: Complete Bypass Hard-coded credentials provide immediate authentication bypass to anyone who discovers them. |
| Access Control | Scope: Unauthorized Access Attackers gain access to systems, data, and functionality protected by the hard-coded credentials. |
| Confidentiality | Scope: Mass Compromise Same credentials across all installations means one discovery compromises all deployments. |
Example Code + Solution Code
Vulnerable Code
// VULNERABLE: Hard-coded database password
public class DatabaseConnection {
private static final String DB_HOST = "db.example.com";
private static final String DB_USER = "admin";
private static final String DB_PASSWORD = "SuperSecret123!"; // Hard-coded!
public Connection getConnection() throws SQLException {
return DriverManager.getConnection(
"jdbc:mysql://" + DB_HOST + "/mydb",
DB_USER,
DB_PASSWORD
);
}
}
// VULNERABLE: Hard-coded API key
public class PaymentService {
private static final String STRIPE_API_KEY = "sk_live_51H7...abc123"; // Exposed!
public void processPayment(Payment payment) {
Stripe.apiKey = STRIPE_API_KEY;
// Process payment
}
}
# VULNERABLE: Credentials in source code
import requests
API_KEY = "AIzaSyD-abc123xyz789" # Hard-coded Google API key!
SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" # AWS secret!
def connect_to_api():
headers = {"Authorization": f"Bearer {API_KEY}"}
return requests.get("https://api.example.com/data", headers=headers)
# VULNERABLE: Hard-coded admin credentials for backdoor
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "admin123" # Default backdoor!
def authenticate(username, password):
if username == ADMIN_USERNAME and password == ADMIN_PASSWORD:
return True # Backdoor access
return check_database(username, password)
// VULNERABLE: Credentials in client-side code
const config = {
apiKey: 'sk-1234567890abcdef', // Exposed in browser!
firebaseConfig: {
apiKey: "AIzaSyD-abc123", // Public API key
authDomain: "myapp.firebaseapp.com",
databaseURL: "https://myapp.firebaseio.com"
}
};
// VULNERABLE: SSH key in source
const SSH_PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`;
async function deployToServer() {
const conn = await ssh.connect({
host: 'production.server.com',
username: 'deploy',
privateKey: SSH_PRIVATE_KEY // Hard-coded private key!
});
}
Fixed Code
// SAFE: Credentials from environment or secrets manager
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
public class SecureDatabaseConnection {
private final AWSSecretsManager secretsManager;
public SecureDatabaseConnection(AWSSecretsManager secretsManager) {
this.secretsManager = secretsManager;
}
public Connection getConnection() throws Exception {
// Get credentials from secrets manager
GetSecretValueResult secret = secretsManager.getSecretValue(
new GetSecretValueRequest().withSecretId("prod/db/credentials")
);
JSONObject creds = new JSONObject(secret.getSecretString());
String host = creds.getString("host");
String user = creds.getString("username");
String password = creds.getString("password");
return DriverManager.getConnection(
"jdbc:mysql://" + host + "/mydb",
user,
password
);
}
}
// SAFE: API key from environment with validation
public class SecurePaymentService {
private final String stripeApiKey;
public SecurePaymentService() {
this.stripeApiKey = System.getenv("STRIPE_API_KEY");
if (stripeApiKey == null || stripeApiKey.isEmpty()) {
throw new IllegalStateException("STRIPE_API_KEY environment variable not set");
}
}
public void processPayment(Payment payment) {
Stripe.apiKey = stripeApiKey;
// Process payment
}
}
# SAFE: Credentials from environment and secrets manager
import os
import boto3
from botocore.exceptions import ClientError
def get_secret(secret_name):
"""Retrieve secret from AWS Secrets Manager."""
client = boto3.client('secretsmanager')
try:
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])
except ClientError as e:
raise RuntimeError(f"Failed to retrieve secret: {e}")
def connect_to_api():
# Get API key from environment or secrets manager
api_key = os.environ.get('API_KEY')
if not api_key:
secrets = get_secret('prod/api/credentials')
api_key = secrets['api_key']
headers = {"Authorization": f"Bearer {api_key}"}
return requests.get("https://api.example.com/data", headers=headers)
# SAFE: No backdoor credentials - use proper authentication
def authenticate(username, password):
# Always check against secure credential store
user = get_user_from_database(username)
if not user:
# Constant-time comparison to prevent timing attacks
dummy_hash = generate_dummy_hash()
verify_password(password, dummy_hash)
return False
return verify_password(password, user.password_hash)
// SAFE: Credentials from environment (server-side only)
require('dotenv').config();
const config = {
// Loaded from environment variables
apiKey: process.env.API_KEY,
stripeKey: process.env.STRIPE_SECRET_KEY
};
// Validate required credentials at startup
const requiredEnvVars = ['API_KEY', 'STRIPE_SECRET_KEY', 'DATABASE_URL'];
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`);
}
}
// SAFE: SSH key from file with proper permissions
const fs = require('fs');
const path = require('path');
async function deployToServer() {
const keyPath = process.env.SSH_KEY_PATH || path.join(os.homedir(), '.ssh', 'deploy_key');
// Verify key file permissions (should be 0600)
const stats = fs.statSync(keyPath);
const mode = stats.mode & 0o777;
if (mode !== 0o600) {
throw new Error('SSH key file has insecure permissions');
}
const privateKey = fs.readFileSync(keyPath, 'utf8');
const conn = await ssh.connect({
host: process.env.DEPLOY_HOST,
username: process.env.DEPLOY_USER,
privateKey: privateKey
});
}
// SAFE: Client-side code uses only public configuration
// Sensitive operations happen server-side
const publicConfig = {
firebaseConfig: {
apiKey: "AIzaSyD-abc123", // Firebase public key (designed for client)
authDomain: "myapp.firebaseapp.com",
projectId: "myapp"
// No secrets here - sensitive ops use Firebase Security Rules
}
};
Exploited in the Wild
Esri Portal for ArcGIS (Esri, 2025)
CVE-2025-2538 (CVSS 9.8 Critical) in Esri Portal for ArcGIS 11.4 and below contains hard-coded credentials enabling unauthenticated remote attackers to gain administrative access to GIS systems used in government, utilities, transportation, and environmental management.
IBM Security Verify Access (IBM, 2025)
CVE-2025-36087 in IBM Security Verify Access versions 10.0.0-10.0.9 and 11.0.0 exposes hard-coded credentials, affecting finance, healthcare, government, and critical infrastructure sectors that rely on robust access controls.
Mirai Botnet IoT Attacks (Multiple, 2016-Present)
The Mirai botnet exploited IoT devices with hard-coded factory credentials, compromising millions of devices for massive DDoS attacks that took down major internet services including Dyn DNS.
Tools to test/exploit
-
TruffleHog — scan for secrets in git repositories.
-
GitLeaks — detect hard-coded secrets in code.
-
Detect-Secrets — pre-commit hook for credential detection.
CVE Examples
-
CVE-2025-2538 — Esri Portal for ArcGIS hard-coded credentials.
-
CVE-2025-36087 — IBM Security Verify Access hard-coded credentials.
-
CVE-2024-0865 — Schneider Electric hard-coded credentials.
References
-
MITRE. "CWE-798: Use of Hard-coded Credentials." https://cwe.mitre.org/data/definitions/798.html
-
OWASP. "Use of hard-coded password." https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password