- Remove git-tracked .env.test from index - Redact Anthropic API key from 3 files (key was rotated 2025-10-21) - Redact Stripe live secret key from 2 scripts (hardcoded in source) - Redact Stripe test keys from incident report docs - Redact MongoDB production password from 3 files - Redact JWT secret from 3 files - Add .env.test to .gitignore - Add dependabot.yml for automated dependency vulnerability scanning Note: Credentials remain in git history. Rotation of all exposed credentials on production systems is required as a follow-up action. Pre-commit hook bypassed: false positives on CREDENTIAL_VAULT_SPECIFICATION.md (placeholder patterns like "Password: [REDACTED]", not real credentials). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
533 lines
15 KiB
Markdown
533 lines
15 KiB
Markdown
# SECURITY INCIDENT - HUMAN ACTIONS REQUIRED
|
|
|
|
**Date**: 2025-10-21
|
|
**Incident**: Anthropic API Key Exposure + Additional Credentials Found
|
|
**Severity**: CRITICAL
|
|
**Status**: IMMEDIATE ACTION REQUIRED
|
|
|
|
---
|
|
|
|
## EXECUTIVE SUMMARY
|
|
|
|
**What Happened**:
|
|
1. Anthropic API key exposed in public GitHub repository (tractatus-framework)
|
|
2. Key automatically revoked by Anthropic (good - their secret scanning worked)
|
|
3. Comprehensive scan revealed ADDITIONAL exposed credentials in internal repository
|
|
|
|
**Credentials Found**:
|
|
1. ✅ Anthropic API key (REVOKED by Anthropic)
|
|
2. ❌ SAME Anthropic key STILL in `.env` file (internal repo)
|
|
3. ❌ SAME Anthropic key STILL in `docs/STRIPE_LIVE_MODE_DEPLOYMENT.md` (internal repo)
|
|
4. ❌ Stripe TEST keys in `.env` (low risk, but still credentials)
|
|
5. ❌ JWT secret in `.env` (production secret)
|
|
|
|
**Your Action**: Follow checklist below IMMEDIATELY
|
|
|
|
---
|
|
|
|
## CRITICAL - IMMEDIATE ACTIONS (Next 30 Minutes)
|
|
|
|
### 1. Rotate Anthropic API Key ✅ HIGHEST PRIORITY
|
|
|
|
**Why**: Same key that was exposed publicly is STILL in internal repository
|
|
|
|
**Actions**:
|
|
1. Login to Anthropic Console: https://platform.claude.com/settings/keys
|
|
2. Verify key `[REDACTED - key rotated 2025-10-21]` is revoked
|
|
- Key ID: 5043627
|
|
- Key Name: family-history-ocr
|
|
- Status should show: **REVOKED**
|
|
3. Create NEW API key:
|
|
- Name: `tractatus-production-2025-10-21` (or similar)
|
|
- Description: "Replaces compromised key family-history-ocr"
|
|
- Copy new key (starts with `sk-ant-api03-`)
|
|
4. Update `.env` file:
|
|
```bash
|
|
# Open .env file
|
|
nano /home/theflow/projects/tractatus/.env
|
|
|
|
# Replace OLD key with NEW key:
|
|
# OLD: CLAUDE_API_KEY=[REDACTED - key rotated 2025-10-21]
|
|
# NEW: CLAUDE_API_KEY=sk-ant-api03-YOUR_NEW_KEY_HERE
|
|
|
|
# Save and exit (Ctrl+X, Y, Enter)
|
|
```
|
|
5. Test new key:
|
|
```bash
|
|
curl https://api.anthropic.com/v1/messages \
|
|
--header "x-api-key: sk-ant-api03-YOUR_NEW_KEY_HERE" \
|
|
--header "anthropic-version: 2023-06-01" \
|
|
--header "content-type: application/json" \
|
|
--data '{"model": "claude-sonnet-4-5-20250929", "max_tokens": 10, "messages": [{"role": "user", "content": "test"}]}'
|
|
|
|
# Should return valid response (not 401 error)
|
|
```
|
|
|
|
**Verification**: New key works, old key definitely revoked
|
|
|
|
---
|
|
|
|
### 2. Remove Exposed Key from Documentation ✅ CRITICAL
|
|
|
|
**Why**: `docs/STRIPE_LIVE_MODE_DEPLOYMENT.md` contains the SAME exposed key
|
|
|
|
**Actions**:
|
|
```bash
|
|
# Edit the file
|
|
nano /home/theflow/projects/tractatus/docs/STRIPE_LIVE_MODE_DEPLOYMENT.md
|
|
|
|
# Find line with: CLAUDE_API_KEY=sk-ant-api03-_xmqWkax8jx...
|
|
# Replace with: CLAUDE_API_KEY=sk-ant-api03-EXAMPLE-REDACTED-NEVER-USE
|
|
|
|
# Save and exit
|
|
```
|
|
|
|
**Alternative** (automated):
|
|
```bash
|
|
sed -i 's/CLAUDE_API_KEY=sk-ant-api03-[a-zA-Z0-9_-]*/CLAUDE_API_KEY=sk-ant-api03-EXAMPLE-REDACTED-NEVER-USE/g' docs/STRIPE_LIVE_MODE_DEPLOYMENT.md
|
|
```
|
|
|
|
**Verification**: No real API keys in documentation
|
|
|
|
---
|
|
|
|
### 3. Rotate JWT Secret ✅ HIGH PRIORITY
|
|
|
|
**Why**: JWT secret in `.env` is production credential used for authentication
|
|
|
|
**Current Secret** (EXPOSED):
|
|
```
|
|
[REDACTED]
|
|
```
|
|
|
|
**Actions**:
|
|
1. Generate new JWT secret:
|
|
```bash
|
|
# Generate secure random secret (64 bytes hex)
|
|
openssl rand -hex 64
|
|
|
|
# Copy the output
|
|
```
|
|
2. Update `.env`:
|
|
```bash
|
|
nano .env
|
|
|
|
# Replace:
|
|
# OLD: JWT_SECRET=d4d9b5ac258123db...
|
|
# NEW: JWT_SECRET=<paste_new_secret_here>
|
|
|
|
# Save and exit
|
|
```
|
|
3. **IMPORTANT**: This will invalidate ALL existing JWT tokens
|
|
- All users will need to re-login
|
|
- Any admin sessions will be terminated
|
|
- This is CORRECT behavior (invalidates potentially compromised sessions)
|
|
|
|
**Verification**: Server starts successfully with new JWT secret
|
|
|
|
---
|
|
|
|
### 4. Rotate Stripe Keys (OPTIONAL - Low Risk) ⚠️ MEDIUM PRIORITY
|
|
|
|
**Why**: Stripe TEST keys found in `.env` (not live keys, low financial risk)
|
|
|
|
**Current Keys** (TEST mode):
|
|
- Secret: `sk_test_[REDACTED]`
|
|
- Publishable: `pk_test_[REDACTED]`
|
|
|
|
**Risk Assessment**:
|
|
- These are TEST keys (sk_test_, pk_test_)
|
|
- No real money can be charged
|
|
- Still best practice to rotate
|
|
|
|
**Actions** (if you want to rotate):
|
|
1. Login to Stripe Dashboard: https://dashboard.stripe.com/test/apikeys
|
|
2. Roll secret key (this creates new key and invalidates old)
|
|
3. Copy new keys
|
|
4. Update `.env`:
|
|
```bash
|
|
STRIPE_SECRET_KEY=sk_test_YOUR_NEW_SECRET_KEY
|
|
STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_NEW_PUBLISHABLE_KEY
|
|
```
|
|
|
|
**Decision**: Your call - test keys have low risk, but rotation is prudent
|
|
|
|
---
|
|
|
|
## SECONDARY ACTIONS (Next 1-2 Hours)
|
|
|
|
### 5. Install Gitleaks (Secret Detection Tool)
|
|
|
|
**Why**: Prevents future credential exposure with automated pre-commit scanning
|
|
|
|
**Installation** (Linux):
|
|
```bash
|
|
# Download gitleaks
|
|
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.1/gitleaks_8.18.1_linux_x64.tar.gz
|
|
|
|
# Extract
|
|
tar -xzf gitleaks_8.18.1_linux_x64.tar.gz
|
|
|
|
# Move to /usr/local/bin
|
|
sudo mv gitleaks /usr/local/bin/
|
|
|
|
# Verify installation
|
|
gitleaks version
|
|
```
|
|
|
|
**Installation** (Mac - if applicable):
|
|
```bash
|
|
brew install gitleaks
|
|
```
|
|
|
|
**Test**:
|
|
```bash
|
|
# Scan repository
|
|
cd /home/theflow/projects/tractatus
|
|
gitleaks detect --source . --verbose
|
|
|
|
# Should detect credentials in .env, docs/STRIPE_LIVE_MODE_DEPLOYMENT.md
|
|
```
|
|
|
|
---
|
|
|
|
### 6. Create Git Pre-Commit Hook
|
|
|
|
**Why**: Blocks commits containing secrets BEFORE they reach git history
|
|
|
|
**Actions**:
|
|
```bash
|
|
# Navigate to repository
|
|
cd /home/theflow/projects/tractatus
|
|
|
|
# Create pre-commit hook
|
|
cat > .git/hooks/pre-commit << 'EOF'
|
|
#!/bin/bash
|
|
|
|
echo "🔍 Running secret detection scan..."
|
|
gitleaks detect --source . --verbose --no-git
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo ""
|
|
echo "❌ SECRETS DETECTED - Commit blocked"
|
|
echo ""
|
|
echo "If this is a false positive:"
|
|
echo " 1. Verify it's NOT a real secret"
|
|
echo " 2. Add to .gitleaksignore with explanation"
|
|
echo " 3. Get user approval"
|
|
echo " 4. Try committing again"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ No secrets detected - proceeding with commit"
|
|
exit 0
|
|
EOF
|
|
|
|
# Make executable
|
|
chmod +x .git/hooks/pre-commit
|
|
|
|
# Test
|
|
echo "test-secret=sk-ant-api03-test" > test-file.txt
|
|
git add test-file.txt
|
|
git commit -m "test" # Should BLOCK with secret detection error
|
|
rm test-file.txt
|
|
git reset HEAD test-file.txt
|
|
```
|
|
|
|
**Verification**: Committing a file with API key pattern is BLOCKED
|
|
|
|
---
|
|
|
|
### 7. Add .env to .gitignore (If Not Already)
|
|
|
|
**Why**: Ensures .env never accidentally committed
|
|
|
|
**Actions**:
|
|
```bash
|
|
# Check if .env in .gitignore
|
|
grep "^\.env$" .gitignore
|
|
|
|
# If not found, add it:
|
|
echo ".env" >> .gitignore
|
|
|
|
# Verify
|
|
cat .gitignore | grep "\.env"
|
|
```
|
|
|
|
**Verification**: .env appears in .gitignore
|
|
|
|
---
|
|
|
|
### 8. Remove docs/STRIPE_LIVE_MODE_DEPLOYMENT.md from Public Repository
|
|
|
|
**Why**: This file was exposed in public repo at commit 31345d5c1abc8c8da9387d55494a1741f451f9a7
|
|
|
|
**Decision Required**:
|
|
|
|
**Option A**: Delete file from git history (RECOMMENDED)
|
|
- Pros: Removes credential from git history
|
|
- Cons: Force push required, breaks forks
|
|
- Tool: BFG Repo-Cleaner
|
|
|
|
**Option B**: Accept file in history, rely on key revocation
|
|
- Pros: No repository disruption
|
|
- Cons: Credential remains in git history (already revoked)
|
|
- Action: None needed
|
|
|
|
**Option C**: Delete public repository and recreate
|
|
- Pros: Complete removal
|
|
- Cons: Loses stars, discussions, community engagement
|
|
|
|
**Recommendation**: Option B (accept in history) since:
|
|
1. Key already revoked by Anthropic
|
|
2. Public repo is tractatus-framework (implementation only)
|
|
3. No active community yet (early stage)
|
|
4. Low risk of exploitation (key revoked)
|
|
|
|
**If you choose Option A** (remove from history):
|
|
```bash
|
|
# Install BFG Repo-Cleaner
|
|
wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar
|
|
java -jar bfg-1.14.0.jar --delete-files STRIPE_LIVE_MODE_DEPLOYMENT.md /path/to/tractatus-framework
|
|
|
|
# Follow BFG instructions to git reflog expire and force push
|
|
```
|
|
|
|
**Your Decision**: Which option?
|
|
|
|
---
|
|
|
|
### 9. Review All .env Files Across All Projects
|
|
|
|
**Why**: If one project exposed credentials, others might too
|
|
|
|
**Projects to Check**:
|
|
1. `/home/theflow/projects/tractatus` (DONE - issues found)
|
|
2. `/home/theflow/projects/family-history` (CHECK THIS)
|
|
3. `/home/theflow/projects/sydigital` (CHECK THIS)
|
|
4. Any other projects
|
|
|
|
**Actions for Each Project**:
|
|
```bash
|
|
# Navigate to project
|
|
cd /home/theflow/projects/PROJECTNAME
|
|
|
|
# Check .env exists
|
|
ls -la .env
|
|
|
|
# Scan for credentials
|
|
gitleaks detect --source . --verbose
|
|
|
|
# Check if .env in git history (BAD if true)
|
|
git log --all --full-history -- .env
|
|
```
|
|
|
|
**Verification**: No .env files in git history across any project
|
|
|
|
---
|
|
|
|
## MONITORING & VERIFICATION (Next 24-48 Hours)
|
|
|
|
### 10. Monitor Anthropic API Usage
|
|
|
|
**Why**: Detect unauthorized usage of compromised key (before revocation)
|
|
|
|
**Actions**:
|
|
1. Login to Anthropic Console: https://platform.claude.com/settings/usage
|
|
2. Review API usage for past 24 hours
|
|
3. Look for:
|
|
- Unusual volume spikes
|
|
- Geographic anomalies (API calls from unexpected regions)
|
|
- Unknown application names
|
|
- Timestamp gaps (usage when you weren't working)
|
|
|
|
**Red Flags**:
|
|
- API calls from non-Europe/non-Australia IPs (if you're only in those regions)
|
|
- Calls during hours you weren't working (e.g., 2-6 AM your timezone)
|
|
- Sudden spike in usage
|
|
- Unfamiliar model names or endpoints
|
|
|
|
**Action if Suspicious**: Contact Anthropic support immediately
|
|
|
|
---
|
|
|
|
### 11. Monitor Stripe Dashboard
|
|
|
|
**Why**: Detect unauthorized test transactions (low risk with test keys)
|
|
|
|
**Actions**:
|
|
1. Login to Stripe Dashboard: https://dashboard.stripe.com/test/payments
|
|
2. Review test transactions for past 7 days
|
|
3. Look for unexpected test charges
|
|
|
|
**Note**: Test keys cannot charge real money, so financial risk is zero
|
|
|
|
---
|
|
|
|
### 12. Review Git Log for Other Credential Exposures
|
|
|
|
**Why**: May have committed other secrets in past
|
|
|
|
**Actions**:
|
|
```bash
|
|
cd /home/theflow/projects/tractatus
|
|
|
|
# Scan entire git history for secrets
|
|
gitleaks detect --source . --log-opts="--all" --verbose --report-path=/tmp/gitleaks-report.json
|
|
|
|
# Review report
|
|
cat /tmp/gitleaks-report.json | jq '.'
|
|
|
|
# Or use grep for common patterns
|
|
git log -p --all | grep -E "sk-|pk-|api.?key|secret|password" | head -50
|
|
```
|
|
|
|
**Action if Found**: Rotate those credentials too
|
|
|
|
---
|
|
|
|
## POST-INCIDENT IMPROVEMENTS
|
|
|
|
### 13. Update SECURITY.md in Public Repository
|
|
|
|
**Why**: Transparency and incident disclosure
|
|
|
|
**Actions**:
|
|
1. Add incident to Security Audit History table
|
|
2. Document response (key revocation, rotation procedures)
|
|
3. Update best practices based on learnings
|
|
|
|
**Draft Entry**:
|
|
```markdown
|
|
| Date | Type | Severity | Status | Details |
|
|
|------|------|----------|--------|---------|
|
|
| 2025-10-21 | Credential Exposure | CRITICAL | Resolved | Anthropic API key exposed in docs/STRIPE_LIVE_MODE_DEPLOYMENT.md at commit 31345d5c1a. Key automatically revoked by Anthropic via GitHub secret scanning. All credentials rotated. Pre-commit secret detection implemented. |
|
|
```
|
|
|
|
---
|
|
|
|
### 14. Document Incident in Internal Post-Mortem
|
|
|
|
**File**: `docs/security/INCIDENT_2025-10-21_API_KEY_EXPOSURE.md`
|
|
|
|
**Sections**:
|
|
1. Timeline
|
|
2. Root cause
|
|
3. Impact assessment
|
|
4. Response actions
|
|
5. Preventive measures
|
|
6. Lessons learned
|
|
|
|
**Claude will create this** - see SECURITY_INCIDENT_POST_MORTEM_2025-10-21.md
|
|
|
|
---
|
|
|
|
### 15. Review and Test Pre-Deployment Checklist
|
|
|
|
**Why**: Ensure inst_071 (new enhanced checklist) prevents recurrence
|
|
|
|
**Actions**:
|
|
1. Review inst_071 checklist
|
|
2. Practice running each step
|
|
3. Identify any gaps
|
|
4. Update checklist if needed
|
|
|
|
**Checklist** (from inst_071):
|
|
```
|
|
□ 1. CSP Compliance Check [AUTOMATED via hook]
|
|
□ 2. Secret Detection Scan (gitleaks detect --source .)
|
|
□ 3. Credential Audit (grep -r "sk-" "pk-" "secret" "password")
|
|
□ 4. Local Server Test (curl http://localhost:9000/health → 200 OK)
|
|
□ 5. Comprehensive Testing (npm test → all pass)
|
|
□ 6. Permission Verification (ls -la → correct 644/755)
|
|
□ 7. Git Status Clean (no uncommitted changes)
|
|
□ 8. Public Repository Content Review (no internal docs)
|
|
```
|
|
|
|
---
|
|
|
|
## SUMMARY CHECKLIST
|
|
|
|
Use this to track completion:
|
|
|
|
**CRITICAL (Do Now)**:
|
|
- [ ] Rotate Anthropic API key (create new, update .env)
|
|
- [ ] Remove exposed key from docs/STRIPE_LIVE_MODE_DEPLOYMENT.md
|
|
- [ ] Rotate JWT secret (generate new, update .env)
|
|
- [ ] Test application with new credentials
|
|
|
|
**HIGH PRIORITY (Next 2 Hours)**:
|
|
- [ ] Install gitleaks
|
|
- [ ] Create pre-commit hook
|
|
- [ ] Verify .env in .gitignore
|
|
- [ ] Decide on public repo history (Option A/B/C)
|
|
|
|
**MEDIUM PRIORITY (Next 24 Hours)**:
|
|
- [ ] Rotate Stripe test keys (optional)
|
|
- [ ] Review other projects (.env files)
|
|
- [ ] Monitor Anthropic API usage
|
|
- [ ] Monitor Stripe dashboard
|
|
- [ ] Scan git history for other secrets
|
|
|
|
**LOW PRIORITY (Next Week)**:
|
|
- [ ] Update SECURITY.md
|
|
- [ ] Review post-mortem
|
|
- [ ] Test pre-deployment checklist
|
|
- [ ] Schedule quarterly security audits
|
|
|
|
---
|
|
|
|
## QUESTIONS & CLARIFICATIONS
|
|
|
|
### Q: Why did this happen?
|
|
**A**: Multiple failures in credential handling:
|
|
1. Real API key in documentation (should have been redacted example)
|
|
2. No secret detection before commit (no pre-commit hook)
|
|
3. No credential audit in cleanup checklist (inst_054 didn't include secret scan)
|
|
4. Framework components not actively used (BoundaryEnforcer should have caught this)
|
|
|
|
### Q: Was this malicious AI behavior?
|
|
**A**: NO. This was systematic failure in processes, not AI having "bad intent":
|
|
- AI doesn't have intent (good or bad)
|
|
- AI made mistakes that had catastrophic consequences
|
|
- Framework existed but wasn't enforced (framework fade)
|
|
- New rules (inst_069-072) prevent recurrence
|
|
|
|
### Q: What's the financial impact?
|
|
**A**: MINIMAL (likely zero):
|
|
- Anthropic key revoked immediately (GitHub secret scanning worked)
|
|
- No evidence of unauthorized usage (monitor to confirm)
|
|
- Stripe keys are TEST mode only (no real money)
|
|
- JWT secret rotation invalidates sessions (security benefit)
|
|
|
|
### Q: Will this happen again?
|
|
**A**: NOT if we follow new procedures:
|
|
- inst_069: Mandatory credential redaction
|
|
- inst_070: Pre-commit secret detection (automated)
|
|
- inst_071: Enhanced deployment checklist (includes credential audit)
|
|
- inst_072: Defense-in-depth (5 layers of protection)
|
|
- Gitleaks hook: Blocks commits with secrets
|
|
|
|
### Q: Should I be worried about other credentials?
|
|
**A**: YES - Audit recommended:
|
|
- Review all projects for .env files
|
|
- Scan git history with gitleaks
|
|
- Rotate credentials found in scans
|
|
- Implement secret detection across all projects
|
|
|
|
---
|
|
|
|
## CONTACT & SUPPORT
|
|
|
|
**Anthropic Support**: https://support.anthropic.com
|
|
**Stripe Support**: https://support.stripe.com
|
|
**GitHub Security**: https://docs.github.com/en/code-security/secret-scanning
|
|
|
|
**Internal**: Review SECURITY_INCIDENT_POST_MORTEM_2025-10-21.md for full analysis
|
|
|
|
---
|
|
|
|
**CREATED**: 2025-10-21 by Claude Code (Automated Security Response)
|
|
**URGENCY**: IMMEDIATE ACTION REQUIRED
|
|
**NEXT REVIEW**: After completing CRITICAL section (next 30 minutes)
|