Skip to content

CWE-798: Use of Hard-coded Credentials

Overview

Hard-coded credentials occur when authentication secrets (passwords, API keys, encryption keys, tokens) are embedded directly in source code, configuration files, or binaries. This violates the principle of separation of code and configuration - credentials become visible to anyone with code access, changing them requires redeployment, they persist in version control history, and credential rotation becomes nearly impossible.

OWASP Classification

A07:2025 - Authentication Failures

Risk

Hard-coded credentials create severe security risks:

  • Credential exposure: Anyone with source code access can extract credentials
  • Unauthorized access: Attackers can authenticate to databases, APIs, cloud services, or admin interfaces
  • Privilege escalation: Hard-coded admin credentials grant full system access
  • Data breaches: Database credentials expose all stored data
  • Supply chain attacks: Credentials in public repositories enable widespread compromise
  • Compliance violations: Fails PCI-DSS, SOC 2, HIPAA, and most security standards
  • Impossible rotation: Cannot change credentials without code deployment

The impact multiplies when credentials are committed to version control - they remain in git history even after removal.

Remediation Steps

Core principle: Never hard-code credentials; use managed secrets and rotation.

Identify all hard-coded credentials in the codebase

  • Search for credentials: Database passwords, API keys, encryption keys, tokens, certificates
  • Check all sources: Source code, configuration files, environment variables in code, build scripts
  • Review version history: Git history may contain previously removed credentials
  • Scan with tools: git-secrets, TruffleHog, GitGuardian, AWS Secrets Detector, Gitleaks
  • Common patterns: password=, api_key=, secret=, token=, connection strings, Base64-encoded secrets
  • Check test code: Mock credentials in tests may be real production secrets

Migrate to secrets management systems (Primary Defense)

  • Use production-grade secrets managers:
    • AWS: Secrets Manager, Systems Manager Parameter Store
    • Azure: Key Vault
    • Google Cloud: Secret Manager
    • HashiCorp: Vault
    • Kubernetes: Secrets
    • Enterprise: CyberArk, Thycotic, enterprise PAM solutions
  • Implementation pattern:

    1. Application authenticates to secrets manager (via IAM role, service account, Managed Identity)
    2. Retrieves credentials at runtime from secure store
    3. Uses credentials in memory only (never logs or persists)
    4. Credentials can be rotated without code changes or redeployment
    • Why this works: Credentials never exist in code; centralized management enables auditing, rotation, and access control
    • Best practices:
      • Use IAM roles/Managed Identities (no credentials to access secrets manager)
      • Enable automatic rotation for database passwords and API keys
      • Cache secrets to reduce API calls (with TTL)
      • Specify secret versions in production (avoid "latest")
      • Never log or print retrieved secrets

Use environment variables (Minimum alternative if secrets manager unavailable)

  • Store in environment: Set credentials as environment variables outside code
  • Read at runtime: Application reads from os.getenv(), process.env, Environment.GetEnvironmentVariable()
  • Never commit .env files: Add .env, secrets.*, credentials.* to .gitignore immediately
  • Secure deployment: Use platform-specific secret storage (Kubernetes Secrets, Docker secrets, cloud-native config)
  • Separate by environment: Different credentials for dev, staging, production
  • Warning: Environment variables less secure than secrets managers (visible in process listings, container configs) but better than hard-coded

Remove credentials from version control

  • Immediate actions:
    • Rotate ALL exposed credentials immediately
    • Remove from current code
    • Scrub git history
    • Force push cleaned history
    • Revoke exposed keys
  • Prevention:
    • Add .gitignore: Include *.env, secrets.*, credentials.*, *.pem, *.key
    • Use pre-commit hooks: git-secrets, detect-secrets to block credential commits
    • Enable secret scanning: GitHub Secret Scanning, GitLab Secret Detection, AWS CodeGuru
    • Code review: Require peer review for any config changes

Implement least privilege and credential rotation

  • Least privilege:
    • Use credentials with minimal required permissions (read-only database user if writes not needed)
    • Separate credentials by environment (dev, staging, prod)
    • Use different credentials for different services/microservices
    • Apply IP allow listing where possible
    • Use temporary credentials (AWS STS, OAuth tokens with expiration)
  • Credential rotation:
    • Rotate credentials regularly (30-90 days for production)
    • Automate rotation with secrets manager
    • Support multiple active credentials during rotation (zero-downtime)
    • Monitor for use of old credentials after rotation
    • Test rotation process regularly

Test and verify credential removal thoroughly

  • Scan codebase: Run credential detection tools (git-secrets, TruffleHog, Gitleaks)
  • Check build artifacts: Ensure secrets not in compiled binaries or Docker images
  • Review configurations: Verify no secrets in config files (application.properties, web.config, settings.py)
  • Test application: Confirm it retrieves secrets from secure store (secrets manager or environment)
  • Audit access logs: Monitor who accesses secrets in secrets manager
  • Verify rotation: Test that rotated credentials work and old ones are rejected
  • Check git history: git log -p | grep -i "password" to ensure history is clean
  • Re-scan with security tools: Confirm findings are resolved
  • Verify environment isolation: Test dev uses dev credentials, prod uses prod credentials

1. Code Scanning

# Search for common credential patterns

grep -r "password\s*=\s*['\"]" .
grep -r "api_key\s*=\s*['\"]" .
grep -r "secret\s*=\s*['\"]" .
grep -r "jdbc:.*://.*:.*@" .

# Use automated tools

truffleHog filesystem ./
gitleaks detect --source . --verbose
git-secrets --scan

Expected result: No hard-coded credentials found in code.

2. Configuration Verification

  • Verify credentials loaded from secrets manager/environment variables
  • Test application startup with missing credentials (should fail gracefully with clear error)
  • Verify different credentials used in dev vs. production
  • Check logs don't expose credentials

3. Credential Rotation Test

  • Rotate a credential in secrets manager
  • Verify application picks up new credential (with or without restart, depending on design)
  • Confirm old credential no longer works
  • Ensure no downtime during rotation

4. Version Control Audit

# Scan entire git history for secrets

truffleHog git file://. --since_commit HEAD~100
gitleaks detect --source . --log-opts="--all"

Expected result: No credentials in current code or git history.

Language-Specific Guidance

For detailed implementation examples in specific programming languages:

  • C# - Azure Key Vault, DefaultAzureCredential, configuration providers
  • Java - AWS SDK, Azure SDK, Spring Boot externalized configuration
  • JavaScript/Node.js - dotenv, AWS SDK, Azure Key Vault, Google Secret Manager, HashiCorp Vault, Kubernetes secrets
  • PHP - Environment variables, Vault SDK, database credential management
  • Python - boto3 for AWS Secrets Manager, environment variables, python-dotenv

Additional Resources