Skip to content

CWE-615: Inclusion of Sensitive Information in Source Code Comments

Overview

Sensitive information in comments (passwords, API keys, internal IPs, TODOs about security issues) is exposed to anyone with source code access (version control, decompiled code, client-side JavaScript), and remains in git history even after removal.

OWASP Classification

A01:2025 - Broken Access Control

Risk

Medium-High: Comments leak credentials, API keys, database passwords, internal architecture, security vulnerabilities (TODOs), PII, and provide attackers reconnaissance data. Git history preserves deleted comments forever.

Remediation Steps

Core principle: Never allow comments or development artifacts containing sensitive or internal information to be exposed in client-visible responses; only explicitly intended runtime content may be delivered to users.

Locate Sensitive Information in Comments

When reviewing security scan results:

  • Search for credentials: Passwords, API keys, database credentials in comments
  • Find internal information: IP addresses, server names, internal URLs
  • Check for security TODOs: Comments revealing vulnerabilities
  • Look for PII: SSNs, credit cards, personal data in test comments
  • Review commented-out code: Old passwords, API keys that were "disabled"

Search patterns:

# Credentials
grep -ri "password" --include="*.java" --include="*.py" --include="*.js"
grep -ri "api[_-]key" .
grep -ri "secret" --include="*.java"
grep -ri "token" | grep -E "#|//|/\*"

# Security issues
grep -ri "TODO.*security\|TODO.*vuln\|FIXME.*inject" .
grep -ri "XXX\|HACK\|FIXME" .

# Internal info
grep -rE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" --include="*.java" | grep -E "#|//"

Remove All Sensitive Comments (Primary Defense)

# BAD - credentials exposed in comments
# Database password: P@ssw0rd123
# API Key: sk_live_abc123xyz789
# Admin username: superadmin

db_config = {
    'host': 'localhost',
    'user': 'admin',
    # 'password': 'admin123'  # OLD PASSWORD - still visible!
}

# GOOD - no sensitive data in comments
db_config = {
    'host': os.getenv('DB_HOST'),
    'user': os.getenv('DB_USER'),
    'password': os.getenv('DB_PASSWORD')
}

Why this works: Comments are visible to anyone with source code access - developers, contractors, attackers who compromise repositories, users of client-side JavaScript. Removing sensitive data from comments eliminates this exposure.

Types of sensitive comments to remove:

# Credentials - DELETE
# DB_PASSWORD=supersecret
# export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
# Stripe key: sk_live_abc123

# Internal architecture - DELETE
# Production server: 10.0.1.50:8080
# Admin panel: https://internal.company.com/admin
# Database: prod-db.internal:5432

# Security vulnerabilities - FIX THEN DELETE
# TODO: This is vulnerable to SQL injection
# HACK: Bypassing authentication for testing
# FIXME: XSS possible here

# PII - DELETE
# Test with: john.doe@example.com / SSN: 123-45-6789
# Customer ID: 12345, CC: 4111-1111-1111-1111

Delete Commented-Out Sensitive Code (Don't Disable, Remove)

// BAD - old credentials still visible
// const API_KEY = 'sk_live_old_real_key_here';  // Old key
// const DB_PASSWORD = 'oldPassword123';  // Deprecated
const API_KEY = process.env.API_KEY;  // New approach

// GOOD - completely removed, use version control for history
const API_KEY = process.env.API_KEY;

Why commenting out is dangerous:

  • Commented code is still visible in source
  • Remains in git history forever
  • Developers forget it's there
  • Contains real credentials (not fake examples)
  • Often "temporary" comments become permanent

Proper approach:

# Delete sensitive code, use git history if needed
git log -p -- path/to/file.py  # View deleted code

# Don't keep sensitive data in comments
# Version control is your backup, not comments

Remove Security TODO Comments (Fix the Issue First)

// BAD - reveals vulnerability to code reviewers/attackers
public void authenticate(String password) {
    // TODO: This is vulnerable to SQL injection, fix later
    String sql = "SELECT * FROM users WHERE password = '" + password + "'";
    // TODO: Need to add rate limiting
    // FIXME: Password stored in plaintext
    executeQuery(sql);
}

// GOOD - fix the vulnerability, then remove TODO
public void authenticate(String password) {
    // Use parameterized query to prevent injection
    String sql = "SELECT * FROM users WHERE password_hash = ?";
    PreparedStatement stmt = connection.prepareStatement(sql);
    stmt.setString(1, hashPassword(password));
    return stmt.executeQuery();
}

Security TODO patterns to fix and remove:

  • TODO: Fix SQL injection → Fix it, then remove comment
  • HACK: Bypassing auth for testing → Remove bypass, delete comment
  • FIXME: No input validation → Add validation, remove comment
  • XXX: Insecure temp solution → Implement proper solution

Clean Git History of Sensitive Comments

# Search git history for sensitive comments
git log -p | grep -i "password"
git log -p | grep -i "api[_-]key"
git log -S "TODO.*security" --all

# Find all commits containing "password" in comments
git log -p --all | grep -B5 -A5 "# password:"

# Even deleted files remain in history
git log --all --full-history -- "**/secrets.py"

# Remove sensitive data from git history (DESTRUCTIVE)
# Option 1: BFG Repo-Cleaner (recommended)
bfg --replace-text passwords.txt  # Remove text patterns

# Option 2: git filter-repo (modern)
git filter-repo --path secrets.txt --invert-paths

# Option 3: git filter-branch (old, slow)
git filter-branch --tree-filter 'rm -f config/secrets.yml' HEAD

# After rewriting history, force push
git push --force --all
git push --force --tags

# Notify team - everyone must re-clone

Warning: Rewriting git history affects all developers:

  • Everyone must re-clone repository
  • Breaks existing branches/PRs
  • Doesn't remove from forks/clones
  • Rotate any exposed credentials immediately

Prevent Future Sensitive Comments

Pre-commit hooks:

# .git/hooks/pre-commit
#!/bin/bash

# Scan staged changes for sensitive patterns
if git diff --cached | grep -iE "password|api[_-]?key|secret"; then
    echo "ERROR: Potential sensitive data in comments"
    echo "Review your changes before committing"
    exit 1
fi

if git diff --cached | grep -iE "TODO.*(security|vuln|inject|XSS)"; then
    echo "WARNING: Security TODO found - fix before committing"
    exit 1
fi

Automated scanning:

# Install git-secrets
git secrets --install
git secrets --register-aws  # AWS patterns

# Add custom patterns
git secrets --add 'password\s*[:=]'
git secrets --add 'api[_-]?key\s*[:=]'

# Scan commits
git secrets --scan
git secrets --scan-history

# TruffleHog for entropy-based detection
trufflehog --regex --entropy=True .

# Gitleaks
gitleaks detect --source . --verbose

Client-side code protection:

// BAD - visible in browser source
// Admin API endpoint: https://api.internal.com/admin
// Test token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

function authenticate() {
    // Demo bypass: username=demo password=demo123
    // ANYONE can see this in browser DevTools!
}

// GOOD - no sensitive comments in client-side code
function authenticate(username, password) {
    return fetch('/api/auth', {
        method: 'POST',
        body: JSON.stringify({ username, password })
    });
}

Testing:

# Test pre-commit hook
echo "# password: test123" >> test.py
git add test.py
git commit -m "test"  # Should fail

# Scan entire codebase
grep -r "password" . | grep -E "#|//|/\*"
# Expected: No matches with actual passwords

# Check git history
git log -p | grep -i "api.?key" | wc -l
# Expected: 0 or only references to environment variables

Common Vulnerable Patterns

Credentials in Comments

# Credentials
# username: admin, password: admin123
# DB_PASSWORD=supersecret
# export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE

Why is this vulnerable: Comments are plain text visible to anyone with source code access - developers, contractors, code reviewers, and attackers who compromise the repository. Even if access is restricted, client-side JavaScript comments are visible in the browser's "View Source" feature. Credentials in comments enable immediate system compromise without requiring any exploitation techniques.

API Keys in Comments

# API Keys
# Stripe key: sk_live_abc123
# // Firebase config: AIzaSyBxyz123

Why is this vulnerable: Live API keys in comments grant direct access to third-party services with your account's privileges and billing. Attackers can use exposed Stripe keys to process fraudulent transactions, Firebase keys to access/modify your database, or AWS keys to launch expensive resources on your account. These keys typically have broad permissions and no rate limiting when used directly.

Internal Information

# Internal information
# Production server: 10.0.1.50
# Admin panel: https://internal.company.com/admin

Why is this vulnerable: Internal IP addresses and URLs provide reconnaissance information that attackers use to map your network topology and identify high-value targets. Knowing the production server's IP enables direct attacks bypassing firewalls or load balancers. Admin panel URLs reveal management interfaces that may have weaker authentication or unpatched vulnerabilities.

Security Issues in Comments

# Security issues
# TODO: Fix XSS vulnerability here
# HACK: Bypassing authentication for testing
# FIXME: SQL injection possible

Why is this vulnerable: Security TODO comments are a roadmap for attackers, explicitly identifying vulnerabilities and their locations. Comments like "HACK: Bypassing authentication" reveal that security controls can be circumvented, potentially showing exactly how. These comments often remain in code for months or years, advertising known vulnerabilities that were never fixed.

PII in Comments

# PII
# Test with john.doe@example.com / SSN: 123-45-6789
# Customer ID: 12345, CC: 4111-1111-1111-1111

Why is this vulnerable: Personal Identifiable Information (PII) in comments violates privacy regulations (GDPR, CCPA) and creates data breach liability. Even if used for testing, real customer data in source code is accessible to all developers and contractors, potentially across geographic boundaries. This data persists in git history even after "deletion" and may be subject to regulatory fines.

Git History Exposure

Searching Git History for Sensitive Data:

# Comments in git history
git log -p | grep -i "password"
git log -S "API_KEY" --all

# Even if file is deleted, comment remains in history!
git log --all --full-history -- "**/config.py"

Why is this vulnerable: Git permanently preserves every version of every file in its history, meaning sensitive comments remain accessible even after being "deleted" from current code. Commands like git log -p reveal all past changes, and git log -S finds when specific strings were added or removed. Even if you delete a file entirely, its contents persist in git history and can be recovered. Attackers who gain repository access can search through years of commits to find credentials that were briefly committed and then removed.

Attempting to Remove from Git History

# Remove from git history (nuclear option)
git filter-branch --tree-filter 'rm -f secrets.txt' HEAD

# Or use git-filter-repo
git filter-repo --path secrets.txt --invert-paths

Why is this vulnerable: While git history rewriting tools can remove sensitive data from the main repository, this process is extremely disruptive - all developers must delete their local clones and re-clone, all open pull requests break, and the process doesn't affect existing forks or backups. More importantly, any credentials that were exposed must be considered permanently compromised and rotated immediately, as there's no way to know if attackers already extracted them. History rewriting is not a security fix, it's damage control after a breach.

JavaScript Comments in Browser Source

// JavaScript comments visible in browser source
// Admin API endpoint: https://api.internal.com/admin
// Use this token for testing: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

function authenticate() {
    // Bypass for demo: username=demo password=demo123
    // Visible to anyone viewing source!
}

Why is this vulnerable: All JavaScript sent to the browser, including comments, is visible to anyone using "View Source" or browser DevTools. Unlike server-side code where comments are only visible to developers with repository access, client-side JavaScript comments are public by default. Attackers can right-click and view source to see API endpoints, authentication bypasses, test credentials, and internal system details. Minification removes comments in production builds, but developers often skip this step or deploy debug builds accidentally, exposing all comments to end users.

Secure Patterns

# Use environment variables

API_KEY = os.getenv('API_KEY')
if not API_KEY:
    raise ValueError("API_KEY not set")

# Use secrets management

import boto3
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId='prod/db/password')

# Document externally, not in code
# Good: See docs/api.md for API key setup
# Bad: API key is abc123xyz
# Pre-commit hooks
# .git/hooks/pre-commit

#!/bin/bash
if git diff --cached | grep -i "password"; then
    echo "WARNING: Potential password in commit"
    exit 1
fi

Dynamic Scan Guidance

For guidance on remediating this CWE when detected by dynamic (DAST) scanners:

Security Checklist

  • All sensitive comments removed from code
  • Commented-out credentials deleted
  • Security TODOs fixed and removed
  • Git history cleaned of sensitive data
  • Pre-commit hooks installed
  • Automated scanning configured (git-secrets, gitleaks)
  • Exposed credentials rotated
  • Team trained on comment security

Additional Resources