Weakness reference
CWE-312

Cleartext Storage of Sensitive Information

This weakness occurs when sensitive data—such as passwords, API keys, authentication tokens, or personal information—is stored in plain, unencrypted form where…

01Summary

This weakness occurs when sensitive data—such as passwords, API keys, authentication tokens, or personal information—is stored in plain, unencrypted form where it can be read by unauthorized users. If an attacker gains access to the storage medium (a database, configuration file, log, or backup), they immediately obtain the sensitive data without any additional effort to decrypt it.

02How It Happens

Developers often store sensitive information in cleartext for convenience: it's simpler to read and compare directly, requires no key management overhead, and avoids the complexity of encryption libraries. However, this approach assumes the storage itself is always secure—a dangerous assumption. If a database is breached, a configuration file is exposed via misconfigured permissions, a backup is left on an unsecured server, or logs are archived without sanitization, all cleartext secrets become immediately compromised. The weakness is compounded when sensitive data is logged during debugging or error handling, persisting in files that may outlive the original application.

03Real-World Impact

Cleartext storage of passwords enables account takeover: an attacker with database access can log in as any user without cracking hashes. Exposed API keys allow unauthorized access to third-party services or internal APIs. Stored credit card numbers or personally identifiable information (PII) create liability under data protection regulations (GDPR, PCI-DSS, HIPAA) and expose users to identity theft. Even "low-sensitivity" data like usernames or email addresses, when stored alongside cleartext passwords, becomes a complete credential set. The impact scales with the number of records and the sensitivity of the data involved.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sqlite3

def store_user_credentials(username, password):
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    # Storing password in cleartext
    cursor.execute(
        "INSERT INTO users (username, password) VALUES (?, ?)",
        (username, password)
    )
    conn.commit()
    conn.close()

Why it's vulnerable:
The password is inserted directly into the database without hashing or encryption. Anyone with database access can read all passwords immediately.

Fixed pattern
import sqlite3
import hashlib
import secrets

def store_user_credentials(username, password):
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    # Hash the password with a salt
    salt = secrets.token_hex(16)
    hashed = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100000)
    cursor.execute(
        "INSERT INTO users (username, password_hash, salt) VALUES (?, ?, ?)",
        (username, hashed.hex(), salt)
    )
    conn.commit()
    conn.close()
Vulnerable pattern
<?php
$db = new mysqli('localhost', 'root', 'password', 'myapp');

function store_api_key($user_id, $api_key) {
    global $db;
    // Storing API key in cleartext
    $db->query(
        "INSERT INTO api_keys (user_id, key_value) VALUES ($user_id, '$api_key')"
    );
}
?>

Why it's vulnerable:
The API key is stored as-is in the database. Any database dump or unauthorized query exposes all keys in plain text.

Fixed pattern
<?php
$db = new mysqli('localhost', 'root', 'password', 'myapp');

function store_api_key($user_id, $api_key) {
    global $db;
    // Hash the API key before storage
    $hashed_key = hash('sha256', $api_key);
    $stmt = $db->prepare("INSERT INTO api_keys (user_id, key_hash) VALUES (?, ?)");
    $stmt->bind_param('is', $user_id, $hashed_key);
    $stmt->execute();
}
?>

05Prevention Checklist

Hash passwords
using a modern algorithm (bcrypt, Argon2, PBKDF2) with a unique salt per user; never store plaintext passwords.
Encrypt sensitive data at rest
(API keys, tokens, PII) using AES-256 or equivalent; use a key management system (KMS) to protect encryption keys separately.
Never log sensitive information
—strip passwords, tokens, and PII from logs before writing to disk or forwarding to log aggregation services.
Restrict database and file permissions
to the minimum necessary; use role-based access control (RBAC) so that compromising one account doesn't expose all data.
Encrypt backups
with the same rigor as production data; store backup encryption keys separately from the backups themselves.
Use environment variables or secrets management tools
(e.g., HashiCorp Vault, AWS Secrets Manager) for configuration secrets; never commit them to version control.

06Signs You May Already Be Affected

Review your database schema and recent backups for columns containing passwords, API keys, or tokens stored without hashing or encryption. Check application logs and error messages for instances where sensitive data (passwords, tokens, credit card numbers) appears in plaintext. Audit file permissions on configuration files, database dumps, and backup archives to ensure they are not world-readable or accessible to low-privileged accounts.

07Related Recent Vulnerabilities