Weakness reference
CWE-313

Cleartext Storage in a File or on Disk

This weakness occurs when an application stores sensitive data—such as passwords, API keys, authentication tokens, or personal information—in plain…

01Summary

This weakness occurs when an application stores sensitive data—such as passwords, API keys, authentication tokens, or personal information—in plain, unencrypted form on disk or in files. Anyone with access to the file system, whether through a compromised account, misconfigured permissions, or physical access, can read this data directly. It is one of the most common and easily preventable security failures.

02How It Happens

Developers often store sensitive information in cleartext for convenience: it's faster to write, easier to debug, and requires no additional libraries or key management. Configuration files, log files, temporary caches, and database backups may all end up containing secrets in plain sight. The assumption—often implicit—is that file system permissions alone will protect the data. However, permissions can be misconfigured, accounts can be compromised, backups can be copied, and in many environments (shared hosting, containers, cloud instances), multiple users or processes may have overlapping access. Once an attacker gains any foothold on the system, cleartext secrets are immediately exploitable.

03Real-World Impact

Cleartext storage of credentials enables account takeover, lateral movement, and privilege escalation. Exposed API keys allow attackers to impersonate the application and access third-party services. Leaked personal data (names, emails, phone numbers, addresses) violates privacy regulations and enables identity theft or social engineering. Database connection strings in config files give attackers direct access to the database. Even seemingly low-value data—like session tokens or temporary authentication codes—can be chained with other weaknesses to compromise user accounts or the application itself.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import json

# Configuration file with secrets in cleartext
config = {
    "db_password": "MySecretPassword123",
    "api_key": "sk_live_abc123xyz789",
    "admin_token": "token_xyz_admin_2024"
}

with open("/app/config.json", "w") as f:
    json.dump(config, f)

# Later, read and use
with open("/app/config.json", "r") as f:
    loaded_config = json.load(f)
    db_pass = loaded_config["db_password"]

Why it's vulnerable:
Secrets are written to disk in plain text. Any process or user with read access to the file can extract the credentials.

Fixed pattern
import json
import os
from cryptography.fernet import Fernet

# Load encryption key from environment (never hardcode)
encryption_key = os.environ.get("APP_ENCRYPTION_KEY")
cipher = Fernet(encryption_key)

config = {
    "db_password": "MySecretPassword123",
    "api_key": "sk_live_abc123xyz789",
    "admin_token": "token_xyz_admin_2024"
}

# Encrypt before writing
encrypted_data = cipher.encrypt(json.dumps(config).encode())
with open("/app/config.json", "wb") as f:
    f.write(encrypted_data)

# Decrypt when reading
with open("/app/config.json", "rb") as f:
    decrypted_data = cipher.decrypt(f.read())
    loaded_config = json.loads(decrypted_data)
Vulnerable pattern
<?php
// Store database credentials in a plaintext config file
$config = array(
    'db_host' => 'localhost',
    'db_user' => 'app_user',
    'db_password' => 'SuperSecret456',
    'api_key' => 'key_production_xyz'
);

file_put_contents('/var/www/config.php', '<?php $config = ' . var_export($config, true) . '; ?>');

// Later, include and use
include '/var/www/config.php';
$mysqli = new mysqli($config['db_host'], $config['db_user'], $config['db_password']);
?>

Why it's vulnerable:
Credentials are stored in a PHP file in plain text. If the web server is misconfigured or the file is accidentally exposed, anyone can read the credentials.

Fixed pattern
<?php
// Use environment variables or a secrets manager
$db_password = getenv('DB_PASSWORD');
$api_key = getenv('API_KEY');

if (!$db_password || !$api_key) {
    die('Required secrets not found in environment.');
}

$mysqli = new mysqli('localhost', 'app_user', $db_password);

// Alternatively, use a secrets manager library (e.g., AWS Secrets Manager, HashiCorp Vault)
// and fetch secrets at runtime, never storing them on disk.
?>

05Prevention Checklist

Use environment variables or a secrets manager
(AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) to store and retrieve sensitive data at runtime, never on disk.
Encrypt sensitive data at rest
using strong encryption (AES-256) if it must be stored; keep encryption keys separate from the encrypted data and in a secure key management system.
Restrict file permissions
on any configuration or data files to the minimum necessary (e.g., chmod 600 for files readable only by the application owner).
Never commit secrets to version control.
Use .gitignore to exclude config files and scan repositories for accidentally committed credentials.
Audit logs and temporary files
for sensitive data; ensure log rotation and secure deletion of temporary files containing secrets.
Use secure credential storage
in databases (hashed passwords, salted tokens) rather than storing plaintext copies anywhere.

06Signs You May Already Be Affected

Check your application's configuration files, logs, and backups for plaintext passwords, API keys, or tokens. Look for .env, config.php, settings.json, or similar files in your codebase or deployed directories that contain unencrypted secrets. Review file permissions on sensitive files—if they are world-readable or readable by unprivileged users, cleartext data is at risk. Examine database backups and old log archives to ensure they do not contain exposed credentials.

07Related Recent Vulnerabilities