The Secrets Problem
Every application depends on secrets: API keys, database passwords, encryption keys, OAuth tokens, and TLS certificates. Mishandling these secrets is one of the most common causes of security breaches. A single hardcoded credential committed to a public repository can compromise your entire infrastructure within minutes.
Where Secrets Go Wrong
| Mistake | Consequence |
|---------|-------------|
| Hardcoded in source code | Credentials exposed in version control |
| Stored in environment files committed to git | Accidental exposure in public repos |
| Shared via chat or email | Unbounded access, no audit trail |
| Stored in config files with wide permissions | Accessible to any process on the machine |
| Logged during debugging | Credentials visible in log aggregation systems |
The Vault Pattern
A secrets vault is a centralized service that stores, manages, and audits access to secrets. Applications request secrets at runtime rather than reading them from configuration files.
HashiCorp Vault
# Start Vault in development mode
vault server -dev
# Store a secret
vault kv put secret/database \
host=db.example.com \
port=5432 \
username=app_user \
password=$(openssl rand -base64 32)
# Read a secret
vault kv get secret/database
Vault Integration with Application Code
import hvac
client = hvac.Client(url='https://vault.example.com',
token=get_vault_token())
secret = client.secrets.kv.read_secret_version(
path='database'
)
db_password = secret['data']['data']['password']
# Use the secret to connect
conn = psycopg2.connect(
host=secret['data']['data']['host'],
password=db_password
)
Cloud-Native Solutions
AWS Secrets Manager
import boto3
from botocore.exceptions import ClientError
def get_secret(secret_name):
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])
# Automatic rotation
db_creds = get_secret('prod/database/credentials')
GCP Secret Manager
from google.cloud import secretmanager
def access_secret_version(secret_id, version_id="latest"):
client = secretmanager.SecretManagerServiceClient()
name = f"projects/my-project/secrets/{secret_id}/versions/{version_id}"
response = client.access_secret_version(name=name)
return response.payload.data.decode("UTF-8")
Secrets in CI/CD
Never store secrets in repository CI/CD configuration files that are committed to source control. Use each platform's native secrets store:
| Platform | How to Store Secrets |
|----------|---------------------|
| GitHub Actions | Settings > Secrets and variables > Actions |
| GitLab CI | Settings > CI/CD > Variables |
| CircleCI | Project Settings > Environment Variables |
| Jenkins | Manage Jenkins > Credentials |
# GitHub Actions workflow with secrets
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh
Detecting Secret Leaks
Pre-Commit Hooks
Use tools like `git-secrets` or `truffleHog` as pre-commit hooks:
# Install git-secrets
brew install git-secrets
git secrets --install
git secrets --register-aws
# Scan for secrets before commit
#!/bin/sh
# .git/hooks/pre-commit
git secrets --scan
Scanning Repositories
# Scan the entire history
trufflehog git https://github.com/example/repo.git
# Scan with Gitleaks
gitleaks detect --source . --verbose
Rotation and Expiration
Secrets should have a limited lifetime. Implement automatic rotation:
# Example: Zero-downtime DB password rotation
# Phase 1: Update app to accept both old and new passwords
# Phase 2: Rotate master password in database
# Phase 3: Update app to use only new password
# Phase 4: Revoke old password
The Principle of Least Privilege
Secrets should be scoped to what a particular service or developer needs:
Summary
Treat secrets as the critical infrastructure they are. Use a dedicated secrets vault in production, store them in platform-native secret stores for CI/CD, never hardcode them or commit them to version control, and implement automatic rotation. Combine these practices with regular scanning for leaked secrets and strict access control to minimize the blast radius of any exposure.