Exposure of Sensitive Information Through Environmental Variables
Environment variables are a convenient way to pass configuration to applications, but they are often visible to anyone with access to the system—including…
Environment variables are a convenient way to pass configuration to applications, but they are often visible to anyone with access to the system—including other users, debugging tools, and crash reporting systems. Storing sensitive data like API keys, database passwords, or authentication tokens in environment variables can expose them to unauthorized access. This weakness is particularly dangerous in shared hosting, containerized, or cloud environments where process inspection is easier.
02How It Happens
Developers often use environment variables to avoid hardcoding secrets in source code, which is a good practice in principle. However, environment variables are not encrypted and are readable by any process running under the same user account (or by privileged users). When an application crashes, logs its environment, or is inspected by monitoring or debugging tools, these variables become visible. In containerized environments, environment variables may also be exposed through orchestration platform APIs, image inspection, or container logs. The weakness arises when developers treat environment variables as a secure storage mechanism rather than as a convenient but unencrypted configuration channel.
03Real-World Impact
An attacker with local system access, or one who gains access to logs, crash dumps, or container metadata, can extract credentials and use them to compromise databases, third-party services, or internal systems. In cloud environments, misconfigured access controls on container registries or orchestration platforms can expose environment variables to unauthorized users. This can lead to data breaches, unauthorized API access, lateral movement within infrastructure, or privilege escalation.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import os
import sqlite3
# Sensitive credentials stored in environment variables
db_password = os.getenv('DB_PASSWORD')
api_key = os.getenv('API_KEY')
# These are now accessible to any process inspection tool
connection = sqlite3.connect(':memory:')
cursor = connection.cursor()
cursor.execute(f"SELECT * FROM users WHERE password='{db_password}'")
Why it's vulnerable: Environment variables are readable by any process on the system and visible in process listings, crash dumps, and logs. Storing secrets this way exposes them to unintended access.
Fixed pattern
import os
from pathlib import Path
# Load secrets from a file with restricted permissions (0600)
# or use a secrets management service
secrets_file = Path('/etc/app/secrets.conf')
if secrets_file.stat().st_mode & 0o077:
raise PermissionError("Secrets file has overly permissive permissions")
with open(secrets_file) as f:
config = {}
for line in f:
key, value = line.strip().split('=', 1)
config[key] = value
db_password = config.get('DB_PASSWORD')
Vulnerable pattern
<?php
// Sensitive credentials stored in environment variables
$db_password = getenv('DB_PASSWORD');
$api_key = getenv('API_KEY');
// These are visible in phpinfo(), process listings, and logs
$mysqli = new mysqli('localhost', 'root', $db_password, 'myapp');
if ($mysqli->connect_error) {
error_log("Connection failed: " . $mysqli->connect_error);
}
?>
Why it's vulnerable: Environment variables are exposed through phpinfo(), process inspection tools, and server logs. Any user with shell access or monitoring capabilities can read them.
Fixed pattern
<?php
// Load secrets from a file outside the web root with restricted permissions
$secrets_file = '/etc/app/secrets.conf';
if ((fileperms($secrets_file) & 0o077) !== 0) {
throw new Exception("Secrets file has overly permissive permissions");
}
$config = parse_ini_file($secrets_file, true);
$db_password = $config['database']['password'] ?? null;
$mysqli = new mysqli('localhost', 'root', $db_password, 'myapp');
if ($mysqli->connect_error) {
error_log("Connection failed");
}
?>
05Prevention Checklist
Use a dedicated secrets management system (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) instead of environment variables for production credentials.
If environment variables must be used, restrict file permissions on configuration files to 0600 (readable only by the owner) and store them outside the web root.
Never log, print, or expose environment variables in error messages, crash reports, or debugging output.
Audit process listings and container metadata regularly to ensure secrets are not visible.
Use short-lived credentials and rotate secrets frequently; avoid storing long-term credentials in any configuration mechanism.
In containerized environments, use orchestration platform secret management (Kubernetes Secrets, Docker Swarm secrets) rather than passing secrets as environment variables.
06Signs You May Already Be Affected
Check your application logs, crash reports, and monitoring dashboards for instances where environment variables or their values appear in plaintext. Review process listings on your servers (using ps aux or similar tools) to see if sensitive values are visible. In container environments, inspect image layers and orchestration platform configurations to confirm secrets are not embedded or exposed as environment variables.