# Use of Hard-coded Credentials (CWE-798) The product contains hard-coded credentials, such as a password or cryptographic key, which it uses for its own inbound authentication, outbound communication to external components, or encryption of internal data. - Prevalence: High Frequently exploited - Impact: Critical 6 critical-severity rules - Prevention: Documented 11 fix examples **OWASP:** Identification and Authentication Failures (A07:2021-Identification and Authentication Failures) - #7 ## Description Hard-coded credentials typically create a significant hole that allows an attacker to bypass the authentication that has been configured by the product administrator. This hole might be difficult for the system administrator to detect. ## Prevention Prevention strategies for Hardcoded Credentials based on 11 Shoulder detection rules. ### Key Practices - loaded from environment variables or secure secret management systems - stored in environment variables or secure vaults - stored in environment variables or secure vaults, never committed to version control ### Python Load SECRET_KEY from environment variables, never commit it to source control Store all credentials in environment variables or a secrets manager, never in code Load all secrets from environment variables or a secrets manager ### Docker Use BuildKit secrets or runtime environment variables instead of hardcoded credentials ### Go Load secrets from environment variables or a secrets manager instead of hardcoding ### Node.js Never use hardcoded fallbacks for secrets; fail fast if environment variables are missing Load credentials from environment variables instead of hardcoding in source code Move secrets to environment variables using dotenv or a secret manager ### Kubernetes Use Kubernetes Secrets with secretKeyRef instead of hardcoding credentials in manifests ## Warning Signs - [HIGH] Hardcoded secret used as fallback for environment variable. Code: ... If the environment variable is not set, this har - [HIGH] hardcoded secrets used as fallback values for environment variables - [HIGH] Hardcoded credential detected in ... Credentials should never be stored in source code. - [HIGH] hardcoded credentials (passwords, API keys, tokens) in database connections and configuration object - [HIGH] hardcoded passwords, API keys, tokens, and other credentials in source code - [LOW] Test file contains hard-coded credentials at line ... - [LOW] security anti-patterns in test files that could leak into production - [CRITICAL] Django SECRET_KEY that is hardcoded, weak, or uses default values ## Consequences - Gain Privileges - Bypass Protection Mechanism ## Mitigations - Store credentials outside of the source code - Use environment variables or secure credential stores - Implement proper key management procedures ## Detection - Total rules: 11 - Critical: 6 - Languages: python, dockerfile, go, javascript, typescript, yaml ## Rules by Language ### Javascript (5 rules) - **Hardcoded Secret in Environment Variable Fallback** [HIGH]: Detects hardcoded secrets used as fallback values for environment variables. Pattern: `process.env.SECRET || 'hardcoded-value'` This is dangerous because: - If the environment variable is not set, the hardcoded value is used - Developers often forget to set env vars in production - The hardcoded fallback may be committed to version control - Creates false sense of security ("we use env vars") This is particularly common with: - JWT secrets - API keys - Database passwords - Encryption keys - Remediation: Remove the fallback and fail fast if the env var is missing: Before (dangerous): const secret = process.env.JWT_SECRET || 'insecure-fallback'; After (safe): const secret = process.env.JWT_SECRET; if (!secret) { throw new Error('JWT_SECRET environment variable is required'); } - **Hardcoded Credentials** [HIGH]: Detects hardcoded credentials (passwords, API keys, tokens) in database connections and configuration objects. Credentials should be loaded from environment variables or secure secret management systems. This is different from CWE-259 (weak password): - CWE-798: Any credential hardcoded in source code (security risk) - CWE-259: Specifically weak/guessable passwords Even a "strong" password is a security risk if hardcoded because: - It gets committed to version control - It's difficult to rotate - It may leak via logs, error messages, or decompilation - No separation between dev/prod environments - Remediation: Move credentials to environment variables: Before: password: 'my-secret-password' After: password: process.env.DB_PASSWORD - **Hardcoded High-Entropy Secrets Detection** [CRITICAL]: Detects hardcoded secrets with high entropy (randomness) that indicate real credentials. This rule uses entropy analysis to avoid false positives from: - Example/placeholder values ("keyboard cat", "your-secret-here") - Test fixtures ("test123", "fake-api-key") - Short/simple strings ("secret", "password") Only flags strings that appear to be REAL secrets: - High entropy (random-looking characters) - Sufficient length (20+ characters for API keys) - Known secret patterns (AWS keys, JWT tokens, private keys) Hardcoded real secrets pose security risks: - Exposure in version control - Difficult credential rotation - Accidental disclosure in logs/errors - No dev/prod separation - Remediation: Move this secret to environment variables or a secret management service. - **Hardcoded Secrets in Security Operations** [CRITICAL]: Detects hardcoded secrets (API keys, tokens, passwords) flowing into security-sensitive operations. Uses taint analysis to track hardcoded secret strings from their definition to actual usage in authentication, API calls, or cryptographic operations. This approach reduces false positives by only flagging secrets that are actually used, not just defined in comments, examples, or unused variables. - Remediation: Load secrets from environment variables instead of hardcoding: ```javascript require('dotenv').config(); const stripe = require('stripe')(process.env.STRIPE_API_KEY); if (!process.env.STRIPE_API_KEY) { throw new Error('STRIPE_API_KEY environment variable required'); } ``` Learn more: https://shoulder.dev/learn/javascript/cwe-798/hardcoded-secrets - **Security Issues in Test Files** [LOW]: Detects security anti-patterns in test files that could leak into production. While test files don't run in production, they can still pose security risks: 1. **Hard-coded credentials** - Test credentials committed to repos 2. **Real API keys** - Production keys used in tests 3. **Exposed secrets** - Secrets in test fixtures or mocks 4. **Insecure test patterns** - Patterns that might be copy-pasted to production This rule helps maintain test hygiene and prevents credential leaks. - Remediation: Use environment variables or mock data instead of hard-coded credentials. ### Typescript (5 rules) - **Hardcoded Secret in Environment Variable Fallback** [HIGH]: Detects hardcoded secrets used as fallback values for environment variables. Pattern: `process.env.SECRET || 'hardcoded-value'` This is dangerous because: - If the environment variable is not set, the hardcoded value is used - Developers often forget to set env vars in production - The hardcoded fallback may be committed to version control - Creates false sense of security ("we use env vars") This is particularly common with: - JWT secrets - API keys - Database passwords - Encryption keys - Remediation: Remove the fallback and fail fast if the env var is missing: Before (dangerous): const secret = process.env.JWT_SECRET || 'insecure-fallback'; After (safe): const secret = process.env.JWT_SECRET; if (!secret) { throw new Error('JWT_SECRET environment variable is required'); } - **Hardcoded Credentials** [HIGH]: Detects hardcoded credentials (passwords, API keys, tokens) in database connections and configuration objects. Credentials should be loaded from environment variables or secure secret management systems. This is different from CWE-259 (weak password): - CWE-798: Any credential hardcoded in source code (security risk) - CWE-259: Specifically weak/guessable passwords Even a "strong" password is a security risk if hardcoded because: - It gets committed to version control - It's difficult to rotate - It may leak via logs, error messages, or decompilation - No separation between dev/prod environments - Remediation: Move credentials to environment variables: Before: password: 'my-secret-password' After: password: process.env.DB_PASSWORD - **Hardcoded High-Entropy Secrets Detection** [CRITICAL]: Detects hardcoded secrets with high entropy (randomness) that indicate real credentials. This rule uses entropy analysis to avoid false positives from: - Example/placeholder values ("keyboard cat", "your-secret-here") - Test fixtures ("test123", "fake-api-key") - Short/simple strings ("secret", "password") Only flags strings that appear to be REAL secrets: - High entropy (random-looking characters) - Sufficient length (20+ characters for API keys) - Known secret patterns (AWS keys, JWT tokens, private keys) Hardcoded real secrets pose security risks: - Exposure in version control - Difficult credential rotation - Accidental disclosure in logs/errors - No dev/prod separation - Remediation: Move this secret to environment variables or a secret management service. - **Hardcoded Secrets in Security Operations** [CRITICAL]: Detects hardcoded secrets (API keys, tokens, passwords) flowing into security-sensitive operations. Uses taint analysis to track hardcoded secret strings from their definition to actual usage in authentication, API calls, or cryptographic operations. This approach reduces false positives by only flagging secrets that are actually used, not just defined in comments, examples, or unused variables. - Remediation: Load secrets from environment variables instead of hardcoding: ```javascript require('dotenv').config(); const stripe = require('stripe')(process.env.STRIPE_API_KEY); if (!process.env.STRIPE_API_KEY) { throw new Error('STRIPE_API_KEY environment variable required'); } ``` Learn more: https://shoulder.dev/learn/javascript/cwe-798/hardcoded-secrets - **Security Issues in Test Files** [LOW]: Detects security anti-patterns in test files that could leak into production. While test files don't run in production, they can still pose security risks: 1. **Hard-coded credentials** - Test credentials committed to repos 2. **Real API keys** - Production keys used in tests 3. **Exposed secrets** - Secrets in test fixtures or mocks 4. **Insecure test patterns** - Patterns that might be copy-pasted to production This rule helps maintain test hygiene and prevents credential leaks. - Remediation: Use environment variables or mock data instead of hard-coded credentials. ### Python (3 rules) - **Django Insecure SECRET_KEY** [CRITICAL]: Detects Django SECRET_KEY that is hardcoded, weak, or uses default values. The SECRET_KEY is used for cryptographic signing and must be kept secret and changed in production. - Remediation: Load SECRET_KEY from environment variables. ```python import os SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] ``` Generate a strong key: `python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'` Learn more: https://shoulder.dev/learn/python/cwe-798/secret-key - **Hardcoded Credentials** [HIGH]: Detects hardcoded passwords, API keys, tokens, and other credentials in source code. Credentials should be stored in environment variables or secure vaults. - Remediation: Store credentials in environment variables instead of source code. ```python import os password = os.getenv('DB_PASSWORD') api_key = os.environ['API_KEY'] secret_key = os.getenv('SECRET_KEY') ``` Learn more: https://shoulder.dev/learn/python/cwe-798/hardcoded-credentials - **Hardcoded Secrets / Credentials** [HIGH]: Detects hardcoded secrets, passwords, API keys, and cryptographic keys in source code. Secrets should be stored in environment variables or secure vaults, never committed to version control. - Remediation: Load secrets from environment variables, never hardcode them. ```python import os from flask import Flask app = Flask(__name__) app.config['SECRET_KEY'] = os.environ['SECRET_KEY'] API_KEY = os.environ['API_KEY'] DATABASE_PASSWORD = os.environ['DB_PASSWORD'] ``` Learn more: https://shoulder.dev/learn/python/cwe-798/hardcoded-secrets ### Dockerfile (1 rules) - **Docker Secrets and Security Best Practices** [CRITICAL]: Detects hardcoded secrets in ENV/ARG and piping curl/wget to shell. - Remediation: Use BuildKit secrets instead of hardcoding credentials. ```dockerfile RUN --mount=type=secret,id=token \ cat /run/secrets/token ``` Learn more: https://shoulder.dev/learn/docker/cwe-798/secrets-security ### Go (1 rules) - **Hardcoded Secrets in Source Code** [CRITICAL]: API keys, passwords, or tokens hardcoded in source code. - Remediation: Load secrets from environment variables instead of hardcoding them. ```go import "os" apiKey := os.Getenv("API_KEY") if apiKey == "" { log.Fatal("API_KEY not set") } ``` Learn more: https://shoulder.dev/learn/go/cwe-798/hardcoded-secrets ### Yaml (1 rules) - **Hardcoded Secrets in Manifest** [CRITICAL]: Detects hardcoded secrets, passwords, or API keys in Kubernetes manifests. - Remediation: Use Kubernetes Secrets with valueFrom. ```yaml env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password ``` Learn more: https://shoulder.dev/learn/kubernetes/cwe-798/hardcoded-secrets