@activemind/scd 1.4.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 (79) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +417 -0
  3. package/bin/scd.js +140 -0
  4. package/lib/audit-report.js +93 -0
  5. package/lib/audit-sync.js +172 -0
  6. package/lib/audit.js +356 -0
  7. package/lib/cli-helpers.js +108 -0
  8. package/lib/commands/accept.js +28 -0
  9. package/lib/commands/audit.js +17 -0
  10. package/lib/commands/configure.js +200 -0
  11. package/lib/commands/doctor.js +14 -0
  12. package/lib/commands/exceptions.js +19 -0
  13. package/lib/commands/export-findings.js +46 -0
  14. package/lib/commands/findings.js +306 -0
  15. package/lib/commands/ignore.js +28 -0
  16. package/lib/commands/init.js +16 -0
  17. package/lib/commands/insights.js +24 -0
  18. package/lib/commands/install.js +15 -0
  19. package/lib/commands/list.js +109 -0
  20. package/lib/commands/remove.js +16 -0
  21. package/lib/commands/repo.js +862 -0
  22. package/lib/commands/report.js +234 -0
  23. package/lib/commands/resolve.js +25 -0
  24. package/lib/commands/rules.js +185 -0
  25. package/lib/commands/scan.js +519 -0
  26. package/lib/commands/scope.js +341 -0
  27. package/lib/commands/sync.js +40 -0
  28. package/lib/commands/uninstall.js +15 -0
  29. package/lib/commands/version.js +33 -0
  30. package/lib/comment-map.js +388 -0
  31. package/lib/config.js +325 -0
  32. package/lib/context-modifiers.js +211 -0
  33. package/lib/deep-analyzer.js +225 -0
  34. package/lib/doctor.js +236 -0
  35. package/lib/exception-manager.js +675 -0
  36. package/lib/export-findings.js +376 -0
  37. package/lib/file-context.js +380 -0
  38. package/lib/file-filter.js +204 -0
  39. package/lib/file-manifest.js +145 -0
  40. package/lib/git-utils.js +102 -0
  41. package/lib/global-config.js +239 -0
  42. package/lib/hooks-manager.js +130 -0
  43. package/lib/init-repo.js +147 -0
  44. package/lib/insights-analyzer.js +416 -0
  45. package/lib/insights-output.js +160 -0
  46. package/lib/installer.js +128 -0
  47. package/lib/output-constants.js +32 -0
  48. package/lib/output-terminal.js +407 -0
  49. package/lib/push-queue.js +322 -0
  50. package/lib/remove-repo.js +108 -0
  51. package/lib/repo-context.js +187 -0
  52. package/lib/report-html.js +1154 -0
  53. package/lib/report-index.js +157 -0
  54. package/lib/report-json.js +136 -0
  55. package/lib/report-markdown.js +250 -0
  56. package/lib/resolve-manager.js +148 -0
  57. package/lib/rule-registry.js +205 -0
  58. package/lib/scan-cache.js +171 -0
  59. package/lib/scan-context.js +312 -0
  60. package/lib/scan-schema.js +67 -0
  61. package/lib/scanner-full.js +681 -0
  62. package/lib/scanner-manual.js +348 -0
  63. package/lib/scanner-secrets.js +83 -0
  64. package/lib/scope.js +331 -0
  65. package/lib/store-verify.js +395 -0
  66. package/lib/store.js +310 -0
  67. package/lib/taint-register.js +196 -0
  68. package/lib/version-check.js +46 -0
  69. package/package.json +37 -0
  70. package/rules/rule-loader.js +324 -0
  71. package/rules/rules-aspx-cs.json +399 -0
  72. package/rules/rules-aspx.json +222 -0
  73. package/rules/rules-infra-leakage.json +434 -0
  74. package/rules/rules-js.json +664 -0
  75. package/rules/rules-php.json +521 -0
  76. package/rules/rules-python.json +466 -0
  77. package/rules/rules-secrets.json +99 -0
  78. package/rules/rules-sensitive-files.json +475 -0
  79. package/rules/rules-ts.json +76 -0
@@ -0,0 +1,434 @@
1
+ {
2
+ "schema_version": 1,
3
+ "rules": [
4
+ {
5
+ "id": "INFRA-001",
6
+ "name": "Hardcoded localhost URL in frontend code",
7
+ "severity": "EXPOSURE",
8
+ "category": "Infrastructure Leakage",
9
+ "pattern": "https?://localhost(?::\\d{2,5})?(?:/[^\\s\"'`]*)?",
10
+ "flags": "gi",
11
+ "extensions": ["js", "ts", "jsx", "tsx", "mjs", "cjs", "vue", "svelte", "html"],
12
+ "antipatterns": [
13
+ "===\\s*['\"]localhost",
14
+ "!==\\s*['\"]localhost",
15
+ "\\.includes\\s*\\(\\s*['\"]localhost",
16
+ "in\\s*\\([^)]*['\"]localhost",
17
+ "hostname\\s*(?:===|==|!==|!=)\\s*['\"]localhost",
18
+ "_BLOCKED|_BLOCKLIST|BLOCKED_HOST|block.*localhost|localhost.*block"
19
+ ],
20
+ "antipattern_flags": "i",
21
+ "skip_for_file_types": ["test", "fixture"],
22
+ "why": "A hardcoded localhost URL was found in browser-delivered frontend code. In production, localhost always resolves to the end user's own machine — this URL will always fail for real users and reveals that development configuration leaked into production code.",
23
+ "scenario": "A React component, Vue file, or client-side JS module contains a hardcoded http://localhost:3000/api URL. In production, every API call fails silently or with a network error because localhost resolves to the user's own machine.",
24
+ "fix": "Replace the hardcoded URL with an environment variable: process.env.REACT_APP_API_URL or import.meta.env.VITE_API_URL. Configure the value per environment in .env files locally and CI/CD secrets in production."
25
+ },
26
+ {
27
+ "id": "INFRA-001B",
28
+ "name": "Localhost reference in committed config file",
29
+ "severity": "EXPOSURE",
30
+ "category": "Infrastructure Leakage",
31
+ "pattern": "localhost",
32
+ "flags": "gi",
33
+ "extensions": ["ini", "conf", "cfg", "env", "properties", "toml"],
34
+ "antipatterns": [
35
+ "expected.*localhost",
36
+ "#.*localhost",
37
+ "(?<![a-z:/])//.*localhost",
38
+ "Must be set if and only if",
39
+ "description.*localhost",
40
+ "comment.*localhost",
41
+ "localhost.*comment"
42
+ ],
43
+ "antipattern_flags": "i",
44
+ "skip_for_file_types": ["test", "fixture"],
45
+ "why": "A localhost reference was found in a committed configuration file. This is typically a development default that should be replaced with environment-specific configuration before deployment. Committed dev config can expose internal service topology and cause silent failures in non-local environments.",
46
+ "scenario": "A docker-compose.yml or alembic.ini committed to the repository contains APP_URL=http://localhost:8000. When another developer or CI pipeline uses this file, services fail to connect because localhost refers to their own machine, not the intended service.",
47
+ "fix": "Use environment variables or separate config files per environment (.env.local, .env.production). Never commit files with hardcoded localhost as a service endpoint. Use docker-compose.override.yml for local-only settings."
48
+ },
49
+ {
50
+ "id": "INFRA-001C",
51
+ "name": "Localhost reference in JSON data file",
52
+ "severity": "LOW",
53
+ "category": "Infrastructure Leakage",
54
+ "pattern": "https?://localhost(?::\\d{2,5})?",
55
+ "flags": "gi",
56
+ "extensions": ["json"],
57
+ "antipatterns": [
58
+ "i18n",
59
+ "translation",
60
+ "expected_failure",
61
+ "(?<![a-z:/])//.*localhost"
62
+ ],
63
+ "antipattern_flags": "i",
64
+ "skip_for_file_types": ["test", "fixture"],
65
+ "why": "A localhost reference was found in a JSON file. This may be a hardcoded development URL in API configuration, i18n strings, or data fixtures that could cause failures in non-local environments.",
66
+ "scenario": "A JSON configuration file or translation file contains a hardcoded localhost URL that was copied from a development environment and never replaced.",
67
+ "fix": "Replace hardcoded localhost references with environment-aware configuration or placeholder values. Ensure JSON config files use environment variable substitution where supported."
68
+ },
69
+ {
70
+ "id": "INFRA-002",
71
+ "name": "Hardcoded 127.0.0.1 URL in frontend code",
72
+ "severity": "EXPOSURE",
73
+ "category": "Infrastructure Leakage",
74
+ "pattern": "(?:https?://)?127\\.0\\.0\\.1(?::\\d{2,5})?(?:/[^\\s\"'`]*)?",
75
+ "flags": "gi",
76
+ "extensions": ["js", "ts", "jsx", "tsx", "mjs", "cjs", "vue", "svelte", "html"],
77
+ "antipatterns": [
78
+ "===\\s*['\"]127\\.0\\.0\\.1",
79
+ "!==\\s*['\"]127\\.0\\.0\\.1",
80
+ "\\.includes\\s*\\(\\s*['\"]127\\.0\\.0\\.1",
81
+ "_BLOCKED|_BLOCKLIST|BLOCKED_HOST|block.*127|127.*block",
82
+ "expected.*127\\.0\\.0\\.1"
83
+ ],
84
+ "antipattern_flags": "i",
85
+ "skip_for_file_types": ["test", "fixture"],
86
+ "why": "A hardcoded 127.0.0.1 URL was found in browser-delivered frontend code. In production, 127.0.0.1 always resolves to the end user's own machine — this URL will always fail for real users and reveals that development configuration leaked into production code.",
87
+ "scenario": "A React component contains a hardcoded fetch('http://127.0.0.1:7398/api/data'). In production every API call fails because 127.0.0.1 resolves to the user's own machine, not the server.",
88
+ "fix": "Replace the hardcoded URL with an environment variable: process.env.REACT_APP_API_URL or import.meta.env.VITE_API_URL. Configure the value per environment in .env files locally and CI/CD secrets in production."
89
+ },
90
+ {
91
+ "id": "INFRA-002B",
92
+ "name": "127.0.0.1 reference in committed config file",
93
+ "severity": "EXPOSURE",
94
+ "category": "Infrastructure Leakage",
95
+ "pattern": "127\\.0\\.0\\.1",
96
+ "flags": "gi",
97
+ "extensions": ["ini", "conf", "cfg", "env", "properties", "toml", "php"],
98
+ "antipatterns": [
99
+ "env\\s*\\(",
100
+ "getenv\\s*\\(",
101
+ "os\\.environ",
102
+ "process\\.env",
103
+ "curl\\s+.*127\\.0\\.0\\.1",
104
+ "wget\\s+.*127\\.0\\.0\\.1",
105
+ "ping\\s+.*127\\.0\\.0\\.1",
106
+ "(?<![a-z:/])//.*127\\.0\\.0\\.1",
107
+ "#.*127\\.0\\.0\\.1",
108
+ "expected.*127\\.0\\.0\\.1",
109
+ "_BLOCKED|_BLOCKLIST|BLOCKED_HOST"
110
+ ],
111
+ "antipattern_flags": "i",
112
+ "skip_for_file_types": ["test", "fixture"],
113
+ "why": "A 127.0.0.1 reference was found in a committed configuration file. This is typically a development default that should be replaced with environment-specific configuration before deployment.",
114
+ "scenario": "A Laravel config/database.php committed to the repository contains 'host' => env('DB_HOST', '127.0.0.1'). Other developers or CI pipelines that don't set DB_HOST will silently connect to their own machine instead of the intended database server.",
115
+ "fix": "Ensure all host references use environment variables without hardcoded fallbacks for production-sensitive values. Use separate config files per environment and never commit 127.0.0.1 as a service host in shared config."
116
+ },
117
+ {
118
+ "id": "INFRA-002C",
119
+ "name": "127.0.0.1 reference in JSON data file",
120
+ "severity": "LOW",
121
+ "category": "Infrastructure Leakage",
122
+ "pattern": "https?://127\\.0\\.0\\.1(?::\\d{2,5})?",
123
+ "flags": "gi",
124
+ "extensions": ["json"],
125
+ "antipatterns": [
126
+ "expected.*127\\.0\\.0\\.1",
127
+ "(?<![a-z:/])//.*127\\.0\\.0\\.1"
128
+ ],
129
+ "antipattern_flags": "i",
130
+ "skip_for_file_types": ["test", "fixture"],
131
+ "why": "A 127.0.0.1 reference was found in a JSON file. This may be a hardcoded development address in API configuration or data fixtures that could cause failures in non-local environments.",
132
+ "scenario": "A JSON configuration file contains a hardcoded 127.0.0.1 address that was copied from a development environment and never replaced with a proper hostname or environment variable.",
133
+ "fix": "Replace hardcoded 127.0.0.1 references with environment-aware configuration or placeholder values."
134
+ },
135
+ {
136
+ "id": "INFRA-003",
137
+ "name": "IPv6 loopback address (::1)",
138
+ "severity": "EXPOSURE",
139
+ "category": "Infrastructure Leakage",
140
+ "pattern": "(?:=\\s*[\"'`]|[\"'`])[^\\n]{0,30}::1(?::\\d{2,5})?[\"'`]",
141
+ "flags": "gim",
142
+ "antipattern": "(?:e\\.g\\.|i\\.e\\.|must include|not just|example|documentation|note:|see also|_has_ipv6|is_loopback|is_reserved|==|!=)",
143
+ "antipattern_flags": "i",
144
+ "lookahead": 150,
145
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
146
+ "why": "The IPv6 loopback address ::1 reveals that the system runs IPv6 internally — useful intelligence for an attacker mapping your infrastructure.",
147
+ "scenario": "An nginx config committed to a public repo contains `listen [::1]:8080`. This tells an attacker both the port and that IPv6 is active internally.",
148
+ "fix": "Move host/port bindings to environment configuration. Never commit network binding details to source control."
149
+ },
150
+ {
151
+ "id": "INFRA-010",
152
+ "name": "Hardcoded 10.x.x.x private network address",
153
+ "severity": "EXPOSURE",
154
+ "category": "Infrastructure Leakage",
155
+ "pattern": "[\"'`\\s(=:/,]10\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})(?::\\d{2,5})?(?:[\"'`\\s)/,]|$)",
156
+ "flags": "gim",
157
+ "antipattern_preset": "DEV_CONTEXT",
158
+ "antipattern_flags": "i",
159
+ "lookahead": 150,
160
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
161
+ "why": "RFC 1918 addresses (10.0.0.0/8) are private internal network addresses. Their presence in source code reveals your internal network topology — subnet layout, server locations, and service architecture — to anyone who can read the code.",
162
+ "scenario": "A deployment script contains `DB_HOST=10.0.1.45`. An attacker who gains any level of access (even read-only to the repo) now knows an internal database server IP. Combined with other findings, this helps plan lateral movement.",
163
+ "fix": "Never hardcode private IP addresses. Use DNS names with environment-specific resolution, or environment variables. Internal service discovery (Consul, Kubernetes DNS) should handle routing."
164
+ },
165
+ {
166
+ "id": "INFRA-011",
167
+ "name": "Hardcoded 172.16–31.x.x private network address",
168
+ "severity": "EXPOSURE",
169
+ "category": "Infrastructure Leakage",
170
+ "pattern": "[\"'`\\s(=:/,]172\\.(?:1[6-9]|2\\d|3[01])\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})(?::\\d{2,5})?(?:[\"'`\\s)/,]|$)",
171
+ "flags": "gim",
172
+ "antipattern_preset": "DEV_CONTEXT",
173
+ "antipattern_flags": "i",
174
+ "lookahead": 150,
175
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
176
+ "why": "The 172.16.0.0/12 range is a private address block commonly used for Docker networks, VPNs, and internal subnets. Exposure reveals network segmentation details.",
177
+ "scenario": "A Docker Compose file references `172.20.0.5` as a service IP. This reveals your Docker subnet configuration and makes container network enumeration easier if an attacker gains a foothold.",
178
+ "fix": "Use Docker service names or Kubernetes service DNS names instead of static IPs. Let orchestration handle IP assignment."
179
+ },
180
+ {
181
+ "id": "INFRA-012",
182
+ "name": "Hardcoded 192.168.x.x private network address",
183
+ "severity": "EXPOSURE",
184
+ "category": "Infrastructure Leakage",
185
+ "pattern": "(?:[=:\\s(]\\s*[\"'`]|https?:\\/\\/|[\"'`]\\s*[+]\\s*|\\$\\{)192\\.168\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})(?::\\d{2,5})?(?:[\"'`\\s)/,]|$)",
186
+ "flags": "gim",
187
+ "antipattern_preset": "DEV_CONTEXT",
188
+ "antipattern": "(?:==\\s*['\"`]|!=\\s*['\"`]|\\.startswith\\s*\\(|netloc\\s*==|\\.host\\s*==|is_loopback|is_private|is_reserved|_has_ipv6|check.*local|local.*check|returns\\s+(?:True|False)\\s+if|e\\.g\\.|i\\.e\\.|for\\s+example|#.*if\\s+ip\\s*=|#.*ip\\s*=|log\\.(?:debug|info|warning|error|critical)\\s*\\()",
189
+ "antipattern_flags": "i",
190
+ "lookahead": 150,
191
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
192
+ "why": "192.168.x.x is the most common private address range for office and home networks. References in code often come from local development and signal that proper environment abstraction is missing.",
193
+ "scenario": "A PHP config file has `$db_host = \"192.168.1.10\"` — likely a developer's local machine IP. If deployed, the application fails in production and exposes local network details to anyone reading the code.",
194
+ "fix": "Use environment variables or service discovery. If this is truly a local-only value, ensure it is in .env (which must be gitignored) rather than in committed config files."
195
+ },
196
+ {
197
+ "id": "INFRA-020",
198
+ "name": "Internal hostname pattern in URL (dev/staging/internal subdomain)",
199
+ "severity": "EXPOSURE",
200
+ "category": "Infrastructure Leakage",
201
+ "pattern": "https?:\\/\\/(?:dev|staging|stage|test|uat|qa|preprod|internal|intranet|corp|local|private|admin|backend|api-internal|int)\\.(?!(?:w3|mozilla|ietf|whatwg|github|google|microsoft|apple|amazon|cloudflare|fastly|example|jquery|npmjs|nodejs)\\b)",
202
+ "flags": "gi",
203
+ "antipattern": "(?:w3\\.org|mozilla\\.org|ietf\\.org|whatwg\\.org|example\\.com|jquery\\.com|draft\\.csswg|spec\\.)",
204
+ "antipattern_flags": "i",
205
+ "lookahead": 80,
206
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
207
+ "confidence_rules": [
208
+ { "if_file_context": ["test", "backend"], "then": "LOW" },
209
+ { "if_file_context": "frontend", "then": "HIGH" },
210
+ { "if_file_context": "doc", "then": "MEDIUM"},
211
+ { "default": "MEDIUM" }
212
+ ],
213
+ "why": "Internal subdomain names in source code reveal your environment structure, naming conventions, and potentially accessible internal services. This is valuable OSINT for an attacker.",
214
+ "scenario": "A frontend config has `API_BASE: \"https://api-internal.company.com\"`. An attacker now knows an internal API endpoint exists, its naming convention, and can probe it for access controls.",
215
+ "fix": "Use environment variables for all base URLs. The running environment should inject the correct URL — source code should never know whether it is dev, staging, or production."
216
+ },
217
+ {
218
+ "id": "INFRA-021",
219
+ "name": "Non-public TLD in hardcoded URL (.local, .internal, .corp, .lan)",
220
+ "severity": "EXPOSURE",
221
+ "category": "Infrastructure Leakage",
222
+ "pattern": "https?:\\/\\/[a-z0-9.-]+\\.(?:local|internal|corp|intranet|lan|priv|home|localdomain)(?=[:/\\s\"'`]|$)(?::\\d{2,5})?(?:\\/[^\\s\"'`]*)?",
223
+ "flags": "gi",
224
+ "antipattern_preset": "LINK_EXAMPLE",
225
+ "antipattern_flags": "i",
226
+ "lookahead": 80,
227
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
228
+ "confidence_rules": [
229
+ { "if_file_context": ["test", "backend"], "then": "LOW" },
230
+ { "if_file_context": "frontend", "then": "HIGH" },
231
+ { "if_file_context": "doc", "then": "MEDIUM"},
232
+ { "default": "MEDIUM" }
233
+ ],
234
+ "why": "Non-public TLDs (.local, .internal, .corp) are exclusively used for internal DNS resolution. Their presence in code reveals internal naming conventions and network architecture.",
235
+ "scenario": "A Kubernetes manifest references `http://redis.internal:6379`. This exposes the internal DNS name and port of your Redis service to anyone reading the manifest in a public repo.",
236
+ "fix": "Replace internal DNS names with Kubernetes service names (e.g. `redis:6379`) or inject via environment variables. Avoid committing any .internal / .local / .corp hostnames."
237
+ },
238
+ {
239
+ "id": "INFRA-022",
240
+ "name": "Possible internal server hostname (short hostname without TLD)",
241
+ "severity": "EXPOSURE",
242
+ "category": "Infrastructure Leakage",
243
+ "pattern": "(?:mongodb|postgres|mysql|redis|amqp|http|https):\\/\\/[a-z][a-z0-9-]{2,20}(?::\\d{2,5})?\\/(?![\\/])",
244
+ "flags": "gi",
245
+ "antipattern": "(?:localhost|127\\.0\\.0|example|sample|placeholder|e\\.g\\.|i\\.e\\.|for\\s+example)",
246
+ "antipattern_flags": "i",
247
+ "lookahead": 100,
248
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
249
+ "why": "Bare hostnames in connection strings or URLs (without a domain) indicate internal server names used within a private network. These names reveal infrastructure naming conventions.",
250
+ "scenario": "A Node.js app config has `MONGO_URI: \"mongodb://mongo01/mydb\"`. The hostname \"mongo01\" reveals that MongoDB servers follow a numbered naming convention, helping an attacker enumerate infrastructure.",
251
+ "fix": "Use environment variables for all connection strings. Never commit internal server names to source control."
252
+ },
253
+ {
254
+ "id": "INFRA-030",
255
+ "name": "Database port hardcoded in connection string (PostgreSQL 5432)",
256
+ "severity": "HIGH",
257
+ "category": "Infrastructure Leakage",
258
+ "pattern": "(?:postgres(?:ql)?|jdbc:postgresql):\\/\\/[^\"'\\s]{3,}:5432",
259
+ "flags": "gi",
260
+ "antipattern_preset": "DEV_CONTEXT",
261
+ "antipattern_flags": "i",
262
+ "lookahead": 200,
263
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
264
+ "why": "A hardcoded PostgreSQL connection string exposes both the server address and confirms PostgreSQL is used. Combined with other findings, this provides enough information to target the database directly.",
265
+ "scenario": "A connection string `postgresql://10.0.1.45:5432/production_db` is found in a config file. An attacker now has the server IP, port, database type, and database name — everything needed for a targeted attack.",
266
+ "fix": "Store the entire connection string in an environment variable: `DATABASE_URL=os.environ[\"DATABASE_URL\"]`. Never hardcode any part of a production connection string."
267
+ },
268
+ {
269
+ "id": "INFRA-031",
270
+ "name": "Database port hardcoded in connection string (MySQL/MariaDB 3306)",
271
+ "severity": "HIGH",
272
+ "category": "Infrastructure Leakage",
273
+ "pattern": "(?:mysql|mariadb|jdbc:mysql):\\/\\/[^\"'\\s]{3,}:3306",
274
+ "flags": "gi",
275
+ "antipattern_preset": "DEV_CONTEXT",
276
+ "antipattern_flags": "i",
277
+ "lookahead": 200,
278
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
279
+ "why": "MySQL/MariaDB connection strings with hardcoded hosts and ports reveal database infrastructure. Port 3306 is the default and well-known; its presence confirms the database type.",
280
+ "scenario": "CI/CD pipeline config contains `mysql://admin:pass@192.168.1.20:3306/app`. This exposes credentials, internal IP, and confirms MySQL — a complete attack package.",
281
+ "fix": "Use environment variables for all database connection details. Treat any committed connection string as fully compromised."
282
+ },
283
+ {
284
+ "id": "INFRA-032",
285
+ "name": "Redis port hardcoded in connection string (6379)",
286
+ "severity": "EXPOSURE",
287
+ "category": "Infrastructure Leakage",
288
+ "pattern": "(?:redis(?:s)?):\\/\\/[^\"'\\s]{3,}:6379",
289
+ "flags": "gi",
290
+ "antipattern_preset": "DEV_CONTEXT",
291
+ "antipattern_flags": "i",
292
+ "lookahead": 150,
293
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
294
+ "why": "Redis on its default port is a common target for attacks when exposed. Hardcoded Redis connection strings reveal server location and confirm caching/session infrastructure.",
295
+ "scenario": "A session config has `REDIS_URL = \"redis://10.0.2.10:6379\"`. An attacker who gains network access now has a direct target for session hijacking attacks.",
296
+ "fix": "Store Redis connection details in environment variables. Ensure Redis requires authentication (`requirepass`) and is not exposed outside the internal network."
297
+ },
298
+ {
299
+ "id": "INFRA-033",
300
+ "name": "MongoDB port hardcoded in connection string (27017)",
301
+ "severity": "EXPOSURE",
302
+ "category": "Infrastructure Leakage",
303
+ "pattern": "mongodb(?:\\+srv)?:\\/\\/[^\"'\\s]{3,}:27017",
304
+ "flags": "gi",
305
+ "antipattern_preset": "DEV_CONTEXT",
306
+ "antipattern_flags": "i",
307
+ "lookahead": 150,
308
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
309
+ "why": "MongoDB on port 27017 has historically been a target for mass scanning attacks due to open instances. Revealing the host and port in source code increases targeted attack risk.",
310
+ "scenario": "An app config has `MONGO_URI = \"mongodb://mongo.internal:27017/users\"`. This reveals both the internal hostname and that MongoDB stores user data — a high-value target.",
311
+ "fix": "Use environment variable `MONGODB_URI`. Ensure MongoDB requires authentication and bind to non-public interfaces only."
312
+ },
313
+ {
314
+ "id": "INFRA-034",
315
+ "name": "Elasticsearch port hardcoded (9200/9300)",
316
+ "severity": "EXPOSURE",
317
+ "category": "Infrastructure Leakage",
318
+ "pattern": "https?:\\/\\/[^\"'\\s]{3,}:(?:9200|9300)(?:[\\/\"'\\s]|$)",
319
+ "flags": "gi",
320
+ "antipattern_preset": "DEV_CONTEXT",
321
+ "antipattern_flags": "i",
322
+ "lookahead": 150,
323
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
324
+ "why": "Elasticsearch is frequently misconfigured with no authentication. Exposing the host and port in source code makes it trivially easy to attempt direct data access.",
325
+ "scenario": "A search service config has `ES_HOST = \"http://10.0.3.15:9200\"`. An attacker with network access can directly query Elasticsearch for indexed data.",
326
+ "fix": "Use environment variables. Enable Elasticsearch X-Pack security and authentication. Bind to non-public interfaces."
327
+ },
328
+ {
329
+ "id": "INFRA-035",
330
+ "name": "RabbitMQ/AMQP port hardcoded (5672/15672)",
331
+ "severity": "EXPOSURE",
332
+ "category": "Infrastructure Leakage",
333
+ "pattern": "amqps?:\\/\\/[^\"'\\s]{3,}:(?:5672|15672)",
334
+ "flags": "gi",
335
+ "antipattern_preset": "DEV_CONTEXT",
336
+ "antipattern_flags": "i",
337
+ "lookahead": 150,
338
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
339
+ "why": "Message queue servers are critical infrastructure. Exposing AMQP connection details reveals queue topology and provides a target for message injection or eavesdropping attacks.",
340
+ "scenario": "A worker service config has `AMQP_URL = \"amqp://user:pass@10.0.4.20:5672\"`. An attacker can now inject malicious messages into the queue, potentially triggering unintended actions.",
341
+ "fix": "Store AMQP connection strings in environment variables. Use TLS (amqps://) and rotate credentials if exposed."
342
+ },
343
+ {
344
+ "id": "INFRA-036",
345
+ "name": "Internal admin/management port hardcoded (8080, 8443, 9090, 9443)",
346
+ "severity": "EXPOSURE",
347
+ "category": "Infrastructure Leakage",
348
+ "pattern": "https?:\\/\\/(?:localhost|127\\.0\\.0\\.1|10\\.|172\\.(?:1[6-9]|2\\d|3[01])\\.|192\\.168\\.)[^\"'\\s]*:(?:8080|8443|9090|9443|4848|8161|8888)(?:[\\/\"'\\s]|$)",
349
+ "flags": "gi",
350
+ "antipattern": "(?:example|sample|placeholder|TODO|FIXME|NOTE|demo|mock|fake|dummy|test|spec|localhost_only|dev.only|development.only|log\\.(?:debug|info|warning|error|critical)\\s*\\(|e\\.g\\.|i\\.e\\.)",
351
+ "antipattern_flags": "i",
352
+ "lookahead": 150,
353
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
354
+ "why": "Management and admin ports (8080, 8443, 9090 etc.) are often less protected than primary application ports. Their exposure in source code, combined with an internal IP, reveals management interfaces.",
355
+ "scenario": "A monitoring config contains `http://10.0.1.5:9090/metrics`. This reveals a Prometheus endpoint on an internal server — useful for mapping the monitoring infrastructure.",
356
+ "fix": "Move all admin/management URLs to environment variables. Restrict management interfaces to specific network segments."
357
+ },
358
+ {
359
+ "id": "INFRA-040",
360
+ "name": "Internal IP address in code comment",
361
+ "severity": "EXPOSURE",
362
+ "category": "Infrastructure Leakage",
363
+ "pattern": "(?<!:)(?:\\/\\/|#|<!--|\\\/\\*)(?!.*https?:\\/\\/)[^\\n]*(?:10\\.(?:\\d{1,3}\\.){2}\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.(?:\\d{1,3}\\.)\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|127\\.0\\.0\\.1)",
364
+ "flags": "gim",
365
+ "antipattern": "(?:example|sample|placeholder|demo|mock|fake|dummy|returns\\s+(?:True|False)|e\\.g\\.|i\\.e\\.|for\\s+example|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}.*\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})",
366
+ "antipattern_flags": "i",
367
+ "lookahead": 200,
368
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
369
+ "why": "Comments containing internal IP addresses are often left-over notes from development. They are never sanitised by minifiers or build processes and persist in git history forever.",
370
+ "scenario": "A JavaScript file has `// TODO: update endpoint – currently points to 10.0.1.45:3000 on prod`. This comment is in the production bundle, visible to anyone who opens DevTools.",
371
+ "fix": "Remove all infrastructure references from comments before committing. Use ticket references (e.g. \"// See INFRA-1234\") instead of IP addresses or server names."
372
+ },
373
+ {
374
+ "id": "INFRA-041",
375
+ "name": "Internal hostname or server name in code comment",
376
+ "severity": "EXPOSURE",
377
+ "category": "Infrastructure Leakage",
378
+ "pattern": "(?:\\/\\/|#|<!--|\\\/\\*)[^\\n]*https?:\\/\\/(?:dev|staging|internal|intranet|corp|local|admin|backend)\\.[a-z0-9.-]+",
379
+ "flags": "gim",
380
+ "antipattern": "(?:w3\\.org|mozilla\\.org|ietf\\.org|whatwg\\.org|csswg|draft\\.|spec\\.|rfc\\d|standards\\.)",
381
+ "antipattern_flags": "i",
382
+ "lookahead": 500,
383
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
384
+ "why": "Internal URLs in comments reveal the same information as hardcoded strings, but are often overlooked because they are 'just comments'. They survive minification, transpilation, and stay in git history.",
385
+ "scenario": "A comment says `// old API was at http://internal.company.com/api/v1`. The internal API hostname is now visible to anyone reading the committed file.",
386
+ "fix": "Treat comments the same as code for sensitive information. Remove server names, internal URLs, and IP addresses from all comments."
387
+ },
388
+ {
389
+ "id": "INFRA-042",
390
+ "name": "Port number with server context in comment",
391
+ "severity": "EXPOSURE",
392
+ "category": "Infrastructure Leakage",
393
+ "pattern": "(?:\\/\\/|#|<!--|\\\/\\*)[^\\n]{0,200}(?:port\\s+\\d{4,5}|(?:running on|listens on|connects to|forwarded to)[^\\n]{0,80}:\\d{4,5})",
394
+ "flags": "gim",
395
+ "antipattern_preset": "DEV_CONTEXT",
396
+ "antipattern_flags": "i",
397
+ "lookahead": 150,
398
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
399
+ "why": "Comments describing service ports and connections are developer notes that expose network architecture. They are typically accurate because developers write them as reminders.",
400
+ "scenario": "`// proxy forwards to backend running on port 8080` — this comment tells an attacker exactly what to look for when they gain access to the network.",
401
+ "fix": "Remove connection and port descriptions from comments. Architecture documentation belongs in internal wikis, not in code comments."
402
+ },
403
+ {
404
+ "id": "INFRA-050",
405
+ "name": "Database connection string with internal IP address",
406
+ "severity": "HIGH",
407
+ "category": "Infrastructure Leakage",
408
+ "pattern": "(?:jdbc:|mongodb(?:\\+srv)?:|postgresql:|mysql:|redis:|amqp:)\\/\\/[^\"'\\s]*(?:10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3})[^\"'\\s]*",
409
+ "flags": "gi",
410
+ "antipattern_preset": "DEV_CONTEXT",
411
+ "antipattern_flags": "i",
412
+ "lookahead": 250,
413
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
414
+ "why": "A complete connection string with an internal IP address reveals: the database type, exact server location, port, and potentially database name — the complete information needed to attempt a direct attack if any network access is obtained.",
415
+ "scenario": "A JDBC connection string `jdbc:postgresql://10.0.1.20:5432/production` is found in a config file. An attacker who gains any internal network access can immediately target this server.",
416
+ "fix": "This is HIGH severity. Store the entire connection string as a single environment variable. Audit git history for this value and rotate all credentials. Consider this information compromised."
417
+ },
418
+ {
419
+ "id": "INFRA-051",
420
+ "name": "Generic URL with internal IP (non-database services)",
421
+ "severity": "HIGH",
422
+ "category": "Infrastructure Leakage",
423
+ "pattern": "https?:\\/\\/(?:10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3})(?::\\d{2,5})?(?:\\/[^\\s\"'`]*)?",
424
+ "flags": "gi",
425
+ "antipattern_preset": "DEV_CONTEXT",
426
+ "antipattern_flags": "i",
427
+ "lookahead": 200,
428
+ "exclude_file_types": ["md", "txt", "yml", "yaml"],
429
+ "why": "A full URL with an internal IP address exposes not just the IP but also the path structure and API layout of internal services. This is immediately actionable intelligence for an attacker.",
430
+ "scenario": "A frontend config has `INTERNAL_API: \"http://10.0.2.30:8080/api/v2/admin\"`. This reveals the internal admin API location, its version, and that it runs on port 8080.",
431
+ "fix": "Replace with an environment variable. Audit all configurations for similar patterns. Treat the internal service location as potentially known to attackers."
432
+ }
433
+ ]
434
+ }