Description
Passwords, API keys, and authentication tokens embedded in application code may be exposed when the code is disclosed.
Potential impact
- Secret exposure: An attacker may obtain secrets from the source code.
- Account takeover: Exposed secrets may allow access to accounts.
- API abuse: An attacker may misuse services with leaked API keys.
Remediation
- Supply secrets through environment variables instead of embedding them in code.
- Use a secret manager such as HashiCorp Vault or AWS Secrets Manager.
- Review and audit code for embedded secrets.
Revoke exposed secrets and replace them with new values. Restrict access to environment variables too, and keep their values out of logs.
Examples
Django
Before
python
# Hardcoded Django secrets
SECRET_KEY = 'your-hardcoded-secret-key'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
After
python
# Django secrets supplied through the environment
import os
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT'),
}
}
Explanation:
- Before:
SECRET_KEYand the database password are embedded in the source. - After: Secrets come from the environment and are not stored in the source.
Flask
Before
python
# Hardcoded Flask secrets
class Config:
SECRET_KEY = 'your-hardcoded-secret-key'
SQLALCHEMY_DATABASE_URI = 'postgresql://myuser:mypassword@localhost/mydatabase'
After
python
# Flask secrets supplied through the environment
import os
class Config:
SECRET_KEY = os.getenv('FLASK_SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
Explanation:
- Before:
SECRET_KEYand credentials in the database URI are embedded in the source. - After: Secrets come from the environment and are not stored in the source.
FastAPI
Before
python
# Hardcoded FastAPI session secret
from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key='your-hardcoded-secret-key', https_only=True)
After
python
# FastAPI session secret supplied through the environment
from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware
import os
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key=os.environ['FASTAPI_SECRET_KEY'], https_only=True)
Explanation:
- Before: The session middleware's
secret_keyis embedded in the source. - After: The session secret comes from the environment instead.