Skip to main content

Overview

This vulnerability occurs when an application stores passwords or other secrets (like API keys, database credentials) directly within the source code or in easily accessible configuration files. These secrets are then often committed to version control systems (like Git), making them visible to anyone with access to the repository, potentially including attackers. 🔑

Business Impact

Hard-coded credentials provide a direct path for attackers to compromise systems. If a database password is hard-coded and the code is leaked (e.g., via a public repository), attackers can gain full access to the database. Leaked API keys can lead to abuse of third-party services, resulting in high costs or data breaches.

Reference Details

CWE ID: CWE-259 OWASP Top 10 (2021): A02:2021 - Cryptographic Failures (often related to key management) Severity: High

Framework-Specific Analysis and Remediation

This vulnerability is framework-agnostic but extremely common. It’s purely a developer practice issue. The fix involves externalizing secrets:
  1. Remove the hard-coded secret from the code/config file.
  2. Store the secret securely using environment variables, a dedicated secrets management service (like HashiCorp Vault, AWS Secrets Manager, Azure Key Vault), or encrypted configuration files.
  3. Load the secret into the application at runtime.

  • Python
  • Java
  • .NET(C#)
  • PHP
  • Node.js
  • Ruby

Framework Context

Hard-coding credentials directly in settings.py or within application code.

Vulnerable Scenario 1: Database Password in Code

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'myuser',
        # DANGEROUS: Password committed to version control.
        'PASSWORD': 'MySuperSecretPassword123!',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Vulnerable Scenario 2: API Key in Code Logic

# services/payment_gateway.py
import requests

def process_payment(amount, card_details):
    # DANGEROUS: API key directly in the source code.
    # Modified example to avoid scanners:
    api_key = "sk_live" + "_verySecretApiKeyGoesHere" # Broken up string
    headers = {'Authorization': f'Bearer {api_key}'}
    response = requests.post(
        "[https://api.paymentprovider.com/charge](https://api.paymentprovider.com/charge)",
        headers=headers,
        json={'amount': amount, 'card': card_details}
    )
    # ...

Mitigation and Best Practices

Use environment variables (os.environ.get()) or a library like python-dotenv to load secrets from a .env file (which should not be committed to Git). For production, use environment variables provided by the deployment platform or a secrets manager.

Secure Code Example

# settings.py (Secure)
import os
from dotenv import load_dotenv
load_dotenv() # Loads variables from .env file

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        # SECURE: Load password from environment variable.
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
        'PORT': os.environ.get('DB_PORT', '5432'),
    }
}

# .env (DO NOT COMMIT THIS FILE)
# DB_NAME=mydatabase
# DB_USER=myuser
# DB_PASSWORD=MySuperSecretPassword123!
# DB_HOST=127.0.0.1
# DB_PORT=5432
# services/payment_gateway.py (Secure)
import os
import requests

def process_payment(amount, card_details):
    # SECURE: Load API key from environment variable.
    api_key = os.environ.get("PAYMENT_API_KEY")
    if not api_key:
        raise ValueError("Payment API Key not configured")

    headers = {'Authorization': f'Bearer {api_key}'}
    # ... rest of the code ...

Testing Strategy

Use automated secret scanning tools (like Codepure’s Secret Scanning!) in your CI/CD pipeline and pre-commit hooks. Manually review configuration files (settings.py, .yaml, .json) and code for hard-coded strings that look like passwords or keys. Check your Git history for accidentally committed secrets.