codeforge-dev 1.5.7 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.devcontainer/.env +2 -1
  2. package/.devcontainer/CHANGELOG.md +55 -9
  3. package/.devcontainer/CLAUDE.md +65 -15
  4. package/.devcontainer/README.md +67 -6
  5. package/.devcontainer/config/keybindings.json +5 -0
  6. package/.devcontainer/config/main-system-prompt.md +63 -2
  7. package/.devcontainer/config/settings.json +25 -6
  8. package/.devcontainer/devcontainer.json +23 -7
  9. package/.devcontainer/features/README.md +21 -7
  10. package/.devcontainer/features/ccburn/README.md +60 -0
  11. package/.devcontainer/features/ccburn/devcontainer-feature.json +38 -0
  12. package/.devcontainer/features/ccburn/install.sh +174 -0
  13. package/.devcontainer/features/ccstatusline/README.md +22 -21
  14. package/.devcontainer/features/ccstatusline/devcontainer-feature.json +1 -1
  15. package/.devcontainer/features/ccstatusline/install.sh +48 -16
  16. package/.devcontainer/features/claude-code/config/settings.json +60 -24
  17. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
  18. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +1 -1
  19. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/__pycache__/format-on-stop.cpython-314.pyc +0 -0
  20. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +21 -6
  21. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/__pycache__/lint-file.cpython-314.pyc +0 -0
  22. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +7 -10
  23. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/REVIEW-RUBRIC.md +440 -0
  24. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +190 -0
  25. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/bash-exec.md +173 -0
  26. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +155 -0
  27. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +248 -0
  28. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +233 -0
  29. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +235 -0
  30. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +125 -0
  31. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +242 -0
  32. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +195 -0
  33. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/perf-profiler.md +265 -0
  34. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +209 -0
  35. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +195 -0
  36. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +289 -0
  37. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +284 -0
  38. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/statusline-config.md +188 -0
  39. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +245 -0
  40. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +12 -0
  41. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/guard-readonly-bash.cpython-314.pyc +0 -0
  42. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/redirect-builtin-agents.cpython-314.pyc +0 -0
  43. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/skill-suggester.cpython-314.pyc +0 -0
  44. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/syntax-validator.cpython-314.pyc +0 -0
  45. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-no-regression.cpython-314.pyc +0 -0
  46. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-tests-pass.cpython-314.pyc +0 -0
  47. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/guard-readonly-bash.py +611 -0
  48. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/redirect-builtin-agents.py +83 -0
  49. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +85 -2
  50. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/syntax-validator.py +9 -4
  51. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-no-regression.py +221 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-tests-pass.py +176 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/SKILL.md +599 -0
  54. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/references/sdk-typescript-reference.md +954 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/SKILL.md +276 -0
  56. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/advanced-commands.md +332 -0
  57. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/investigation-playbooks.md +319 -0
  58. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/SKILL.md +341 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/interpreting-results.md +235 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/tool-commands.md +395 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/SKILL.md +344 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/safe-transformations.md +247 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/smell-catalog.md +332 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/SKILL.md +277 -0
  65. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/owasp-patterns.md +269 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/secrets-patterns.md +253 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +288 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/criteria-patterns.md +245 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/ears-templates.md +239 -0
  70. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/__pycache__/guard-protected.cpython-314.pyc +0 -0
  71. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +40 -39
  72. package/.devcontainer/scripts/setup-aliases.sh +10 -20
  73. package/.devcontainer/scripts/setup-config.sh +2 -0
  74. package/.devcontainer/scripts/setup-plugins.sh +38 -46
  75. package/.devcontainer/scripts/setup-projects.sh +175 -0
  76. package/.devcontainer/scripts/setup-symlink-claude.sh +36 -0
  77. package/.devcontainer/scripts/setup-update-claude.sh +11 -8
  78. package/.devcontainer/scripts/setup.sh +4 -2
  79. package/package.json +1 -1
  80. package/.devcontainer/scripts/setup-irie-claude.sh +0 -32
@@ -0,0 +1,269 @@
1
+ # OWASP Top 10 Patterns with Code Examples
2
+
3
+ Detailed vulnerability patterns with vulnerable and fixed code for each OWASP category.
4
+
5
+ ## Contents
6
+
7
+ - [A01: Broken Access Control](#a01-broken-access-control)
8
+ - [A02: Cryptographic Failures](#a02-cryptographic-failures)
9
+ - [A03: Injection](#a03-injection)
10
+ - [A05: Security Misconfiguration](#a05-security-misconfiguration)
11
+ - [A07: Authentication Failures](#a07-authentication-failures)
12
+ - [A10: Server-Side Request Forgery (SSRF)](#a10-server-side-request-forgery-ssrf)
13
+ - [Cross-Cutting Patterns](#cross-cutting-patterns)
14
+
15
+ ---
16
+
17
+ ## A01: Broken Access Control
18
+
19
+ ### Insecure Direct Object Reference (IDOR)
20
+
21
+ ```python
22
+ # VULNERABLE: No authorization check — any user can access any order
23
+ @app.get("/api/orders/{order_id}")
24
+ async def get_order(order_id: int):
25
+ return db.get_order(order_id)
26
+
27
+ # FIXED: Verify the requesting user owns the resource
28
+ @app.get("/api/orders/{order_id}")
29
+ async def get_order(order_id: int, current_user: User = Depends(get_current_user)):
30
+ order = db.get_order(order_id)
31
+ if order.user_id != current_user.id:
32
+ raise HTTPException(status_code=403, detail="Forbidden")
33
+ return order
34
+ ```
35
+
36
+ ### Missing Function-Level Access Control
37
+
38
+ ```python
39
+ # VULNERABLE: Admin endpoint with no role check
40
+ @app.delete("/api/users/{user_id}")
41
+ async def delete_user(user_id: int, current_user: User = Depends(get_current_user)):
42
+ db.delete_user(user_id)
43
+
44
+ # FIXED: Enforce role-based access
45
+ @app.delete("/api/users/{user_id}")
46
+ async def delete_user(user_id: int, current_user: User = Depends(require_admin)):
47
+ db.delete_user(user_id)
48
+
49
+ def require_admin(current_user: User = Depends(get_current_user)):
50
+ if current_user.role != "admin":
51
+ raise HTTPException(status_code=403, detail="Admin required")
52
+ return current_user
53
+ ```
54
+
55
+ ---
56
+
57
+ ## A02: Cryptographic Failures
58
+
59
+ ### Weak Password Hashing
60
+
61
+ ```python
62
+ # VULNERABLE: MD5 is not a password hash — it's fast and rainbow-table-vulnerable
63
+ import hashlib
64
+ hashed = hashlib.md5(password.encode()).hexdigest()
65
+
66
+ # FIXED: Use bcrypt with automatic salting
67
+ import bcrypt
68
+ hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
69
+
70
+ # Verification
71
+ if bcrypt.checkpw(password.encode(), stored_hash):
72
+ grant_access()
73
+ ```
74
+
75
+ ### Sensitive Data in Logs
76
+
77
+ ```python
78
+ # VULNERABLE: Logging sensitive data
79
+ logger.info(f"User login: email={email}, password={password}")
80
+ logger.debug(f"API response: {response.json()}") # may contain tokens
81
+
82
+ # FIXED: Redact sensitive fields
83
+ logger.info(f"User login: email={email}")
84
+ logger.debug(f"API response: status={response.status_code}")
85
+ ```
86
+
87
+ ---
88
+
89
+ ## A03: Injection
90
+
91
+ ### SQL Injection
92
+
93
+ ```python
94
+ # VULNERABLE: String interpolation in SQL
95
+ query = f"SELECT * FROM users WHERE email = '{email}' AND password = '{password}'"
96
+ cursor.execute(query)
97
+ # Attack: email = "' OR '1'='1' --"
98
+
99
+ # FIXED: Parameterized query
100
+ cursor.execute("SELECT * FROM users WHERE email = ? AND password = ?", (email, password_hash))
101
+ ```
102
+
103
+ ### Command Injection
104
+
105
+ ```javascript
106
+ // VULNERABLE: User input in shell command
107
+ const { exec } = require("child_process");
108
+ exec(`convert ${req.body.filename} output.png`);
109
+ // Attack: filename = "input.jpg; rm -rf /"
110
+
111
+ // FIXED: Use execFile with argument array (no shell)
112
+ const { execFile } = require("child_process");
113
+ execFile("convert", [req.body.filename, "output.png"]);
114
+ ```
115
+
116
+ ### Template Injection (SSTI)
117
+
118
+ ```python
119
+ # VULNERABLE: User input in template string
120
+ from jinja2 import Template
121
+ template = Template(f"Hello {user_input}")
122
+ # Attack: user_input = "{{ config.items() }}"
123
+
124
+ # FIXED: Pass user input as a variable, not template content
125
+ from jinja2 import Environment, select_autoescape
126
+ env = Environment(autoescape=select_autoescape())
127
+ template = env.from_string("Hello {{ name }}")
128
+ result = template.render(name=user_input)
129
+ ```
130
+
131
+ ---
132
+
133
+ ## A05: Security Misconfiguration
134
+
135
+ ### CORS Misconfiguration
136
+
137
+ ```python
138
+ # VULNERABLE: Allow all origins
139
+ from fastapi.middleware.cors import CORSMiddleware
140
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True)
141
+
142
+ # FIXED: Explicit origin allowlist
143
+ app.add_middleware(
144
+ CORSMiddleware,
145
+ allow_origins=["https://myapp.com", "https://staging.myapp.com"],
146
+ allow_credentials=True,
147
+ allow_methods=["GET", "POST", "PUT", "DELETE"],
148
+ allow_headers=["Authorization", "Content-Type"],
149
+ )
150
+ ```
151
+
152
+ ### Debug Mode in Production
153
+
154
+ ```python
155
+ # VULNERABLE: Debug mode exposes stack traces and internal state
156
+ app = Flask(__name__)
157
+ app.run(debug=True) # NEVER in production
158
+
159
+ # FIXED: Environment-driven configuration
160
+ import os
161
+ app.run(debug=os.getenv("FLASK_ENV") == "development")
162
+ ```
163
+
164
+ ---
165
+
166
+ ## A07: Authentication Failures
167
+
168
+ ### No Rate Limiting on Login
169
+
170
+ ```python
171
+ # VULNERABLE: No limit on login attempts
172
+ @app.post("/login")
173
+ async def login(email: str, password: str):
174
+ user = db.get_user_by_email(email)
175
+ if user and verify_password(password, user.password_hash):
176
+ return create_token(user)
177
+ raise HTTPException(status_code=401)
178
+
179
+ # FIXED: Rate limiting with exponential backoff
180
+ from slowapi import Limiter
181
+ limiter = Limiter(key_func=get_remote_address)
182
+
183
+ @app.post("/login")
184
+ @limiter.limit("5/minute")
185
+ async def login(request: Request, email: str, password: str):
186
+ user = db.get_user_by_email(email)
187
+ if user and verify_password(password, user.password_hash):
188
+ return create_token(user)
189
+ await asyncio.sleep(random.uniform(0.1, 0.5)) # timing attack mitigation
190
+ raise HTTPException(status_code=401)
191
+ ```
192
+
193
+ ---
194
+
195
+ ## A10: Server-Side Request Forgery (SSRF)
196
+
197
+ ```python
198
+ # VULNERABLE: User-supplied URL fetched without validation
199
+ @app.post("/fetch-url")
200
+ async def fetch_url(url: str):
201
+ response = httpx.get(url) # can access internal services
202
+ return response.text
203
+ # Attack: url = "http://169.254.169.254/latest/meta-data/" (AWS metadata)
204
+
205
+ # FIXED: Validate URL against allowlist and block internal ranges
206
+ import ipaddress
207
+ from urllib.parse import urlparse
208
+
209
+ BLOCKED_NETWORKS = [
210
+ ipaddress.ip_network("10.0.0.0/8"),
211
+ ipaddress.ip_network("172.16.0.0/12"),
212
+ ipaddress.ip_network("192.168.0.0/16"),
213
+ ipaddress.ip_network("169.254.0.0/16"),
214
+ ipaddress.ip_network("127.0.0.0/8"),
215
+ ]
216
+
217
+ def is_safe_url(url: str) -> bool:
218
+ parsed = urlparse(url)
219
+ if parsed.scheme not in ("http", "https"):
220
+ return False
221
+ try:
222
+ ip = ipaddress.ip_address(parsed.hostname)
223
+ return not any(ip in net for net in BLOCKED_NETWORKS)
224
+ except ValueError:
225
+ # Hostname, not IP — resolve and check
226
+ import socket
227
+ ip = ipaddress.ip_address(socket.gethostbyname(parsed.hostname))
228
+ return not any(ip in net for net in BLOCKED_NETWORKS)
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Cross-Cutting Patterns
234
+
235
+ ### Security Headers (All Frameworks)
236
+
237
+ ```python
238
+ # FastAPI middleware for security headers
239
+ @app.middleware("http")
240
+ async def add_security_headers(request, call_next):
241
+ response = await call_next(request)
242
+ response.headers["X-Content-Type-Options"] = "nosniff"
243
+ response.headers["X-Frame-Options"] = "DENY"
244
+ response.headers["X-XSS-Protection"] = "0" # disabled in favor of CSP
245
+ response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
246
+ response.headers["Content-Security-Policy"] = "default-src 'self'"
247
+ response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
248
+ return response
249
+ ```
250
+
251
+ ### Input Validation Pattern
252
+
253
+ ```python
254
+ from pydantic import BaseModel, Field, field_validator
255
+
256
+ class CreateUserRequest(BaseModel):
257
+ email: str = Field(..., max_length=254)
258
+ name: str = Field(..., min_length=1, max_length=100)
259
+ age: int = Field(..., ge=0, le=150)
260
+
261
+ @field_validator("email")
262
+ @classmethod
263
+ def validate_email(cls, v: str) -> str:
264
+ if "@" not in v or ".." in v:
265
+ raise ValueError("Invalid email format")
266
+ return v.lower().strip()
267
+ ```
268
+
269
+ Always validate at the boundary — even if the frontend validates, the backend must validate independently.
@@ -0,0 +1,253 @@
1
+ # Secrets Detection Patterns
2
+
3
+ Comprehensive regex patterns and strategies for detecting accidentally committed secrets.
4
+
5
+ ## Contents
6
+
7
+ - [Cloud Provider Keys](#cloud-provider-keys)
8
+ - [Version Control Platform Tokens](#version-control-platform-tokens)
9
+ - [API Keys and Tokens](#api-keys-and-tokens)
10
+ - [Database Connection Strings](#database-connection-strings)
11
+ - [Certificates and Private Keys](#certificates-and-private-keys)
12
+ - [High-Entropy String Detection](#high-entropy-string-detection)
13
+ - [Prevention Strategies](#prevention-strategies)
14
+
15
+ ---
16
+
17
+ ## Cloud Provider Keys
18
+
19
+ ### AWS
20
+
21
+ ```regex
22
+ # AWS Access Key ID (starts with AKIA)
23
+ AKIA[0-9A-Z]{16}
24
+
25
+ # AWS Secret Access Key (40-char base64 near "aws" keyword)
26
+ (?i)aws(.{0,20})?(?-i)['\"][0-9a-zA-Z/+]{40}['\"]
27
+
28
+ # AWS Session Token
29
+ (?i)aws(.{0,10})?session(.{0,10})?token(.{0,5})?['\"][A-Za-z0-9/+=]{100,}['\"]
30
+
31
+ # AWS Account ID (12 digits, context-dependent)
32
+ (?i)(aws.?account.?id|account.?id)[\s:=]*['\"]?\d{12}['\"]?
33
+ ```
34
+
35
+ ### Google Cloud
36
+
37
+ ```regex
38
+ # GCP Service Account Key (JSON key file identifier)
39
+ \"type\":\s*\"service_account\"
40
+
41
+ # GCP API Key
42
+ AIza[0-9A-Za-z\\-_]{35}
43
+
44
+ # GCP OAuth Client Secret
45
+ (?i)(client_secret|client.secret)[\s:=]*['\"][a-zA-Z0-9_-]{24,}['\"]
46
+ ```
47
+
48
+ ### Azure
49
+
50
+ ```regex
51
+ # Azure Storage Account Key
52
+ (?i)(AccountKey|account_key|azure.storage.key)[\s:=]*['\"][A-Za-z0-9+/=]{86,88}['\"]
53
+
54
+ # Azure Connection String
55
+ (?i)(DefaultEndpointsProtocol=https?;AccountName=)[^\s;]+;AccountKey=[A-Za-z0-9+/=]+
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Version Control Platform Tokens
61
+
62
+ ```regex
63
+ # GitHub Personal Access Token (classic)
64
+ ghp_[A-Za-z0-9_]{36}
65
+
66
+ # GitHub OAuth Access Token
67
+ gho_[A-Za-z0-9_]{36}
68
+
69
+ # GitHub User-to-Server Token
70
+ ghu_[A-Za-z0-9_]{36}
71
+
72
+ # GitHub Server-to-Server Token
73
+ ghs_[A-Za-z0-9_]{36}
74
+
75
+ # GitHub Refresh Token
76
+ ghr_[A-Za-z0-9_]{36}
77
+
78
+ # GitLab Personal/Project/Group Access Token
79
+ glpat-[A-Za-z0-9_\-]{20,}
80
+
81
+ # Bitbucket App Password
82
+ (?i)(bitbucket.{0,20})(password|secret|token)[\s:=]*['\"][A-Za-z0-9]{20,}['\"]
83
+ ```
84
+
85
+ ---
86
+
87
+ ## API Keys and Tokens
88
+
89
+ ```regex
90
+ # Generic API Key pattern (key=value or key:value)
91
+ (?i)(api[_-]?key|apikey|api[_-]?secret|api[_-]?token)[\s]*[=:]\s*['\"][a-zA-Z0-9_\-]{16,}['\"]
92
+
93
+ # Bearer Token in code
94
+ (?i)(bearer|authorization)[\s:=]*['\"]Bearer\s+[A-Za-z0-9\-._~+/]+=*['\"]
95
+
96
+ # Slack Token
97
+ xox[bpors]-[0-9a-zA-Z]{10,250}
98
+
99
+ # Slack Webhook URL
100
+ https://hooks\.slack\.com/services/T[a-zA-Z0-9_]+/B[a-zA-Z0-9_]+/[a-zA-Z0-9_]+
101
+
102
+ # Stripe API Key
103
+ (?:sk|pk)_(test|live)_[0-9a-zA-Z]{24,}
104
+
105
+ # Twilio Account SID and Auth Token
106
+ AC[a-f0-9]{32}
107
+ (?i)(twilio.{0,20})(auth.?token|secret)[\s:=]*['\"][a-f0-9]{32}['\"]
108
+
109
+ # SendGrid API Key
110
+ SG\.[A-Za-z0-9_\-]{22}\.[A-Za-z0-9_\-]{43}
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Database Connection Strings
116
+
117
+ ```regex
118
+ # PostgreSQL
119
+ (?i)postgres(ql)?://[^:]+:[^@]+@[^\s]+
120
+
121
+ # MySQL
122
+ (?i)mysql://[^:]+:[^@]+@[^\s]+
123
+
124
+ # MongoDB
125
+ (?i)mongodb(\+srv)?://[^:]+:[^@]+@[^\s]+
126
+
127
+ # Redis with password
128
+ (?i)redis://:[^@]+@[^\s]+
129
+
130
+ # JDBC with password
131
+ (?i)jdbc:[a-z]+://[^?]+\?.*password=[^\s&]+
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Certificates and Private Keys
137
+
138
+ ```regex
139
+ # PEM-encoded private keys
140
+ -----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----
141
+
142
+ # PEM-encoded certificates (less sensitive but may indicate bundled keys)
143
+ -----BEGIN CERTIFICATE-----
144
+
145
+ # PKCS#12 / PFX files (binary, detect by extension)
146
+ \.(p12|pfx)$
147
+
148
+ # SSH private key (not PEM format)
149
+ -----BEGIN OPENSSH PRIVATE KEY-----
150
+ ```
151
+
152
+ ---
153
+
154
+ ## High-Entropy String Detection
155
+
156
+ For secrets that don't match known patterns, detect high-entropy strings:
157
+
158
+ ```python
159
+ import math
160
+ import re
161
+ from collections import Counter
162
+
163
+ def shannon_entropy(s: str) -> float:
164
+ """Calculate Shannon entropy of a string."""
165
+ if not s:
166
+ return 0.0
167
+ length = len(s)
168
+ freq = Counter(s)
169
+ return -sum((count / length) * math.log2(count / length) for count in freq.values())
170
+
171
+ def is_potential_secret(value: str) -> bool:
172
+ """Heuristic: long, high-entropy strings in assignment contexts."""
173
+ if len(value) < 16:
174
+ return False
175
+ entropy = shannon_entropy(value)
176
+ # Base64 strings: entropy > 4.5, hex strings: entropy > 3.5
177
+ if entropy > 4.5 and len(value) >= 20:
178
+ return True
179
+ if entropy > 3.5 and len(value) >= 32 and re.match(r'^[0-9a-fA-F]+$', value):
180
+ return True
181
+ return False
182
+ ```
183
+
184
+ **Entropy thresholds:**
185
+ - Random hex (32+ chars): entropy > 3.5
186
+ - Random base64 (20+ chars): entropy > 4.5
187
+ - English text: entropy ~ 3.5-4.0
188
+ - Code identifiers: entropy ~ 2.5-3.5
189
+
190
+ ---
191
+
192
+ ## Prevention Strategies
193
+
194
+ ### Pre-commit Hook with gitleaks
195
+
196
+ ```bash
197
+ # Install gitleaks
198
+ brew install gitleaks # macOS
199
+ # or download from https://github.com/gitleaks/gitleaks/releases
200
+
201
+ # Run manually
202
+ gitleaks detect --source . --verbose
203
+
204
+ # Pre-commit hook (.pre-commit-config.yaml)
205
+ repos:
206
+ - repo: https://github.com/gitleaks/gitleaks
207
+ rev: v8.18.0
208
+ hooks:
209
+ - id: gitleaks
210
+ ```
211
+
212
+ ### .gitignore Patterns
213
+
214
+ ```gitignore
215
+ # Environment files
216
+ .env
217
+ .env.*
218
+ !.env.example
219
+
220
+ # Private keys and certificates
221
+ *.pem
222
+ *.key
223
+ *.p12
224
+ *.pfx
225
+ *.jks
226
+
227
+ # Credential files
228
+ credentials.json
229
+ service-account*.json
230
+ *-credentials.*
231
+ *.keystore
232
+
233
+ # IDE and tool secrets
234
+ .idea/dataSources.xml
235
+ .vscode/settings.json # may contain tokens
236
+ ```
237
+
238
+ ### Emergency Response
239
+
240
+ If a secret is committed:
241
+
242
+ 1. **Rotate the secret immediately** -- this is the priority, not git history cleanup
243
+ 2. **Revoke the old secret** in the provider's console
244
+ 3. **Remove from git history** (optional, for hygiene):
245
+ ```bash
246
+ # Using git-filter-repo (preferred over filter-branch)
247
+ pip install git-filter-repo
248
+ git filter-repo --invert-paths --path secrets.json
249
+ ```
250
+ 4. **Force push** the cleaned history (coordinate with team)
251
+ 5. **Audit access logs** for the compromised secret's usage during exposure window
252
+
253
+ **Critical:** Removing a secret from git history does NOT make it safe. If the repo was ever pushed to a remote (GitHub, GitLab), the secret was cached by the platform and potentially scraped by bots within minutes. Always rotate first.