@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.
Files changed (153) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +17 -0
  3. package/dist/engines/config.d.ts +3 -0
  4. package/dist/engines/config.d.ts.map +1 -0
  5. package/dist/engines/config.js +433 -0
  6. package/dist/engines/config.js.map +1 -0
  7. package/dist/engines/dast.d.ts +3 -0
  8. package/dist/engines/dast.d.ts.map +1 -0
  9. package/dist/engines/dast.js +167 -0
  10. package/dist/engines/dast.js.map +1 -0
  11. package/dist/engines/db-rules.d.ts +3 -0
  12. package/dist/engines/db-rules.d.ts.map +1 -0
  13. package/dist/engines/db-rules.js +166 -0
  14. package/dist/engines/db-rules.js.map +1 -0
  15. package/dist/engines/dependencies.d.ts +3 -0
  16. package/dist/engines/dependencies.d.ts.map +1 -0
  17. package/dist/engines/dependencies.js +167 -0
  18. package/dist/engines/dependencies.js.map +1 -0
  19. package/dist/engines/github-actions.d.ts +3 -0
  20. package/dist/engines/github-actions.d.ts.map +1 -0
  21. package/dist/engines/github-actions.js +215 -0
  22. package/dist/engines/github-actions.js.map +1 -0
  23. package/dist/engines/gitleaks.d.ts +3 -0
  24. package/dist/engines/gitleaks.d.ts.map +1 -0
  25. package/dist/engines/gitleaks.js +107 -0
  26. package/dist/engines/gitleaks.js.map +1 -0
  27. package/dist/engines/npm-audit.d.ts +3 -0
  28. package/dist/engines/npm-audit.d.ts.map +1 -0
  29. package/dist/engines/npm-audit.js +113 -0
  30. package/dist/engines/npm-audit.js.map +1 -0
  31. package/dist/engines/patterns.d.ts +3 -0
  32. package/dist/engines/patterns.d.ts.map +1 -0
  33. package/dist/engines/patterns.js +1330 -0
  34. package/dist/engines/patterns.js.map +1 -0
  35. package/dist/engines/secrets.d.ts +4 -0
  36. package/dist/engines/secrets.d.ts.map +1 -0
  37. package/dist/engines/secrets.js +260 -0
  38. package/dist/engines/secrets.js.map +1 -0
  39. package/dist/engines/semgrep.d.ts +3 -0
  40. package/dist/engines/semgrep.d.ts.map +1 -0
  41. package/dist/engines/semgrep.js +173 -0
  42. package/dist/engines/semgrep.js.map +1 -0
  43. package/dist/engines/types.d.ts +30 -0
  44. package/dist/engines/types.d.ts.map +1 -0
  45. package/dist/engines/types.js +3 -0
  46. package/dist/engines/types.js.map +1 -0
  47. package/dist/engines/url-scanner.d.ts +3 -0
  48. package/dist/engines/url-scanner.d.ts.map +1 -0
  49. package/dist/engines/url-scanner.js +469 -0
  50. package/dist/engines/url-scanner.js.map +1 -0
  51. package/dist/index.d.ts +8 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/orchestrator.d.ts +32 -0
  56. package/dist/orchestrator.d.ts.map +1 -0
  57. package/dist/orchestrator.js +237 -0
  58. package/dist/orchestrator.js.map +1 -0
  59. package/dist/rules/.gitkeep +0 -0
  60. package/dist/rules/ai-llm-security.yaml +199 -0
  61. package/dist/rules/api-security.yaml +489 -0
  62. package/dist/rules/auth-patterns.yaml +406 -0
  63. package/dist/rules/crypto-patterns.yaml +227 -0
  64. package/dist/rules/database-cloud-security.yaml +169 -0
  65. package/dist/rules/general-security.yaml +588 -0
  66. package/dist/rules/injection-patterns.yaml +318 -0
  67. package/dist/rules/nextjs-security.yaml +532 -0
  68. package/dist/rules/node-security.yaml +380 -0
  69. package/dist/rules/rules/.gitkeep +0 -0
  70. package/dist/rules/rules/ai-llm-security.yaml +199 -0
  71. package/dist/rules/rules/api-security.yaml +489 -0
  72. package/dist/rules/rules/auth-patterns.yaml +406 -0
  73. package/dist/rules/rules/crypto-patterns.yaml +227 -0
  74. package/dist/rules/rules/database-cloud-security.yaml +169 -0
  75. package/dist/rules/rules/general-security.yaml +588 -0
  76. package/dist/rules/rules/injection-patterns.yaml +318 -0
  77. package/dist/rules/rules/nextjs-security.yaml +532 -0
  78. package/dist/rules/rules/node-security.yaml +380 -0
  79. package/dist/rules/rules/supabase-security.yaml +387 -0
  80. package/dist/rules/supabase-security.yaml +387 -0
  81. package/dist/scanning/agents/csharp-agent.d.ts +12 -0
  82. package/dist/scanning/agents/csharp-agent.d.ts.map +1 -0
  83. package/dist/scanning/agents/csharp-agent.js +592 -0
  84. package/dist/scanning/agents/csharp-agent.js.map +1 -0
  85. package/dist/scanning/agents/go-agent.d.ts +14 -0
  86. package/dist/scanning/agents/go-agent.d.ts.map +1 -0
  87. package/dist/scanning/agents/go-agent.js +641 -0
  88. package/dist/scanning/agents/go-agent.js.map +1 -0
  89. package/dist/scanning/agents/java-agent.d.ts +8 -0
  90. package/dist/scanning/agents/java-agent.d.ts.map +1 -0
  91. package/dist/scanning/agents/java-agent.js +807 -0
  92. package/dist/scanning/agents/java-agent.js.map +1 -0
  93. package/dist/scanning/agents/javascript-agent.d.ts +8 -0
  94. package/dist/scanning/agents/javascript-agent.d.ts.map +1 -0
  95. package/dist/scanning/agents/javascript-agent.js +77 -0
  96. package/dist/scanning/agents/javascript-agent.js.map +1 -0
  97. package/dist/scanning/agents/mobile-agent.d.ts +8 -0
  98. package/dist/scanning/agents/mobile-agent.d.ts.map +1 -0
  99. package/dist/scanning/agents/mobile-agent.js +916 -0
  100. package/dist/scanning/agents/mobile-agent.js.map +1 -0
  101. package/dist/scanning/agents/php-agent.d.ts +8 -0
  102. package/dist/scanning/agents/php-agent.d.ts.map +1 -0
  103. package/dist/scanning/agents/php-agent.js +679 -0
  104. package/dist/scanning/agents/php-agent.js.map +1 -0
  105. package/dist/scanning/agents/python-agent.d.ts +8 -0
  106. package/dist/scanning/agents/python-agent.d.ts.map +1 -0
  107. package/dist/scanning/agents/python-agent.js +701 -0
  108. package/dist/scanning/agents/python-agent.js.map +1 -0
  109. package/dist/scanning/agents/supabase-agent.d.ts +8 -0
  110. package/dist/scanning/agents/supabase-agent.d.ts.map +1 -0
  111. package/dist/scanning/agents/supabase-agent.js +484 -0
  112. package/dist/scanning/agents/supabase-agent.js.map +1 -0
  113. package/dist/scanning/orchestrator.d.ts +29 -0
  114. package/dist/scanning/orchestrator.d.ts.map +1 -0
  115. package/dist/scanning/orchestrator.js +186 -0
  116. package/dist/scanning/orchestrator.js.map +1 -0
  117. package/dist/scanning/tech-detector.d.ts +12 -0
  118. package/dist/scanning/tech-detector.d.ts.map +1 -0
  119. package/dist/scanning/tech-detector.js +252 -0
  120. package/dist/scanning/tech-detector.js.map +1 -0
  121. package/dist/scanning/types.d.ts +87 -0
  122. package/dist/scanning/types.d.ts.map +1 -0
  123. package/dist/scanning/types.js +5 -0
  124. package/dist/scanning/types.js.map +1 -0
  125. package/dist/utils/child-process.d.ts +2 -0
  126. package/dist/utils/child-process.d.ts.map +1 -0
  127. package/dist/utils/child-process.js +4 -0
  128. package/dist/utils/child-process.js.map +1 -0
  129. package/dist/utils/context-classifier.d.ts +11 -0
  130. package/dist/utils/context-classifier.d.ts.map +1 -0
  131. package/dist/utils/context-classifier.js +79 -0
  132. package/dist/utils/context-classifier.js.map +1 -0
  133. package/dist/utils/exec.d.ts +18 -0
  134. package/dist/utils/exec.d.ts.map +1 -0
  135. package/dist/utils/exec.js +51 -0
  136. package/dist/utils/exec.js.map +1 -0
  137. package/dist/utils/file-filter.d.ts +4 -0
  138. package/dist/utils/file-filter.d.ts.map +1 -0
  139. package/dist/utils/file-filter.js +68 -0
  140. package/dist/utils/file-filter.js.map +1 -0
  141. package/dist/utils/fs.d.ts +2 -0
  142. package/dist/utils/fs.d.ts.map +1 -0
  143. package/dist/utils/fs.js +5 -0
  144. package/dist/utils/fs.js.map +1 -0
  145. package/dist/utils/logger.d.ts +12 -0
  146. package/dist/utils/logger.d.ts.map +1 -0
  147. package/dist/utils/logger.js +27 -0
  148. package/dist/utils/logger.js.map +1 -0
  149. package/dist/utils/post-processor.d.ts +10 -0
  150. package/dist/utils/post-processor.d.ts.map +1 -0
  151. package/dist/utils/post-processor.js +183 -0
  152. package/dist/utils/post-processor.js.map +1 -0
  153. package/package.json +44 -0
@@ -0,0 +1,406 @@
1
+ rules:
2
+ # ID 77: Session Fixation - no session regeneration after login
3
+ - id: datahogo-session-fixation
4
+ patterns:
5
+ - pattern-either:
6
+ - pattern: |
7
+ async function login(...) {
8
+ ...
9
+ }
10
+ - pattern: |
11
+ async function signin(...) {
12
+ ...
13
+ }
14
+ - pattern-not: |
15
+ async function $FUNC(...) {
16
+ ...
17
+ $SESSION.regenerate(...)
18
+ ...
19
+ }
20
+ - pattern-not: |
21
+ async function $FUNC(...) {
22
+ ...
23
+ regenerateSession(...)
24
+ ...
25
+ }
26
+ message: "Login function should regenerate session ID to prevent session fixation attacks"
27
+ severity: ERROR
28
+ languages: [typescript, javascript]
29
+ metadata:
30
+ datahogo_id: 77
31
+ datahogo_category: "auth-sessions"
32
+ owasp_ref: "A07:2021"
33
+
34
+ # ID 79: Weak password policy - no length check
35
+ - id: datahogo-no-password-length-check
36
+ patterns:
37
+ - pattern-either:
38
+ - pattern: |
39
+ const password = $INPUT
40
+ ...
41
+ $DB.$METHOD({ password: $HASH })
42
+ - pattern: |
43
+ function $FUNC($PASSWORD, ...) {
44
+ ...
45
+ bcrypt.hash($PASSWORD, ...)
46
+ ...
47
+ }
48
+ - pattern-not: |
49
+ $PASSWORD.length >= $NUM
50
+ - pattern-not: |
51
+ $PASSWORD.length > $NUM
52
+ - pattern-not: |
53
+ if ($PASSWORD.length $OP $NUM)
54
+ message: "Password validation missing length requirement (minimum 8-12 characters recommended)"
55
+ severity: WARNING
56
+ languages: [typescript, javascript]
57
+ metadata:
58
+ datahogo_id: 79
59
+ datahogo_category: "auth-sessions"
60
+ owasp_ref: "A07:2021"
61
+
62
+ # ID 80: OAuth state missing
63
+ - id: datahogo-oauth-missing-state
64
+ patterns:
65
+ - pattern-either:
66
+ - pattern: |
67
+ const authUrl = `$OAUTH_ENDPOINT?client_id=$CLIENT_ID&redirect_uri=$REDIRECT`
68
+ - pattern: |
69
+ new URL($OAUTH_URL)
70
+ ...
71
+ $URL.searchParams.append('client_id', ...)
72
+ $URL.searchParams.append('redirect_uri', ...)
73
+ - pattern-not: |
74
+ $URL.searchParams.append('state', ...)
75
+ - pattern-not: |
76
+ state=$STATE
77
+ message: "OAuth redirect missing state parameter - vulnerable to CSRF attacks"
78
+ severity: ERROR
79
+ languages: [typescript, javascript]
80
+ metadata:
81
+ datahogo_id: 80
82
+ datahogo_category: "auth-sessions"
83
+ owasp_ref: "A07:2021"
84
+
85
+ # ID 81: Token not invalidated on logout
86
+ - id: datahogo-logout-no-invalidation
87
+ patterns:
88
+ - pattern-either:
89
+ - pattern: |
90
+ async function logout(...) {
91
+ ...
92
+ $RESPONSE.redirect(...)
93
+ }
94
+ - pattern: |
95
+ async function signout(...) {
96
+ ...
97
+ }
98
+ - pattern-not: |
99
+ async function $FUNC(...) {
100
+ ...
101
+ $DB.$METHOD({ token: ... })
102
+ ...
103
+ }
104
+ - pattern-not: |
105
+ async function $FUNC(...) {
106
+ ...
107
+ $SESSION.destroy(...)
108
+ ...
109
+ }
110
+ - pattern-not: |
111
+ async function $FUNC(...) {
112
+ ...
113
+ blacklist.add(...)
114
+ ...
115
+ }
116
+ message: "Logout function should invalidate tokens or destroy sessions"
117
+ severity: WARNING
118
+ languages: [typescript, javascript]
119
+ metadata:
120
+ datahogo_id: 81
121
+ datahogo_category: "auth-sessions"
122
+ owasp_ref: "A07:2021"
123
+
124
+ # ID 82: No session invalidation on password change
125
+ - id: datahogo-password-change-no-session-invalidation
126
+ patterns:
127
+ - pattern-either:
128
+ - pattern: |
129
+ async function changePassword(...) {
130
+ ...
131
+ $DB.update({ password: ... })
132
+ ...
133
+ }
134
+ - pattern: |
135
+ async function updatePassword(...) {
136
+ ...
137
+ }
138
+ - pattern-not: |
139
+ async function $FUNC(...) {
140
+ ...
141
+ $SESSION.destroy(...)
142
+ ...
143
+ }
144
+ - pattern-not: |
145
+ async function $FUNC(...) {
146
+ ...
147
+ invalidateAllSessions(...)
148
+ ...
149
+ }
150
+ message: "Password change should invalidate all active sessions for security"
151
+ severity: WARNING
152
+ languages: [typescript, javascript]
153
+ metadata:
154
+ datahogo_id: 82
155
+ datahogo_category: "auth-sessions"
156
+ owasp_ref: "A07:2021"
157
+
158
+ # ID 84: Insecure password reset - no TTL
159
+ - id: datahogo-password-reset-no-expiry
160
+ patterns:
161
+ - pattern-either:
162
+ - pattern: |
163
+ const resetToken = $RANDOM
164
+ ...
165
+ $DB.save({ resetToken: $TOKEN })
166
+ - pattern: |
167
+ function createPasswordResetToken(...) {
168
+ ...
169
+ return $TOKEN
170
+ }
171
+ - pattern-not: |
172
+ expiresAt: ...
173
+ - pattern-not: |
174
+ expires_at: ...
175
+ - pattern-not: |
176
+ expiry: ...
177
+ - pattern-not: |
178
+ ttl: ...
179
+ message: "Password reset token should have an expiration time (15-60 minutes recommended)"
180
+ severity: ERROR
181
+ languages: [typescript, javascript]
182
+ metadata:
183
+ datahogo_id: 84
184
+ datahogo_category: "auth-sessions"
185
+ owasp_ref: "A07:2021"
186
+
187
+ # ID 85: User enumeration - different error messages
188
+ - id: datahogo-user-enumeration
189
+ patterns:
190
+ - pattern-either:
191
+ - pattern: |
192
+ if (!$USER) {
193
+ throw new Error("User not found")
194
+ }
195
+ - pattern: |
196
+ if (!$USER) {
197
+ return { error: "User does not exist" }
198
+ }
199
+ - pattern: |
200
+ if (!$USER) {
201
+ $RESPONSE.status(404).json({ error: "User not found" })
202
+ }
203
+ message: "Login error messages should be generic to prevent user enumeration (use 'Invalid credentials')"
204
+ severity: INFO
205
+ languages: [typescript, javascript]
206
+ metadata:
207
+ datahogo_id: 85
208
+ datahogo_category: "auth-sessions"
209
+ owasp_ref: "A07:2021"
210
+
211
+ # ID 156: No password policy enforcement
212
+ - id: datahogo-no-password-policy
213
+ patterns:
214
+ - pattern-either:
215
+ - pattern: |
216
+ async function register(..., password: $TYPE, ...) {
217
+ ...
218
+ bcrypt.hash(password, ...)
219
+ ...
220
+ }
221
+ - pattern: |
222
+ async function signup(...) {
223
+ ...
224
+ const hashedPassword = await $HASH(password, ...)
225
+ ...
226
+ }
227
+ - pattern-not: |
228
+ if (password.length $OP $NUM && $REGEX.test(password))
229
+ - pattern-not: |
230
+ validatePassword(password)
231
+ - pattern-not: |
232
+ passwordSchema.parse(...)
233
+ message: "Password registration missing policy enforcement (length, complexity, common passwords)"
234
+ severity: WARNING
235
+ languages: [typescript, javascript]
236
+ metadata:
237
+ datahogo_id: 156
238
+ datahogo_category: "best-practices"
239
+ owasp_ref: "A07:2021"
240
+
241
+ # ID 159: No email verification
242
+ - id: datahogo-no-email-verification
243
+ patterns:
244
+ - pattern: |
245
+ async function register(...) {
246
+ ...
247
+ $DB.create({ email: $EMAIL, ... })
248
+ ...
249
+ }
250
+ - pattern-not: |
251
+ async function register(...) {
252
+ ...
253
+ sendVerificationEmail(...)
254
+ ...
255
+ }
256
+ - pattern-not: |
257
+ async function register(...) {
258
+ ...
259
+ emailVerified: false
260
+ ...
261
+ }
262
+ message: "User registration should require email verification to prevent fake accounts"
263
+ severity: WARNING
264
+ languages: [typescript, javascript]
265
+ metadata:
266
+ datahogo_id: 159
267
+ datahogo_category: "best-practices"
268
+ owasp_ref: "A07:2021"
269
+
270
+ # ID 164: No confirmation for critical actions
271
+ - id: datahogo-no-delete-confirmation
272
+ patterns:
273
+ - pattern-either:
274
+ - pattern: |
275
+ async function deleteAccount(...) {
276
+ ...
277
+ $DB.delete(...)
278
+ }
279
+ - pattern: |
280
+ async function DELETE(...) {
281
+ ...
282
+ $DB.users.delete(...)
283
+ ...
284
+ }
285
+ - pattern-not: |
286
+ if ($CONFIRM === $PASSWORD)
287
+ - pattern-not: |
288
+ if (confirmed)
289
+ - pattern-not: |
290
+ requirePasswordConfirmation(...)
291
+ message: "Critical actions like account deletion should require password confirmation"
292
+ severity: WARNING
293
+ languages: [typescript, javascript]
294
+ metadata:
295
+ datahogo_id: 164
296
+ datahogo_category: "best-practices"
297
+ owasp_ref: "A07:2021"
298
+
299
+ # ID 77 Extended: Session token reuse after privilege escalation
300
+ - id: datahogo-session-reuse-privilege-change
301
+ patterns:
302
+ - pattern: |
303
+ async function $FUNC(...) {
304
+ ...
305
+ $DB.update({ role: $NEW_ROLE })
306
+ ...
307
+ }
308
+ - pattern-not: |
309
+ async function $FUNC(...) {
310
+ ...
311
+ $SESSION.regenerate(...)
312
+ ...
313
+ }
314
+ message: "Session should be regenerated after privilege changes to prevent session adoption attacks"
315
+ severity: WARNING
316
+ languages: [typescript, javascript]
317
+ metadata:
318
+ datahogo_id: 77
319
+ datahogo_category: "auth-sessions"
320
+ owasp_ref: "A07:2021"
321
+
322
+ # ID 80 Extended: OAuth redirect_uri not validated
323
+ - id: datahogo-oauth-open-redirect
324
+ patterns:
325
+ - pattern-either:
326
+ - pattern: |
327
+ const redirect_uri = $REQ.query.redirect_uri
328
+ ...
329
+ $OAUTH.$METHOD({ redirect_uri })
330
+ - pattern: |
331
+ const callbackUrl = $REQ.body.callback
332
+ ...
333
+ redirect(callbackUrl)
334
+ - pattern-not: |
335
+ if (allowedUrls.includes($URL))
336
+ - pattern-not: |
337
+ if ($URL.startsWith($DOMAIN))
338
+ message: "OAuth redirect_uri should be validated against allowlist to prevent open redirects"
339
+ severity: ERROR
340
+ languages: [typescript, javascript]
341
+ metadata:
342
+ datahogo_id: 80
343
+ datahogo_category: "auth-sessions"
344
+ owasp_ref: "A07:2021"
345
+
346
+ # JWT without expiration
347
+ - id: datahogo-jwt-no-expiration
348
+ patterns:
349
+ - pattern-either:
350
+ - pattern: |
351
+ jwt.sign($PAYLOAD, $SECRET)
352
+ - pattern: |
353
+ jwt.sign($PAYLOAD, $SECRET, { algorithm: $ALG })
354
+ - pattern-not: |
355
+ jwt.sign($PAYLOAD, $SECRET, { ..., expiresIn: ... })
356
+ - pattern-not: |
357
+ jwt.sign($PAYLOAD, $SECRET, { ..., exp: ... })
358
+ message: "JWT tokens should have an expiration time (expiresIn or exp claim)"
359
+ severity: ERROR
360
+ languages: [typescript, javascript]
361
+ metadata:
362
+ datahogo_id: 56
363
+ datahogo_category: "vibecoding"
364
+ owasp_ref: "A07:2021"
365
+
366
+ # Tokens in localStorage
367
+ - id: datahogo-token-in-localstorage
368
+ patterns:
369
+ - pattern-either:
370
+ - pattern: localStorage.setItem($KEY, $TOKEN)
371
+ - pattern: sessionStorage.setItem($KEY, $TOKEN)
372
+ - metavariable-regex:
373
+ metavariable: $KEY
374
+ regex: .*(token|jwt|auth|session|access|refresh).*
375
+ message: "Authentication tokens in localStorage/sessionStorage are vulnerable to XSS. Use httpOnly cookies"
376
+ severity: ERROR
377
+ languages: [typescript, javascript]
378
+ metadata:
379
+ datahogo_id: 47
380
+ datahogo_category: "react-nextjs"
381
+ owasp_ref: "A07:2021"
382
+
383
+ # ID 156 Extended: Common passwords not checked
384
+ - id: datahogo-no-common-password-check
385
+ patterns:
386
+ - pattern: |
387
+ async function $FUNC(..., password: string, ...) {
388
+ ...
389
+ if (password.length >= $NUM) {
390
+ ...
391
+ }
392
+ ...
393
+ }
394
+ - pattern-not: |
395
+ commonPasswords.includes(password)
396
+ - pattern-not: |
397
+ isCommonPassword(password)
398
+ - pattern-not: |
399
+ hibp.check(password)
400
+ message: "Password validation should check against common/breached passwords list"
401
+ severity: INFO
402
+ languages: [typescript, javascript]
403
+ metadata:
404
+ datahogo_id: 156
405
+ datahogo_category: "best-practices"
406
+ owasp_ref: "A07:2021"
@@ -0,0 +1,227 @@
1
+ rules:
2
+ # ID 121: ECB mode in cipher
3
+ - id: datahogo-ecb-mode-cipher
4
+ patterns:
5
+ - pattern-either:
6
+ - pattern: crypto.createCipheriv("aes-$BITS-ecb", ...)
7
+ - pattern: crypto.createDecipheriv("aes-$BITS-ecb", ...)
8
+ - pattern: crypto.createCipheriv('aes-$BITS-ecb', ...)
9
+ - pattern: crypto.createDecipheriv('aes-$BITS-ecb', ...)
10
+ message: "ECB cipher mode does not use an IV and reveals patterns in plaintext - use CBC or GCM mode instead"
11
+ severity: WARNING
12
+ languages: [typescript, javascript]
13
+ metadata:
14
+ datahogo_id: 121
15
+ datahogo_category: "cryptography"
16
+ owasp_ref: "A02:2021"
17
+
18
+ # ID 122: Static IV / Nonce
19
+ - id: datahogo-static-iv-buffer
20
+ patterns:
21
+ - pattern-either:
22
+ - pattern: |
23
+ const iv = Buffer.alloc($SIZE, 0)
24
+ - pattern: |
25
+ const iv = Buffer.alloc($SIZE)
26
+ - pattern: |
27
+ const nonce = Buffer.alloc($SIZE, 0)
28
+ - pattern: |
29
+ const iv = Buffer.from("$STATIC_STRING")
30
+ message: "Static or zero-filled IV/nonce makes encryption deterministic - use crypto.randomBytes() for each encryption"
31
+ severity: ERROR
32
+ languages: [typescript, javascript]
33
+ metadata:
34
+ datahogo_id: 122
35
+ datahogo_category: "cryptography"
36
+ owasp_ref: "A02:2021"
37
+
38
+ - id: datahogo-static-iv-hardcoded
39
+ patterns:
40
+ - pattern-either:
41
+ - pattern: |
42
+ const $IV = "$STRING"
43
+ ...
44
+ crypto.createCipheriv($ALGO, $KEY, $IV)
45
+ - pattern: |
46
+ const $IV = '$STRING'
47
+ ...
48
+ crypto.createCipheriv($ALGO, $KEY, $IV)
49
+ message: "Hardcoded IV/nonce in cipher - generate a unique random IV for every encryption operation"
50
+ severity: ERROR
51
+ languages: [typescript, javascript]
52
+ metadata:
53
+ datahogo_id: 122
54
+ datahogo_category: "cryptography"
55
+ owasp_ref: "A02:2021"
56
+
57
+ # ID 123: Weak key size
58
+ - id: datahogo-weak-rsa-key-size
59
+ patterns:
60
+ - pattern-either:
61
+ - pattern: |
62
+ crypto.generateKeyPair("rsa", { modulusLength: $SIZE, ... }, ...)
63
+ - pattern: |
64
+ crypto.generateKeyPairSync("rsa", { modulusLength: $SIZE, ... })
65
+ - metavariable-regex:
66
+ metavariable: $SIZE
67
+ regex: ^(512|1024)$
68
+ message: "RSA key size below 2048 bits is cryptographically weak - use at least 2048 bits (4096 recommended)"
69
+ severity: WARNING
70
+ languages: [typescript, javascript]
71
+ metadata:
72
+ datahogo_id: 123
73
+ datahogo_category: "cryptography"
74
+ owasp_ref: "A02:2021"
75
+
76
+ - id: datahogo-weak-aes-key-size
77
+ patterns:
78
+ - pattern-either:
79
+ - pattern: crypto.createCipheriv("aes-64-$MODE", ...)
80
+ - pattern: crypto.createCipheriv('aes-64-$MODE', ...)
81
+ message: "AES key size below 128 bits is insufficient - use AES-128, AES-192, or AES-256"
82
+ severity: WARNING
83
+ languages: [typescript, javascript]
84
+ metadata:
85
+ datahogo_id: 123
86
+ datahogo_category: "cryptography"
87
+ owasp_ref: "A02:2021"
88
+
89
+ # ID 124: Certificate validation disabled
90
+ - id: datahogo-tls-reject-unauthorized-env
91
+ patterns:
92
+ - pattern-either:
93
+ - pattern: process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
94
+ - pattern: process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
95
+ - pattern: process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"
96
+ message: "Disabling TLS certificate validation exposes all HTTPS connections to man-in-the-middle attacks"
97
+ severity: CRITICAL
98
+ languages: [typescript, javascript]
99
+ metadata:
100
+ datahogo_id: 124
101
+ datahogo_category: "cryptography"
102
+ owasp_ref: "A02:2021"
103
+
104
+ - id: datahogo-tls-reject-unauthorized-agent
105
+ patterns:
106
+ - pattern-either:
107
+ - pattern: |
108
+ new https.Agent({ rejectUnauthorized: false })
109
+ - pattern: |
110
+ https.request({ ..., rejectUnauthorized: false, ... })
111
+ - pattern: |
112
+ axios.create({ ..., httpsAgent: new https.Agent({ rejectUnauthorized: false }) })
113
+ message: "TLS certificate validation disabled in HTTPS agent - remove rejectUnauthorized: false before deploying to production"
114
+ severity: CRITICAL
115
+ languages: [typescript, javascript]
116
+ metadata:
117
+ datahogo_id: 124
118
+ datahogo_category: "cryptography"
119
+ owasp_ref: "A02:2021"
120
+
121
+ # ID 125: Weak PRNG for security tokens
122
+ - id: datahogo-math-random-token
123
+ patterns:
124
+ - pattern-either:
125
+ - pattern: |
126
+ const $TOKEN = Math.random()
127
+ - pattern: |
128
+ const $ID = Math.random().toString(...)
129
+ - pattern: |
130
+ token = Math.random().toString($BASE).slice($N)
131
+ - pattern: |
132
+ id = Math.random().toString($BASE).substr($N)
133
+ message: "Math.random() is not cryptographically secure - use crypto.randomBytes() or crypto.randomUUID() for tokens and IDs"
134
+ severity: ERROR
135
+ languages: [typescript, javascript]
136
+ metadata:
137
+ datahogo_id: 125
138
+ datahogo_category: "cryptography"
139
+ owasp_ref: "A02:2021"
140
+
141
+ - id: datahogo-date-now-token
142
+ patterns:
143
+ - pattern-either:
144
+ - pattern: |
145
+ const $TOKEN = Date.now().toString()
146
+ - pattern: |
147
+ const $TOKEN = String(Date.now())
148
+ - pattern: |
149
+ token: Date.now()
150
+ - metavariable-regex:
151
+ metavariable: $TOKEN
152
+ regex: .*(token|secret|key|reset|nonce|csrf|session).*
153
+ message: "Date.now() is predictable and should not be used for security tokens - use crypto.randomBytes()"
154
+ severity: ERROR
155
+ languages: [typescript, javascript]
156
+ metadata:
157
+ datahogo_id: 125
158
+ datahogo_category: "cryptography"
159
+ owasp_ref: "A02:2021"
160
+
161
+ # ID 126: JWT algorithm none
162
+ - id: datahogo-jwt-algorithm-none
163
+ patterns:
164
+ - pattern-either:
165
+ - pattern: jwt.verify($TOKEN, $SECRET, { algorithms: [..., "none", ...] })
166
+ - pattern: jwt.verify($TOKEN, $SECRET, { algorithms: ["none"] })
167
+ - pattern: jwt.sign($PAYLOAD, $SECRET, { algorithm: "none" })
168
+ - pattern: jwt.sign($PAYLOAD, "", ...)
169
+ message: "JWT 'none' algorithm allows forged tokens with no signature verification - always use a strong algorithm (RS256, ES256)"
170
+ severity: CRITICAL
171
+ languages: [typescript, javascript]
172
+ metadata:
173
+ datahogo_id: 126
174
+ datahogo_category: "cryptography"
175
+ owasp_ref: "A02:2021"
176
+
177
+ - id: datahogo-jwt-empty-secret
178
+ patterns:
179
+ - pattern-either:
180
+ - pattern: jwt.verify($TOKEN, "")
181
+ - pattern: jwt.verify($TOKEN, '')
182
+ - pattern: jwt.verify($TOKEN, null)
183
+ - pattern: jwt.verify($TOKEN, undefined)
184
+ message: "JWT verification with empty or null secret disables signature validation - always use a strong secret"
185
+ severity: CRITICAL
186
+ languages: [typescript, javascript]
187
+ metadata:
188
+ datahogo_id: 126
189
+ datahogo_category: "cryptography"
190
+ owasp_ref: "A02:2021"
191
+
192
+ # ID 127: Hardcoded encryption key
193
+ - id: datahogo-hardcoded-encryption-key-string
194
+ patterns:
195
+ - pattern-either:
196
+ - pattern: |
197
+ const $KEY = "$LITERAL_KEY"
198
+ ...
199
+ crypto.createCipheriv($ALGO, $KEY, ...)
200
+ - pattern: |
201
+ const $KEY = '$LITERAL_KEY'
202
+ ...
203
+ crypto.createCipheriv($ALGO, $KEY, ...)
204
+ - pattern: |
205
+ crypto.createCipheriv($ALGO, "$LITERAL_KEY", ...)
206
+ - pattern: |
207
+ crypto.createCipheriv($ALGO, '$LITERAL_KEY', ...)
208
+ message: "Hardcoded encryption key in source code - load from environment variables or secrets manager"
209
+ severity: ERROR
210
+ languages: [typescript, javascript]
211
+ metadata:
212
+ datahogo_id: 127
213
+ datahogo_category: "cryptography"
214
+ owasp_ref: "A02:2021"
215
+
216
+ - id: datahogo-hardcoded-hmac-key
217
+ patterns:
218
+ - pattern-either:
219
+ - pattern: crypto.createHmac($ALGO, "$LITERAL_KEY")
220
+ - pattern: crypto.createHmac($ALGO, '$LITERAL_KEY')
221
+ message: "Hardcoded HMAC key in source code - load secret from environment variables"
222
+ severity: ERROR
223
+ languages: [typescript, javascript]
224
+ metadata:
225
+ datahogo_id: 127
226
+ datahogo_category: "cryptography"
227
+ owasp_ref: "A02:2021"