Weakness reference
CWE-318

Cleartext Storage of Sensitive Information in Executable

This weakness occurs when sensitive data—such as API keys, database credentials, encryption keys, or authentication tokens—is hardcoded or embedded in…

01Summary

This weakness occurs when sensitive data—such as API keys, database credentials, encryption keys, or authentication tokens—is hardcoded or embedded in plaintext within compiled binaries or executable files. Anyone with access to the binary can extract this information using basic tools like string dumpers or disassemblers, bypassing all runtime security controls.

02How It Happens

Developers often embed sensitive configuration or credentials directly in source code for convenience during development, intending to remove them before release but forgetting to do so. When the code is compiled into a binary (whether native executable, bytecode, or intermediate representation), these strings remain readable in the compiled output. Even if the source code is not distributed, the binary itself becomes a liability: attackers who obtain it through reverse engineering, supply chain compromise, or insider access can trivially extract plaintext secrets using automated tools that scan for recognizable patterns (e.g., "password=", "api_key=", or base64-encoded credentials).

03Real-World Impact

Exposed credentials in binaries can lead to unauthorized access to backend systems, databases, or third-party services. An attacker who extracts an API key or database password gains the same privileges as the application itself, potentially allowing data theft, modification, or deletion at scale. If the binary is distributed widely (as in mobile apps or desktop software), the compromise affects all users simultaneously and is difficult to remediate without forcing an update.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sqlite3

DATABASE_PASSWORD = "admin_pass_2024"
API_KEY = "sk-1234567890abcdef"

def connect_to_db():
    conn = sqlite3.connect("app.db")
    # Password hardcoded above, visible in compiled bytecode
    return conn

def fetch_user_data(user_id):
    headers = {"Authorization": f"Bearer {API_KEY}"}
    # API key hardcoded above, visible in compiled bytecode
    response = requests.get(f"https://api.example.com/users/{user_id}", headers=headers)
    return response.json()

Why it's vulnerable:
The credentials are stored as string literals in the source code and remain readable in the compiled .pyc bytecode or when the script is packaged. Tools like strings or bytecode decompilers can extract them instantly.

Fixed pattern
import os
import sqlite3
from dotenv import load_dotenv

load_dotenv()

DATABASE_PASSWORD = os.getenv("DATABASE_PASSWORD")
API_KEY = os.getenv("API_KEY")

def connect_to_db():
    conn = sqlite3.connect("app.db")
    return conn

def fetch_user_data(user_id):
    headers = {"Authorization": f"Bearer {API_KEY}"}
    response = requests.get(f"https://api.example.com/users/{user_id}", headers=headers)
    return response.json()
Vulnerable pattern
<?php
define('DB_USER', 'admin');
define('DB_PASS', 'SecurePass123');
define('API_TOKEN', 'token_abc123xyz');

function get_db_connection() {
    $conn = new mysqli('localhost', DB_USER, DB_PASS, 'myapp_db');
    // Credentials hardcoded as constants, visible in source or decompiled code
    return $conn;
}

function call_external_api($endpoint) {
    $headers = array('Authorization: Bearer ' . API_TOKEN);
    // Token hardcoded, visible in source
    $response = wp_remote_get($endpoint, array('headers' => $headers));
    return $response;
}
?>

Why it's vulnerable:
Constants and string literals in PHP source files remain visible if the source is accessed, or if the application is decompiled or reverse-engineered. Even in compiled extensions, strings are often extractable.

Fixed pattern
<?php
// Load credentials from environment or secure configuration file outside web root
$db_user = getenv('DB_USER');
$db_pass = getenv('DB_PASS');
$api_token = getenv('API_TOKEN');

function get_db_connection() {
    global $db_user, $db_pass;
    $conn = new mysqli('localhost', $db_user, $db_pass, 'myapp_db');
    return $conn;
}

function call_external_api($endpoint) {
    global $api_token;
    $headers = array('Authorization: Bearer ' . $api_token);
    $response = wp_remote_get($endpoint, array('headers' => $headers));
    return $response;
}
?>

05Prevention Checklist

Use environment variables, secure configuration files (outside the web root or binary distribution), or a secrets management system (e.g., HashiCorp Vault, AWS Secrets Manager) to store credentials and API keys.
Never commit secrets to version control; use .gitignore to exclude .env files and configuration files containing credentials.
Audit source code and compiled binaries regularly for hardcoded strings matching common credential patterns (e.g., "password=", "api_key=", "token=").
Rotate credentials frequently and immediately if a binary or source code is suspected to be compromised.
Use code scanning tools (e.g., git-secrets, truffleHog, or SAST tools) in your CI/CD pipeline to detect and block commits containing secrets.
For distributed binaries (mobile apps, desktop software), implement a secure configuration delivery mechanism that fetches credentials at runtime from a trusted server over an encrypted channel.

06Signs You May Already Be Affected

Review your source code and any compiled binaries for hardcoded strings matching credential patterns. Check version control history for commits that may have accidentally included passwords or API keys, even if they were later removed (they remain in git history). If a binary or source repository has been publicly exposed or accessed by unauthorized parties, assume any embedded credentials have been compromised and rotate them immediately.