This guide explains how to properly handle secrets, credentials, and sensitive information in the Mobile Money project.
NEVER commit the following to the repository:
- API keys or tokens
- Database passwords
- SSH keys or private keys
- OAuth secrets or client secrets
- AWS credentials
- Encryption keys
- JWT secrets
- Stellar secret keys
- Webhook URLs with authentication
- Personal access tokens (PATs)
- Any hardcoded credentials
NEVER, even in a private commit:
- Hardcode secrets in source files
- Include secrets in
src/directory - Add credentials to configuration files that are version-controlled
- Comment out secrets in code (they can be extracted from git history)
Always use environment variables for sensitive information.
// ❌ WRONG - Hardcoded secret
const dbPassword = "super_secret_password_123";
const db = new Database(dbPassword);
// ✅ RIGHT - Environment variable
const dbPassword = process.env.DATABASE_PASSWORD;
if (!dbPassword) {
throw new Error("DATABASE_PASSWORD environment variable is required");
}
const db = new Database(dbPassword);Create a .env file (DO NOT commit this file):
# .env (local development only - NOT in version control)
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
REDIS_URL=redis://localhost:6379
JWT_SECRET=your-local-dev-secret-key
STELLAR_ISSUER_SECRET=SBX...Use GitHub Actions Secrets or your deployment platform's secret management:
- Never store in
.env.examplewith real values - Use
.env.exampleas a template only
# .env.example - Template ONLY, do not store real secrets
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
REDIS_URL=redis://localhost:6379
JWT_SECRET=replace-with-your-secret
STELLAR_ISSUER_SECRET=replace-with-your-keyValidate required secrets on application startup:
// src/config.ts
export function validateSecrets(): void {
const requiredSecrets = [
'DATABASE_PASSWORD',
'JWT_SECRET',
'STELLAR_ISSUER_SECRET',
];
for (const secret of requiredSecrets) {
if (!process.env[secret]) {
throw new Error(`Required environment variable not set: ${secret}`);
}
}
}For CI/CD pipelines, use GitHub Actions Secrets:
- Go to repository Settings → Secrets and variables → Actions
- Click "New repository secret"
- Add secret name and value
- Reference in workflows:
${{ secrets.SECRET_NAME }}
Example workflow:
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}This project uses GitGuardian via GitHub Actions to automatically scan for accidentally committed secrets.
Install and run ggshield locally before committing:
pip install pre-commitpre-commit install# Scan entire repository
ggshield secret scan repo .
# Scan latest commit
ggshield secret scan commit HEAD
# Scan before staging
ggshield secret scan pre-commitGitGuardian runs automatically on all PRs via .github/workflows/gitguardian.yml.
What to do if a secret is detected:
- ❌ DO NOT merge the PR
- 🔑 Revoke the compromised secret immediately (reset password, rotate API key, etc.)
- 🗑️ Remove the secret from the PR
- ✨ Replace with environment variable or proper secret management
- 🔄 Force-push to update the branch history
- ✅ Re-run the GitGuardian check
# Amend the commit
git add .
git commit --amend --no-edit
# Force push to your branch
git push --force-with-lease origin feature/your-feature# Using git-filter-branch (for entire history)
git filter-branch --tree-filter 'sed -i "s/hardcoded_secret/$(process.env.SECRET_VAR)/g" src/file.ts' HEAD
# Then force push
git push --force-with-lease origin feature/your-feature# Install: https://rtyley.github.io/bfg-repo-cleaner/
# Remove a string:
bfg --replace-text "secret_value.txt" -- .git/refs
# Push
git push --force-with-lease- No hardcoded API keys in code
- No hardcoded passwords in code
- No hardcoded Stellar secret keys
- All sensitive values use
process.env.* -
.envfile is in.gitignore -
.env.examplehas placeholders only - No secrets in config files
- No secrets in comments
- Pre-commit hook ran successfully
- No warnings from ggshield
If you accidentally commit a secret:
- Immediately notify the team via private email or Slack
- Revoke the compromised secret in all systems
- Report the incident to the security team
- Follow the remediation steps above
Remember: It's not a question of IF you'll accidentally commit a secret, but WHEN. Have a plan!