The problem
A fintech startup discovered their AWS keys, Stripe secret keys, database passwords, and JWT secrets were publicly visible in their GitHub repository. A security researcher had found them using a simple GitHub search and responsibly disclosed the issue. The keys had been exposed for 8 months across 127 commits. Their AWS account showed $14,000 in unauthorized crypto mining charges. They faced potential PCI compliance violations and customer data exposure.
How AI created this issue
Developers had been asking ChatGPT for Rails configuration examples. ChatGPT consistently embedded real-looking secrets directly in code:
# ChatGPT's Rails configuration example
# config/initializers/stripe.rb
Rails.configuration.stripe = {
publishable_key: 'pk_test_51KX5H2DFA3kPl0OoQ9TXRnvH',
secret_key: 'sk_test_51KX5H2DFA3kPl0OoYmK8wXuVC'
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
# config/storage.yml - ChatGPT included actual-looking keys
amazon:
service: S3
access_key_id: "AKIAIOSFODNN7EXAMPLE"
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region: us-east-1
bucket: mybucket
# config/database.yml
production:
adapter: postgresql
host: prod-db.c9akciq32.us-east-1.rds.amazonaws.com
database: myapp_production
username: postgres
password: "MyStr0ngP@ssw0rd2023!"
# config/credentials.yml.enc was never mentioned by ChatGPT
ChatGPT never mentioned Rails credentials, environment variables, or secrets management. Developers copied these examples verbatim, committing real secrets that looked like the AI's examples. The AI generated realistic-looking keys that developers replaced with actual keys in the same files.
The solution
- Immediate key rotation: Rotated all exposed credentials within 2 hours
- Git history cleanup: Used BFG Repo-Cleaner to purge secrets from history:
# Remove all secrets from git history bfg --replace-text passwords.txt repo.git git reflog expire --expire=now --all git gc --prune=now --aggressive # Force push cleaned history git push --force --all git push --force --tags
- Rails credentials implementation: Properly configured Rails encrypted credentials:
# Properly using Rails credentials # Run: rails credentials:edit # config/credentials.yml.enc (encrypted) aws: access_key_id: AKIAIOSFODNN7REAL secret_access_key: wJalrXUtnFEMI/REAL/KEY stripe: publishable_key: pk_live_real secret_key: sk_live_real # Access in code Rails.application.credentials.aws[:access_key_id] Rails.application.credentials.stripe[:secret_key] # config/storage.yml - reference credentials amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
- Pre-commit hooks: Added git-secrets to prevent future leaks
- CI/CD secret scanning: Integrated TruffleHog in the pipeline
- Developer training: Mandatory secrets management workshop for all devs
The results
- $14,000 in fraudulent charges reversed by AWS after proving compromise
- Zero secrets exposed in 12 months since implementing controls
- Passed PCI compliance audit with improved security posture
- Deployment time reduced 30% with proper credentials management
- 100% of secrets now encrypted at rest and in transit
- Automated alerts catch any plain text secrets before merge
The team learned that AI examples often use realistic-looking fake credentials that developers mistakenly treat as templates. They now have a strict policy: never put any secret (real or fake) in code. All configuration examples must show environment variable or credentials references, never actual values.
Ready to fix your codebase?
Let us analyze your application and resolve these issues before they impact your users.
Get Diagnostic Assessment →