@datahogo/core 0.1.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.
- package/LICENSE +661 -0
- package/README.md +17 -0
- package/dist/engines/config.d.ts +3 -0
- package/dist/engines/config.d.ts.map +1 -0
- package/dist/engines/config.js +433 -0
- package/dist/engines/config.js.map +1 -0
- package/dist/engines/dast.d.ts +3 -0
- package/dist/engines/dast.d.ts.map +1 -0
- package/dist/engines/dast.js +167 -0
- package/dist/engines/dast.js.map +1 -0
- package/dist/engines/db-rules.d.ts +3 -0
- package/dist/engines/db-rules.d.ts.map +1 -0
- package/dist/engines/db-rules.js +166 -0
- package/dist/engines/db-rules.js.map +1 -0
- package/dist/engines/dependencies.d.ts +3 -0
- package/dist/engines/dependencies.d.ts.map +1 -0
- package/dist/engines/dependencies.js +167 -0
- package/dist/engines/dependencies.js.map +1 -0
- package/dist/engines/github-actions.d.ts +3 -0
- package/dist/engines/github-actions.d.ts.map +1 -0
- package/dist/engines/github-actions.js +215 -0
- package/dist/engines/github-actions.js.map +1 -0
- package/dist/engines/gitleaks.d.ts +3 -0
- package/dist/engines/gitleaks.d.ts.map +1 -0
- package/dist/engines/gitleaks.js +107 -0
- package/dist/engines/gitleaks.js.map +1 -0
- package/dist/engines/npm-audit.d.ts +3 -0
- package/dist/engines/npm-audit.d.ts.map +1 -0
- package/dist/engines/npm-audit.js +113 -0
- package/dist/engines/npm-audit.js.map +1 -0
- package/dist/engines/patterns.d.ts +3 -0
- package/dist/engines/patterns.d.ts.map +1 -0
- package/dist/engines/patterns.js +1330 -0
- package/dist/engines/patterns.js.map +1 -0
- package/dist/engines/secrets.d.ts +4 -0
- package/dist/engines/secrets.d.ts.map +1 -0
- package/dist/engines/secrets.js +260 -0
- package/dist/engines/secrets.js.map +1 -0
- package/dist/engines/semgrep.d.ts +3 -0
- package/dist/engines/semgrep.d.ts.map +1 -0
- package/dist/engines/semgrep.js +173 -0
- package/dist/engines/semgrep.js.map +1 -0
- package/dist/engines/types.d.ts +30 -0
- package/dist/engines/types.d.ts.map +1 -0
- package/dist/engines/types.js +3 -0
- package/dist/engines/types.js.map +1 -0
- package/dist/engines/url-scanner.d.ts +3 -0
- package/dist/engines/url-scanner.d.ts.map +1 -0
- package/dist/engines/url-scanner.js +469 -0
- package/dist/engines/url-scanner.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +32 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +237 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/rules/.gitkeep +0 -0
- package/dist/rules/ai-llm-security.yaml +199 -0
- package/dist/rules/api-security.yaml +489 -0
- package/dist/rules/auth-patterns.yaml +406 -0
- package/dist/rules/crypto-patterns.yaml +227 -0
- package/dist/rules/database-cloud-security.yaml +169 -0
- package/dist/rules/general-security.yaml +588 -0
- package/dist/rules/injection-patterns.yaml +318 -0
- package/dist/rules/nextjs-security.yaml +532 -0
- package/dist/rules/node-security.yaml +380 -0
- package/dist/rules/rules/.gitkeep +0 -0
- package/dist/rules/rules/ai-llm-security.yaml +199 -0
- package/dist/rules/rules/api-security.yaml +489 -0
- package/dist/rules/rules/auth-patterns.yaml +406 -0
- package/dist/rules/rules/crypto-patterns.yaml +227 -0
- package/dist/rules/rules/database-cloud-security.yaml +169 -0
- package/dist/rules/rules/general-security.yaml +588 -0
- package/dist/rules/rules/injection-patterns.yaml +318 -0
- package/dist/rules/rules/nextjs-security.yaml +532 -0
- package/dist/rules/rules/node-security.yaml +380 -0
- package/dist/rules/rules/supabase-security.yaml +387 -0
- package/dist/rules/supabase-security.yaml +387 -0
- package/dist/scanning/agents/csharp-agent.d.ts +12 -0
- package/dist/scanning/agents/csharp-agent.d.ts.map +1 -0
- package/dist/scanning/agents/csharp-agent.js +592 -0
- package/dist/scanning/agents/csharp-agent.js.map +1 -0
- package/dist/scanning/agents/go-agent.d.ts +14 -0
- package/dist/scanning/agents/go-agent.d.ts.map +1 -0
- package/dist/scanning/agents/go-agent.js +641 -0
- package/dist/scanning/agents/go-agent.js.map +1 -0
- package/dist/scanning/agents/java-agent.d.ts +8 -0
- package/dist/scanning/agents/java-agent.d.ts.map +1 -0
- package/dist/scanning/agents/java-agent.js +807 -0
- package/dist/scanning/agents/java-agent.js.map +1 -0
- package/dist/scanning/agents/javascript-agent.d.ts +8 -0
- package/dist/scanning/agents/javascript-agent.d.ts.map +1 -0
- package/dist/scanning/agents/javascript-agent.js +77 -0
- package/dist/scanning/agents/javascript-agent.js.map +1 -0
- package/dist/scanning/agents/mobile-agent.d.ts +8 -0
- package/dist/scanning/agents/mobile-agent.d.ts.map +1 -0
- package/dist/scanning/agents/mobile-agent.js +916 -0
- package/dist/scanning/agents/mobile-agent.js.map +1 -0
- package/dist/scanning/agents/php-agent.d.ts +8 -0
- package/dist/scanning/agents/php-agent.d.ts.map +1 -0
- package/dist/scanning/agents/php-agent.js +679 -0
- package/dist/scanning/agents/php-agent.js.map +1 -0
- package/dist/scanning/agents/python-agent.d.ts +8 -0
- package/dist/scanning/agents/python-agent.d.ts.map +1 -0
- package/dist/scanning/agents/python-agent.js +701 -0
- package/dist/scanning/agents/python-agent.js.map +1 -0
- package/dist/scanning/agents/supabase-agent.d.ts +8 -0
- package/dist/scanning/agents/supabase-agent.d.ts.map +1 -0
- package/dist/scanning/agents/supabase-agent.js +484 -0
- package/dist/scanning/agents/supabase-agent.js.map +1 -0
- package/dist/scanning/orchestrator.d.ts +29 -0
- package/dist/scanning/orchestrator.d.ts.map +1 -0
- package/dist/scanning/orchestrator.js +186 -0
- package/dist/scanning/orchestrator.js.map +1 -0
- package/dist/scanning/tech-detector.d.ts +12 -0
- package/dist/scanning/tech-detector.d.ts.map +1 -0
- package/dist/scanning/tech-detector.js +252 -0
- package/dist/scanning/tech-detector.js.map +1 -0
- package/dist/scanning/types.d.ts +87 -0
- package/dist/scanning/types.d.ts.map +1 -0
- package/dist/scanning/types.js +5 -0
- package/dist/scanning/types.js.map +1 -0
- package/dist/utils/child-process.d.ts +2 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +4 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/context-classifier.d.ts +11 -0
- package/dist/utils/context-classifier.d.ts.map +1 -0
- package/dist/utils/context-classifier.js +79 -0
- package/dist/utils/context-classifier.js.map +1 -0
- package/dist/utils/exec.d.ts +18 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +51 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/file-filter.d.ts +4 -0
- package/dist/utils/file-filter.d.ts.map +1 -0
- package/dist/utils/file-filter.js +68 -0
- package/dist/utils/file-filter.js.map +1 -0
- package/dist/utils/fs.d.ts +2 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +5 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/post-processor.d.ts +10 -0
- package/dist/utils/post-processor.d.ts.map +1 -0
- package/dist/utils/post-processor.js +183 -0
- package/dist/utils/post-processor.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
# ID 128: Prototype pollution - deepMerge / lodash.merge without proto filter
|
|
3
|
+
- id: datahogo-prototype-pollution-merge
|
|
4
|
+
patterns:
|
|
5
|
+
- pattern-either:
|
|
6
|
+
- pattern: _.merge($OBJ, $REQ.body)
|
|
7
|
+
- pattern: _.merge($OBJ, $USER_INPUT)
|
|
8
|
+
- pattern: lodash.merge($OBJ, $REQ.body)
|
|
9
|
+
- pattern: deepmerge($OBJ, $REQ.body)
|
|
10
|
+
- pattern: merge($OBJ, $REQ.body)
|
|
11
|
+
message: "Merging user-controlled object without sanitization can cause prototype pollution - filter __proto__ and constructor keys"
|
|
12
|
+
severity: ERROR
|
|
13
|
+
languages: [typescript, javascript]
|
|
14
|
+
metadata:
|
|
15
|
+
datahogo_id: 128
|
|
16
|
+
datahogo_category: "node-security"
|
|
17
|
+
owasp_ref: "A03:2021"
|
|
18
|
+
|
|
19
|
+
- id: datahogo-prototype-pollution-bracket
|
|
20
|
+
patterns:
|
|
21
|
+
- pattern: |
|
|
22
|
+
$OBJ[$REQ.body.$KEY] = $REQ.body.$VALUE
|
|
23
|
+
- pattern-not: |
|
|
24
|
+
if ($KEY !== '__proto__' && $KEY !== 'constructor')
|
|
25
|
+
message: "Dynamic property assignment with user-controlled key can cause prototype pollution"
|
|
26
|
+
severity: ERROR
|
|
27
|
+
languages: [typescript, javascript]
|
|
28
|
+
metadata:
|
|
29
|
+
datahogo_id: 128
|
|
30
|
+
datahogo_category: "node-security"
|
|
31
|
+
owasp_ref: "A03:2021"
|
|
32
|
+
|
|
33
|
+
- id: datahogo-prototype-pollution-dynamic-key
|
|
34
|
+
patterns:
|
|
35
|
+
- pattern: |
|
|
36
|
+
function $FUNC($OBJ, $KEY, $VALUE) {
|
|
37
|
+
...
|
|
38
|
+
$OBJ[$KEY] = $VALUE
|
|
39
|
+
...
|
|
40
|
+
}
|
|
41
|
+
- pattern-not: |
|
|
42
|
+
if ($KEY === '__proto__' || $KEY === 'constructor' || $KEY === 'prototype')
|
|
43
|
+
- pattern-not: |
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(Object.prototype, $KEY))
|
|
45
|
+
message: "Deep assignment function missing prototype pollution protection - reject __proto__, constructor, and prototype keys"
|
|
46
|
+
severity: WARNING
|
|
47
|
+
languages: [typescript, javascript]
|
|
48
|
+
metadata:
|
|
49
|
+
datahogo_id: 128
|
|
50
|
+
datahogo_category: "node-security"
|
|
51
|
+
owasp_ref: "A03:2021"
|
|
52
|
+
|
|
53
|
+
# ID 129: ReDoS - regex with nested quantifiers
|
|
54
|
+
- id: datahogo-redos-nested-quantifiers
|
|
55
|
+
patterns:
|
|
56
|
+
- pattern-either:
|
|
57
|
+
- pattern: |
|
|
58
|
+
const $RE = /($PATTERN+)+/
|
|
59
|
+
- pattern: |
|
|
60
|
+
const $RE = /($PATTERN*)+/
|
|
61
|
+
- pattern: |
|
|
62
|
+
const $RE = /($PATTERN+)*/
|
|
63
|
+
- pattern: |
|
|
64
|
+
new RegExp("($PATTERN+)+")
|
|
65
|
+
- pattern: |
|
|
66
|
+
new RegExp("($PATTERN*)+")
|
|
67
|
+
message: "Regex with nested quantifiers (e.g. (a+)+) is vulnerable to ReDoS with crafted input - simplify or use a linear-time library"
|
|
68
|
+
severity: WARNING
|
|
69
|
+
languages: [typescript, javascript]
|
|
70
|
+
metadata:
|
|
71
|
+
datahogo_id: 129
|
|
72
|
+
datahogo_category: "node-security"
|
|
73
|
+
owasp_ref: "A05:2021"
|
|
74
|
+
|
|
75
|
+
- id: datahogo-redos-user-input-regex
|
|
76
|
+
patterns:
|
|
77
|
+
- pattern-either:
|
|
78
|
+
- pattern: new RegExp($REQ.body.$FIELD)
|
|
79
|
+
- pattern: new RegExp($REQ.query.$PARAM)
|
|
80
|
+
- pattern: new RegExp($USER_INPUT)
|
|
81
|
+
- pattern-not: |
|
|
82
|
+
safe-regex($INPUT)
|
|
83
|
+
message: "Regex constructed from user input can cause ReDoS or be abused for information disclosure - never allow user-defined regexes"
|
|
84
|
+
severity: ERROR
|
|
85
|
+
languages: [typescript, javascript]
|
|
86
|
+
metadata:
|
|
87
|
+
datahogo_id: 129
|
|
88
|
+
datahogo_category: "node-security"
|
|
89
|
+
owasp_ref: "A05:2021"
|
|
90
|
+
|
|
91
|
+
# ID 130: Insecure randomness
|
|
92
|
+
- id: datahogo-math-random-id
|
|
93
|
+
patterns:
|
|
94
|
+
- pattern-either:
|
|
95
|
+
- pattern: |
|
|
96
|
+
const $ID = Math.random().toString($BASE).slice($N)
|
|
97
|
+
- pattern: |
|
|
98
|
+
const $ID = Math.floor(Math.random() * $N)
|
|
99
|
+
- pattern: |
|
|
100
|
+
id: Math.random()
|
|
101
|
+
- metavariable-regex:
|
|
102
|
+
metavariable: $ID
|
|
103
|
+
regex: .*(id|token|key|secret|session|nonce|code).*
|
|
104
|
+
message: "Math.random() is predictable - use crypto.randomUUID() for IDs or crypto.randomBytes() for tokens"
|
|
105
|
+
severity: ERROR
|
|
106
|
+
languages: [typescript, javascript]
|
|
107
|
+
metadata:
|
|
108
|
+
datahogo_id: 130
|
|
109
|
+
datahogo_category: "node-security"
|
|
110
|
+
owasp_ref: "A02:2021"
|
|
111
|
+
|
|
112
|
+
# ID 131: Service worker without scope
|
|
113
|
+
- id: datahogo-service-worker-no-scope
|
|
114
|
+
patterns:
|
|
115
|
+
- pattern-either:
|
|
116
|
+
- pattern: |
|
|
117
|
+
navigator.serviceWorker.register($FILE)
|
|
118
|
+
- pattern: |
|
|
119
|
+
navigator.serviceWorker.register($FILE, {})
|
|
120
|
+
- pattern-not: |
|
|
121
|
+
navigator.serviceWorker.register($FILE, { scope: $SCOPE })
|
|
122
|
+
message: "Service worker registered without explicit scope - define scope to limit intercepted requests"
|
|
123
|
+
severity: WARNING
|
|
124
|
+
languages: [typescript, javascript]
|
|
125
|
+
metadata:
|
|
126
|
+
datahogo_id: 131
|
|
127
|
+
datahogo_category: "node-security"
|
|
128
|
+
owasp_ref: "A05:2021"
|
|
129
|
+
|
|
130
|
+
# ID 132: Function timeout missing
|
|
131
|
+
- id: datahogo-lambda-no-timeout
|
|
132
|
+
patterns:
|
|
133
|
+
- pattern-either:
|
|
134
|
+
- pattern: |
|
|
135
|
+
export const handler = async (event, context) => {
|
|
136
|
+
...
|
|
137
|
+
}
|
|
138
|
+
- pattern: |
|
|
139
|
+
exports.handler = async (event) => {
|
|
140
|
+
...
|
|
141
|
+
}
|
|
142
|
+
- pattern-not: |
|
|
143
|
+
context.callbackWaitsForEmptyEventLoop = false
|
|
144
|
+
- pattern-not: |
|
|
145
|
+
timeout: $N
|
|
146
|
+
message: "Serverless function without timeout configuration can be abused for resource exhaustion - configure a timeout"
|
|
147
|
+
severity: WARNING
|
|
148
|
+
languages: [typescript, javascript]
|
|
149
|
+
metadata:
|
|
150
|
+
datahogo_id: 132
|
|
151
|
+
datahogo_category: "serverless-cloud"
|
|
152
|
+
owasp_ref: "A05:2021"
|
|
153
|
+
|
|
154
|
+
# ID 134: console.log(process.env) - env vars in logs
|
|
155
|
+
- id: datahogo-console-log-process-env
|
|
156
|
+
patterns:
|
|
157
|
+
- pattern-either:
|
|
158
|
+
- pattern: console.log(process.env)
|
|
159
|
+
- pattern: console.log(..., process.env, ...)
|
|
160
|
+
- pattern: console.info(process.env)
|
|
161
|
+
- pattern: console.error(process.env)
|
|
162
|
+
- pattern: console.log(JSON.stringify(process.env))
|
|
163
|
+
message: "Logging process.env exposes all environment variables including secrets to logs"
|
|
164
|
+
severity: ERROR
|
|
165
|
+
languages: [typescript, javascript]
|
|
166
|
+
metadata:
|
|
167
|
+
datahogo_id: 134
|
|
168
|
+
datahogo_category: "serverless-cloud"
|
|
169
|
+
owasp_ref: "A09:2021"
|
|
170
|
+
|
|
171
|
+
- id: datahogo-console-log-env-var
|
|
172
|
+
patterns:
|
|
173
|
+
- pattern-either:
|
|
174
|
+
- pattern: console.log(..., process.env.$SECRET_VAR, ...)
|
|
175
|
+
- pattern: console.log(`...${ process.env.$SECRET_VAR }...`)
|
|
176
|
+
- metavariable-regex:
|
|
177
|
+
metavariable: $SECRET_VAR
|
|
178
|
+
regex: .*(KEY|SECRET|PASSWORD|TOKEN|PRIVATE|CREDENTIAL|PASS|PWD).*
|
|
179
|
+
message: "Logging secret environment variable exposes sensitive credentials"
|
|
180
|
+
severity: ERROR
|
|
181
|
+
languages: [typescript, javascript]
|
|
182
|
+
metadata:
|
|
183
|
+
datahogo_id: 134
|
|
184
|
+
datahogo_category: "serverless-cloud"
|
|
185
|
+
owasp_ref: "A09:2021"
|
|
186
|
+
|
|
187
|
+
# ID 135: Sensitive files in /tmp
|
|
188
|
+
- id: datahogo-sensitive-tmp-write
|
|
189
|
+
patterns:
|
|
190
|
+
- pattern-either:
|
|
191
|
+
- pattern: |
|
|
192
|
+
fs.writeFile("/tmp/$FILENAME", $DATA, ...)
|
|
193
|
+
- pattern: |
|
|
194
|
+
fs.writeFileSync("/tmp/$FILENAME", $DATA)
|
|
195
|
+
- pattern: |
|
|
196
|
+
fs.writeFile(`/tmp/${$FILENAME}`, ...)
|
|
197
|
+
- metavariable-regex:
|
|
198
|
+
metavariable: $FILENAME
|
|
199
|
+
regex: .*(password|token|key|secret|credential|auth|private).*
|
|
200
|
+
message: "Writing sensitive data to /tmp - files in /tmp may persist across Lambda invocations and be read by other functions"
|
|
201
|
+
severity: WARNING
|
|
202
|
+
languages: [typescript, javascript]
|
|
203
|
+
metadata:
|
|
204
|
+
datahogo_id: 135
|
|
205
|
+
datahogo_category: "serverless-cloud"
|
|
206
|
+
owasp_ref: "A02:2021"
|
|
207
|
+
|
|
208
|
+
# ID 136: Global variables with user data
|
|
209
|
+
- id: datahogo-global-user-data
|
|
210
|
+
patterns:
|
|
211
|
+
- pattern-either:
|
|
212
|
+
- pattern: |
|
|
213
|
+
global.$VAR = $REQ.body
|
|
214
|
+
- pattern: |
|
|
215
|
+
global.$VAR = $REQ.user
|
|
216
|
+
- pattern: |
|
|
217
|
+
global.$VAR = $USER_DATA
|
|
218
|
+
- metavariable-regex:
|
|
219
|
+
metavariable: $VAR
|
|
220
|
+
regex: .*(user|session|request|auth|current).*
|
|
221
|
+
message: "Storing user data in global variables causes data leakage between requests in serverless environments"
|
|
222
|
+
severity: WARNING
|
|
223
|
+
languages: [typescript, javascript]
|
|
224
|
+
metadata:
|
|
225
|
+
datahogo_id: 136
|
|
226
|
+
datahogo_category: "serverless-cloud"
|
|
227
|
+
owasp_ref: "A01:2021"
|
|
228
|
+
|
|
229
|
+
# ID 172: Console.log sensitive data
|
|
230
|
+
- id: datahogo-console-log-sensitive-fields
|
|
231
|
+
patterns:
|
|
232
|
+
- pattern-either:
|
|
233
|
+
- pattern: console.log($OBJ.password)
|
|
234
|
+
- pattern: console.log($OBJ.passwordHash)
|
|
235
|
+
- pattern: console.log($OBJ.creditCard)
|
|
236
|
+
- pattern: console.log($OBJ.ssn)
|
|
237
|
+
- pattern: console.log($OBJ.secret)
|
|
238
|
+
- pattern: console.log(`...${ $OBJ.password }...`)
|
|
239
|
+
- pattern: console.log(`...${ $OBJ.secret }...`)
|
|
240
|
+
message: "Logging sensitive fields (password, secret, credit card) exposes them in logs"
|
|
241
|
+
severity: WARNING
|
|
242
|
+
languages: [typescript, javascript]
|
|
243
|
+
metadata:
|
|
244
|
+
datahogo_id: 172
|
|
245
|
+
datahogo_category: "best-practices"
|
|
246
|
+
owasp_ref: "A09:2021"
|
|
247
|
+
|
|
248
|
+
- id: datahogo-console-log-credentials-object
|
|
249
|
+
patterns:
|
|
250
|
+
- pattern-either:
|
|
251
|
+
- pattern: console.log({ user: $U, password: $P })
|
|
252
|
+
- pattern: console.log({ email: $E, password: $P })
|
|
253
|
+
- pattern: console.log({ ..., password: $P, ... })
|
|
254
|
+
message: "Logging object with password field will expose credentials in logs"
|
|
255
|
+
severity: WARNING
|
|
256
|
+
languages: [typescript, javascript]
|
|
257
|
+
metadata:
|
|
258
|
+
datahogo_id: 172
|
|
259
|
+
datahogo_category: "best-practices"
|
|
260
|
+
owasp_ref: "A09:2021"
|
|
261
|
+
|
|
262
|
+
# ID 173: Stack traces to user
|
|
263
|
+
- id: datahogo-error-stack-to-user
|
|
264
|
+
patterns:
|
|
265
|
+
- pattern-either:
|
|
266
|
+
- pattern: |
|
|
267
|
+
$RESPONSE.json({ ..., stack: $ERROR.stack, ... })
|
|
268
|
+
- pattern: |
|
|
269
|
+
$RESPONSE.json({ error: $ERROR.stack })
|
|
270
|
+
- pattern: |
|
|
271
|
+
$RESPONSE.send($ERROR.stack)
|
|
272
|
+
- pattern: |
|
|
273
|
+
res.status($CODE).json({ ..., stack: err.stack })
|
|
274
|
+
message: "Stack trace returned to API caller exposes internal file paths and implementation details"
|
|
275
|
+
severity: WARNING
|
|
276
|
+
languages: [typescript, javascript]
|
|
277
|
+
metadata:
|
|
278
|
+
datahogo_id: 173
|
|
279
|
+
datahogo_category: "best-practices"
|
|
280
|
+
owasp_ref: "A05:2021"
|
|
281
|
+
|
|
282
|
+
- id: datahogo-error-message-to-user-verbose
|
|
283
|
+
patterns:
|
|
284
|
+
- pattern-either:
|
|
285
|
+
- pattern: |
|
|
286
|
+
$RESPONSE.json({ error: $ERROR.message })
|
|
287
|
+
- pattern: |
|
|
288
|
+
$RESPONSE.status($CODE).json({ message: $ERROR.message })
|
|
289
|
+
- pattern-not: |
|
|
290
|
+
if (process.env.NODE_ENV === "development")
|
|
291
|
+
- pattern-not: |
|
|
292
|
+
if (isDevelopment)
|
|
293
|
+
message: "Raw error messages sent to clients may expose internal details - use generic user-facing messages and log full errors server-side"
|
|
294
|
+
severity: INFO
|
|
295
|
+
languages: [typescript, javascript]
|
|
296
|
+
metadata:
|
|
297
|
+
datahogo_id: 173
|
|
298
|
+
datahogo_category: "best-practices"
|
|
299
|
+
owasp_ref: "A05:2021"
|
|
300
|
+
|
|
301
|
+
# ID 176: PII in logs
|
|
302
|
+
- id: datahogo-pii-in-logs-email
|
|
303
|
+
patterns:
|
|
304
|
+
- pattern-either:
|
|
305
|
+
- pattern: console.log(`...${ $USER.email }...`)
|
|
306
|
+
- pattern: console.log($USER.email)
|
|
307
|
+
- pattern: logger.info({ email: $EMAIL })
|
|
308
|
+
- pattern: logger.info(`user email: ${ $EMAIL }`)
|
|
309
|
+
message: "Logging user email addresses is PII exposure - use user IDs in logs and store emails separately"
|
|
310
|
+
severity: WARNING
|
|
311
|
+
languages: [typescript, javascript]
|
|
312
|
+
metadata:
|
|
313
|
+
datahogo_id: 176
|
|
314
|
+
datahogo_category: "best-practices"
|
|
315
|
+
owasp_ref: "A09:2021"
|
|
316
|
+
|
|
317
|
+
- id: datahogo-pii-in-logs-phone
|
|
318
|
+
patterns:
|
|
319
|
+
- pattern-either:
|
|
320
|
+
- pattern: console.log(`...${ $USER.phone }...`)
|
|
321
|
+
- pattern: console.log(`...${ $USER.phoneNumber }...`)
|
|
322
|
+
- pattern: logger.info({ phone: $PHONE })
|
|
323
|
+
- pattern: logger.info({ phoneNumber: $PHONE })
|
|
324
|
+
message: "Logging phone numbers is PII exposure - reference users by ID in logs"
|
|
325
|
+
severity: WARNING
|
|
326
|
+
languages: [typescript, javascript]
|
|
327
|
+
metadata:
|
|
328
|
+
datahogo_id: 176
|
|
329
|
+
datahogo_category: "best-practices"
|
|
330
|
+
owasp_ref: "A09:2021"
|
|
331
|
+
|
|
332
|
+
# ID 188: Payment data stored locally
|
|
333
|
+
- id: datahogo-payment-data-localstorage
|
|
334
|
+
patterns:
|
|
335
|
+
- pattern-either:
|
|
336
|
+
- pattern: localStorage.setItem($KEY, $CARD_DATA)
|
|
337
|
+
- pattern: sessionStorage.setItem($KEY, $CARD_DATA)
|
|
338
|
+
- metavariable-regex:
|
|
339
|
+
metavariable: $KEY
|
|
340
|
+
regex: .*(card|credit|payment|cvv|pan|billing|stripe).*
|
|
341
|
+
message: "Payment card data must never be stored in localStorage/sessionStorage - violates PCI-DSS compliance"
|
|
342
|
+
severity: CRITICAL
|
|
343
|
+
languages: [typescript, javascript]
|
|
344
|
+
metadata:
|
|
345
|
+
datahogo_id: 188
|
|
346
|
+
datahogo_category: "best-practices"
|
|
347
|
+
owasp_ref: "A02:2021"
|
|
348
|
+
|
|
349
|
+
- id: datahogo-payment-data-in-db
|
|
350
|
+
patterns:
|
|
351
|
+
- pattern-either:
|
|
352
|
+
- pattern: |
|
|
353
|
+
$DB.create({ ..., cardNumber: $NUM, ... })
|
|
354
|
+
- pattern: |
|
|
355
|
+
$DB.create({ ..., cvv: $CVV, ... })
|
|
356
|
+
- pattern: |
|
|
357
|
+
$DB.insert({ ..., card_number: $NUM, ... })
|
|
358
|
+
message: "Storing raw card numbers or CVV in the database violates PCI-DSS - use a payment processor token instead"
|
|
359
|
+
severity: CRITICAL
|
|
360
|
+
languages: [typescript, javascript]
|
|
361
|
+
metadata:
|
|
362
|
+
datahogo_id: 188
|
|
363
|
+
datahogo_category: "best-practices"
|
|
364
|
+
owasp_ref: "A02:2021"
|
|
365
|
+
|
|
366
|
+
# ID 130 Extended: Insecure randomness for session IDs
|
|
367
|
+
- id: datahogo-insecure-session-id
|
|
368
|
+
patterns:
|
|
369
|
+
- pattern-either:
|
|
370
|
+
- pattern: |
|
|
371
|
+
const $SID = Math.random().toString($BASE).slice($N)
|
|
372
|
+
- pattern: |
|
|
373
|
+
sessionId: Math.random().toString($BASE)
|
|
374
|
+
message: "Session IDs must be generated with cryptographically secure randomness - use crypto.randomBytes(32).toString('hex')"
|
|
375
|
+
severity: ERROR
|
|
376
|
+
languages: [typescript, javascript]
|
|
377
|
+
metadata:
|
|
378
|
+
datahogo_id: 130
|
|
379
|
+
datahogo_category: "node-security"
|
|
380
|
+
owasp_ref: "A07:2021"
|
|
File without changes
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
# =============================================
|
|
3
|
+
# AI / LLM Security (IDs 200-208)
|
|
4
|
+
# =============================================
|
|
5
|
+
|
|
6
|
+
- id: datahogo-ai-prompt-injection
|
|
7
|
+
patterns:
|
|
8
|
+
- pattern-either:
|
|
9
|
+
- pattern: |
|
|
10
|
+
$MESSAGES = `...${$USER_INPUT}...`
|
|
11
|
+
- pattern: |
|
|
12
|
+
$MESSAGES.push({..., content: `...${$INPUT}...`})
|
|
13
|
+
- pattern: |
|
|
14
|
+
$CLIENT.messages.create({..., messages: [{..., content: `...${$INPUT}...`}]})
|
|
15
|
+
message: >
|
|
16
|
+
User input is interpolated directly into an LLM prompt. This enables prompt injection attacks
|
|
17
|
+
where an attacker can manipulate the AI's behavior. Sanitize or use structured prompts with
|
|
18
|
+
system/user role separation.
|
|
19
|
+
severity: WARNING
|
|
20
|
+
languages: [typescript, javascript]
|
|
21
|
+
metadata:
|
|
22
|
+
datahogo_id: 200
|
|
23
|
+
owasp: "A03:2021"
|
|
24
|
+
category: ai-llm
|
|
25
|
+
|
|
26
|
+
- id: datahogo-ai-api-key-frontend
|
|
27
|
+
patterns:
|
|
28
|
+
- pattern-either:
|
|
29
|
+
- pattern: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY
|
|
30
|
+
- pattern: process.env.NEXT_PUBLIC_OPENAI_API_KEY
|
|
31
|
+
- pattern: process.env.NEXT_PUBLIC_AI_API_KEY
|
|
32
|
+
- pattern: process.env.NEXT_PUBLIC_CLAUDE_API_KEY
|
|
33
|
+
message: >
|
|
34
|
+
AI API key is exposed via NEXT_PUBLIC_ environment variable, making it accessible in the browser.
|
|
35
|
+
AI API keys must only be used server-side.
|
|
36
|
+
severity: ERROR
|
|
37
|
+
languages: [typescript, javascript]
|
|
38
|
+
metadata:
|
|
39
|
+
datahogo_id: 203
|
|
40
|
+
owasp: "A07:2021"
|
|
41
|
+
category: ai-llm
|
|
42
|
+
|
|
43
|
+
- id: datahogo-ai-output-eval
|
|
44
|
+
patterns:
|
|
45
|
+
- pattern-either:
|
|
46
|
+
- pattern: eval($AI_RESPONSE)
|
|
47
|
+
- pattern: new Function($AI_RESPONSE)
|
|
48
|
+
- pattern: eval($COMPLETION.content)
|
|
49
|
+
- pattern: eval($RESPONSE.choices[0].message.content)
|
|
50
|
+
message: >
|
|
51
|
+
AI-generated output is passed to eval() or Function constructor. Never execute AI output as code —
|
|
52
|
+
it can be manipulated via prompt injection to run arbitrary code.
|
|
53
|
+
severity: ERROR
|
|
54
|
+
languages: [typescript, javascript]
|
|
55
|
+
metadata:
|
|
56
|
+
datahogo_id: 208
|
|
57
|
+
owasp: "A03:2021"
|
|
58
|
+
category: ai-llm
|
|
59
|
+
|
|
60
|
+
- id: datahogo-ai-no-output-sanitization
|
|
61
|
+
patterns:
|
|
62
|
+
- pattern: |
|
|
63
|
+
dangerouslySetInnerHTML={{__html: $AI_OUTPUT}}
|
|
64
|
+
- metavariable-regex:
|
|
65
|
+
metavariable: $AI_OUTPUT
|
|
66
|
+
regex: ".*(completion|response|aiOutput|generated|llm|chat|gpt|claude).*"
|
|
67
|
+
message: >
|
|
68
|
+
AI-generated content is rendered as HTML without sanitization. AI outputs can contain XSS payloads
|
|
69
|
+
via prompt injection. Always sanitize with DOMPurify before rendering.
|
|
70
|
+
severity: WARNING
|
|
71
|
+
languages: [typescript, javascript]
|
|
72
|
+
metadata:
|
|
73
|
+
datahogo_id: 204
|
|
74
|
+
category: ai-llm
|
|
75
|
+
|
|
76
|
+
# =============================================
|
|
77
|
+
# Database Connection Security (IDs 209-220)
|
|
78
|
+
# =============================================
|
|
79
|
+
|
|
80
|
+
- id: datahogo-db-connection-no-ssl
|
|
81
|
+
patterns:
|
|
82
|
+
- pattern-either:
|
|
83
|
+
- pattern: |
|
|
84
|
+
new Pool({..., ssl: false})
|
|
85
|
+
- pattern: |
|
|
86
|
+
new Client({..., ssl: false})
|
|
87
|
+
- pattern: |
|
|
88
|
+
createConnection({..., ssl: false})
|
|
89
|
+
message: >
|
|
90
|
+
Database connection has SSL explicitly disabled. Always use SSL/TLS for database connections
|
|
91
|
+
to prevent credential and data interception.
|
|
92
|
+
severity: WARNING
|
|
93
|
+
languages: [typescript, javascript]
|
|
94
|
+
metadata:
|
|
95
|
+
datahogo_id: 209
|
|
96
|
+
category: database-connection
|
|
97
|
+
|
|
98
|
+
- id: datahogo-db-ssl-reject-unauthorized-false
|
|
99
|
+
pattern: |
|
|
100
|
+
ssl: { rejectUnauthorized: false }
|
|
101
|
+
message: >
|
|
102
|
+
Database SSL certificate validation is disabled. This makes the connection vulnerable to
|
|
103
|
+
man-in-the-middle attacks. Use a proper CA certificate instead.
|
|
104
|
+
severity: WARNING
|
|
105
|
+
languages: [typescript, javascript]
|
|
106
|
+
metadata:
|
|
107
|
+
datahogo_id: 219
|
|
108
|
+
category: database-connection
|
|
109
|
+
|
|
110
|
+
- id: datahogo-db-default-credentials
|
|
111
|
+
patterns:
|
|
112
|
+
- pattern-regex: "(?:postgres|mysql|mongodb)://(?:postgres|root|admin):(?:postgres|root|admin|password|secret|test)@"
|
|
113
|
+
message: >
|
|
114
|
+
Database connection string uses default credentials. Use strong, unique passwords
|
|
115
|
+
managed via environment variables or a secrets manager.
|
|
116
|
+
severity: ERROR
|
|
117
|
+
languages: [typescript, javascript]
|
|
118
|
+
metadata:
|
|
119
|
+
datahogo_id: 211
|
|
120
|
+
category: database-connection
|
|
121
|
+
|
|
122
|
+
- id: datahogo-db-connection-string-logged
|
|
123
|
+
patterns:
|
|
124
|
+
- pattern-either:
|
|
125
|
+
- pattern: console.log(process.env.DATABASE_URL)
|
|
126
|
+
- pattern: console.log($X.connectionString)
|
|
127
|
+
- pattern: console.log(..., process.env.DATABASE_URL, ...)
|
|
128
|
+
- pattern: console.error(process.env.DATABASE_URL)
|
|
129
|
+
message: >
|
|
130
|
+
Database connection string (which may contain credentials) is logged. Remove logging of
|
|
131
|
+
connection strings to prevent credential exposure.
|
|
132
|
+
severity: WARNING
|
|
133
|
+
languages: [typescript, javascript]
|
|
134
|
+
metadata:
|
|
135
|
+
datahogo_id: 218
|
|
136
|
+
category: database-connection
|
|
137
|
+
|
|
138
|
+
- id: datahogo-db-hardcoded-host
|
|
139
|
+
patterns:
|
|
140
|
+
- pattern-regex: "host:\\s*['\"]\\w+\\.(?:rds\\.amazonaws\\.com|database\\.azure\\.com|cloudsql\\.google\\.com)['\"]"
|
|
141
|
+
message: >
|
|
142
|
+
Database host is hardcoded to a cloud provider endpoint. Use environment variables
|
|
143
|
+
to allow different configurations per environment.
|
|
144
|
+
severity: INFO
|
|
145
|
+
languages: [typescript, javascript]
|
|
146
|
+
metadata:
|
|
147
|
+
datahogo_id: 220
|
|
148
|
+
category: database-connection
|
|
149
|
+
|
|
150
|
+
# =============================================
|
|
151
|
+
# Cloud Provider Security (IDs 221-232)
|
|
152
|
+
# =============================================
|
|
153
|
+
|
|
154
|
+
- id: datahogo-cloud-metadata-ssrf
|
|
155
|
+
patterns:
|
|
156
|
+
- pattern-either:
|
|
157
|
+
- pattern: fetch("http://169.254.169.254/...")
|
|
158
|
+
- pattern: fetch(`http://169.254.169.254/...`)
|
|
159
|
+
- pattern: axios.get("http://169.254.169.254/...")
|
|
160
|
+
message: >
|
|
161
|
+
Request to cloud metadata endpoint detected. If user input can influence this URL,
|
|
162
|
+
it enables SSRF attacks to steal cloud credentials. Block metadata IPs in your HTTP client.
|
|
163
|
+
severity: ERROR
|
|
164
|
+
languages: [typescript, javascript]
|
|
165
|
+
metadata:
|
|
166
|
+
datahogo_id: 222
|
|
167
|
+
owasp: "A10:2021"
|
|
168
|
+
category: cloud
|
|
169
|
+
|
|
170
|
+
- id: datahogo-cloud-iam-star-star
|
|
171
|
+
patterns:
|
|
172
|
+
- pattern-regex: '"Action"\\s*:\\s*"\\*"[\\s\\S]{0,100}"Resource"\\s*:\\s*"\\*"'
|
|
173
|
+
message: >
|
|
174
|
+
IAM policy grants full access (Action: *, Resource: *). Follow least-privilege principle —
|
|
175
|
+
specify only the actions and resources needed.
|
|
176
|
+
severity: WARNING
|
|
177
|
+
languages: [json]
|
|
178
|
+
metadata:
|
|
179
|
+
datahogo_id: 224
|
|
180
|
+
category: cloud
|
|
181
|
+
|
|
182
|
+
- id: datahogo-cloud-s3-public
|
|
183
|
+
patterns:
|
|
184
|
+
- pattern-either:
|
|
185
|
+
- pattern: |
|
|
186
|
+
new s3.Bucket({..., publicReadAccess: true})
|
|
187
|
+
- pattern: |
|
|
188
|
+
ACL: "public-read"
|
|
189
|
+
- pattern: |
|
|
190
|
+
ACL: "public-read-write"
|
|
191
|
+
message: >
|
|
192
|
+
S3 bucket configured with public access. Unless intentionally serving public static assets,
|
|
193
|
+
buckets should be private with CloudFront or presigned URLs for access.
|
|
194
|
+
severity: ERROR
|
|
195
|
+
languages: [typescript, javascript]
|
|
196
|
+
metadata:
|
|
197
|
+
datahogo_id: 221
|
|
198
|
+
owasp: "A05:2021"
|
|
199
|
+
category: cloud
|