narvy-cli 1.0.0__py3-none-any.whl

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 (93) hide show
  1. narvy/__init__.py +3 -0
  2. narvy/android/__init__.py +0 -0
  3. narvy/android/source_analyzer.py +268 -0
  4. narvy/android/split_bundle.py +475 -0
  5. narvy/android_rule_context.py +196 -0
  6. narvy/apk_memory_preflight.py +248 -0
  7. narvy/auth.py +40 -0
  8. narvy/ci_templates/bitbucket.yml +25 -0
  9. narvy/ci_templates/github.yml +60 -0
  10. narvy/ci_templates/gitlab.yml +32 -0
  11. narvy/cloud/__init__.py +0 -0
  12. narvy/cloud/aws_scan.py +1188 -0
  13. narvy/comment_filter.py +134 -0
  14. narvy/crypto_taint_lite.py +82 -0
  15. narvy/decompiler.py +337 -0
  16. narvy/doctor.py +244 -0
  17. narvy/host/__init__.py +0 -0
  18. narvy/host/audit.py +157 -0
  19. narvy/host/host_knowledge.py +982 -0
  20. narvy/host/lynis_bootstrap.py +400 -0
  21. narvy/host/lynis_parser.py +358 -0
  22. narvy/host/narvy_checks.py +789 -0
  23. narvy/host/report.py +69 -0
  24. narvy/host/ssh_exec.py +219 -0
  25. narvy/ios/__init__.py +0 -0
  26. narvy/ios/binary_analyzer.py +1201 -0
  27. narvy/ios/plist_checks.py +249 -0
  28. narvy/ios/source_analyzer.py +301 -0
  29. narvy/ios/third_party_filter.py +242 -0
  30. narvy/ios/trust_all_context.py +66 -0
  31. narvy/main.py +1983 -0
  32. narvy/native_hardening.py +503 -0
  33. narvy/reporter.py +151 -0
  34. narvy/rule_engine.py +57 -0
  35. narvy/rules/android/config.yml +77 -0
  36. narvy/rules/android/crypto.yml +34 -0
  37. narvy/rules/android/secrets.yml +161 -0
  38. narvy/rules/android/storage.yml +24 -0
  39. narvy/rules/android/webview.yml +23 -0
  40. narvy/rules/android.yml +219 -0
  41. narvy/rules/ios/objc/crypto.yml +56 -0
  42. narvy/rules/ios/objc/network.yml +67 -0
  43. narvy/rules/ios/objc/secrets.yml +79 -0
  44. narvy/rules/ios/objc/storage.yml +45 -0
  45. narvy/rules/ios/objc/webview.yml +45 -0
  46. narvy/rules/ios_swift.yml +327 -0
  47. narvy/rules/web/go.yml +2837 -0
  48. narvy/rules/web/java.yml +1576 -0
  49. narvy/rules/web/javascript.yml +3683 -0
  50. narvy/rules/web/kotlin.yml +413 -0
  51. narvy/rules/web/local/csharp_narvy/config.yml +61 -0
  52. narvy/rules/web/local/csharp_narvy/crypto.yml +64 -0
  53. narvy/rules/web/local/csharp_narvy/deserialization.yml +59 -0
  54. narvy/rules/web/local/csharp_narvy/injection.yml +122 -0
  55. narvy/rules/web/local/csharp_narvy/xxe.yml +48 -0
  56. narvy/rules/web/local/java_narvy/auth_jwt.yml +134 -0
  57. narvy/rules/web/local/java_narvy/deserialization.yml +108 -0
  58. narvy/rules/web/local/java_narvy/mybatis.yml +39 -0
  59. narvy/rules/web/local/java_narvy/snakeyaml.yml +34 -0
  60. narvy/rules/web/local/java_narvy/spring_authz.yml +32 -0
  61. narvy/rules/web/local/java_narvy/spring_config.yml +67 -0
  62. narvy/rules/web/local/java_narvy/spring_hardening.yml +291 -0
  63. narvy/rules/web/local/java_narvy/sqli.yml +235 -0
  64. narvy/rules/web/local/java_narvy/xxe.yml +212 -0
  65. narvy/rules/web/php.yml +1644 -0
  66. narvy/rules/web/python.yml +3967 -0
  67. narvy/rules/web/ruby.yml +703 -0
  68. narvy/rules/web/rust.yml +258 -0
  69. narvy/rules/web/secrets.yml +1420 -0
  70. narvy/rules/web/secrets_supplement.yml +383 -0
  71. narvy/sca/__init__.py +1 -0
  72. narvy/sca/android_deps.py +349 -0
  73. narvy/sca/ios_deps.py +578 -0
  74. narvy/sca/osv_client.py +617 -0
  75. narvy/sca/web_deps.py +955 -0
  76. narvy/scope_config.py +195 -0
  77. narvy/semgrep_engine.py +219 -0
  78. narvy/stack_protector_evidence.py +96 -0
  79. narvy/third_party_filter.py +211 -0
  80. narvy/uploader.py +92 -0
  81. narvy/weak_prng_context.py +270 -0
  82. narvy/web/__init__.py +0 -0
  83. narvy/web/nuclei_binary.py +105 -0
  84. narvy/web/scan_blocklist.py +96 -0
  85. narvy/web/scanner.py +842 -0
  86. narvy/web/source_analyzer.py +714 -0
  87. narvy/web/ssrf_guard.py +374 -0
  88. narvy_cli-1.0.0.dist-info/METADATA +165 -0
  89. narvy_cli-1.0.0.dist-info/RECORD +93 -0
  90. narvy_cli-1.0.0.dist-info/WHEEL +5 -0
  91. narvy_cli-1.0.0.dist-info/entry_points.txt +2 -0
  92. narvy_cli-1.0.0.dist-info/licenses/LICENSE +202 -0
  93. narvy_cli-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1644 @@
1
+ # PHP security rules, authored by Narvy.
2
+ # Injection, file inclusion, deserialization, weak crypto, session handling.
3
+
4
+ rules:
5
+ - id: narvy.php.lang.assert-tainted-string.assert-tainted-string
6
+ message: '`assert()` called with a string built from user input. When `assert()` receives a string argument (not a boolean
7
+ expression), PHP < 8 evaluates it as PHP code via `eval()` semantics - a tainted value here is remote code execution (CWE-95).
8
+ PHP 8 removed string evaluation, but this is still exploitable on any PHP 7.x deployment. Never build the assertion string
9
+ from input; pass a real boolean expression instead.'
10
+ severity: ERROR
11
+ languages:
12
+ - php
13
+ metadata:
14
+ category: security
15
+ cwe:
16
+ - 'CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code (''Eval Injection'')'
17
+ owasp:
18
+ - A03:2021 - Injection
19
+ subcategory:
20
+ - vuln
21
+ likelihood: MEDIUM
22
+ impact: HIGH
23
+ confidence: MEDIUM
24
+ technology:
25
+ - php
26
+ mode: taint
27
+ pattern-sources:
28
+ - patterns:
29
+ - pattern-either:
30
+ - pattern: $_GET[...]
31
+ - pattern: $_POST[...]
32
+ - pattern: $_REQUEST[...]
33
+ - pattern: $_COOKIE[...]
34
+ pattern-sinks:
35
+ - patterns:
36
+ - pattern-either:
37
+ - pattern: assert("..." . $SINK . "...")
38
+ - pattern: assert("...$SINK...")
39
+ - pattern: assert($SINK)
40
+ - id: narvy.php.lang.extract-tainted-array.extract-tainted-array
41
+ message: '`extract()` called directly on a superglobal (`$_GET` / `$_POST` / `$_REQUEST` / `$_COOKIE`). This lets an attacker
42
+ define or overwrite any variable in the current symbol table by choosing the array key - variable injection that can bypass
43
+ authentication checks or poison variables used later in the request (CWE-621 / CWE-473 class). Never `extract()` a superglobal;
44
+ whitelist the keys you actually need with `EXTR_SKIP` and a fixed key list, or avoid `extract()` entirely.'
45
+ severity: ERROR
46
+ languages:
47
+ - php
48
+ metadata:
49
+ category: security
50
+ cwe:
51
+ - 'CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code (''Eval Injection'')'
52
+ owasp:
53
+ - A03:2021 - Injection
54
+ subcategory:
55
+ - vuln
56
+ likelihood: HIGH
57
+ impact: HIGH
58
+ confidence: HIGH
59
+ technology:
60
+ - php
61
+ patterns:
62
+ - pattern-either:
63
+ - pattern: extract($_GET)
64
+ - pattern: extract($_POST)
65
+ - pattern: extract($_REQUEST)
66
+ - pattern: extract($_COOKIE)
67
+ - pattern: extract($_GET, ...)
68
+ - pattern: extract($_POST, ...)
69
+ - pattern: extract($_REQUEST, ...)
70
+ - pattern: extract(array_merge($_GET, ...))
71
+ - pattern: extract(array_merge($_POST, ...))
72
+ - id: narvy.php.code-injection.create-function-tainted.create-function-tainted
73
+ mode: taint
74
+ message: '`create_function()` compiles its arguments as PHP code via an internal `eval()` - it is deprecated (removed in
75
+ PHP 8.0) precisely because of this. If either argument is user-controlled, this is remote code execution (CWE-94). Use
76
+ an anonymous function (`function(...) { ... }` or an arrow function) instead - never build the function source from a
77
+ string.'
78
+ severity: ERROR
79
+ languages:
80
+ - php
81
+ metadata:
82
+ cwe:
83
+ - 'CWE-94: Improper Control of Generation of Code (''Code Injection'')'
84
+ owasp:
85
+ - A03:2021 - Injection
86
+ category: security
87
+ subcategory:
88
+ - vuln
89
+ technology:
90
+ - php
91
+ likelihood: MEDIUM
92
+ impact: HIGH
93
+ confidence: HIGH
94
+ vulnerability_class:
95
+ - Code Injection
96
+ pattern-sources:
97
+ - patterns:
98
+ - pattern-either:
99
+ - pattern: $_GET[...]
100
+ - pattern: $_POST[...]
101
+ - pattern: $_REQUEST[...]
102
+ - pattern: $_COOKIE[...]
103
+ pattern-sinks:
104
+ - patterns:
105
+ - pattern: create_function(...)
106
+ - id: narvy.php.code-injection.preg-replace-e-modifier.preg-replace-e-modifier
107
+ message: '`preg_replace()` is called with the `/e` modifier on its pattern. The `/e` modifier evaluates the replacement
108
+ string as PHP code after backreference substitution - if any matched/substituted portion is attacker-influenced, this
109
+ is remote code execution (CWE-94). The modifier was removed in PHP 7.0, but legacy code running on old runtimes (or migrated
110
+ verbatim) still carries it. Use `preg_replace_callback()` with a real closure instead.'
111
+ severity: ERROR
112
+ languages:
113
+ - php
114
+ metadata:
115
+ cwe:
116
+ - 'CWE-94: Improper Control of Generation of Code (''Code Injection'')'
117
+ owasp:
118
+ - A03:2021 - Injection
119
+ category: security
120
+ subcategory:
121
+ - vuln
122
+ technology:
123
+ - php
124
+ likelihood: LOW
125
+ impact: HIGH
126
+ confidence: HIGH
127
+ vulnerability_class:
128
+ - Code Injection
129
+ patterns:
130
+ - pattern: preg_replace($PATTERN, $REPL, $SUBJECT)
131
+ - metavariable-regex:
132
+ metavariable: $PATTERN
133
+ regex: ^['"].*/[a-zA-Z]*e[a-zA-Z]*['"]$
134
+ - id: narvy.php.cors.wildcard-allow-origin.wildcard-allow-origin
135
+ message: '`Access-Control-Allow-Origin: *` accepts cross-origin requests from ANY website. If this response also carries
136
+ session cookies or an Authorization header, any site can read the authenticated response on behalf of a logged-in user
137
+ (CWE-942). Reflect a validated origin from an allow-list instead of using a wildcard.'
138
+ severity: WARNING
139
+ languages:
140
+ - php
141
+ metadata:
142
+ cwe:
143
+ - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains'
144
+ owasp:
145
+ - A05:2021 - Security Misconfiguration
146
+ category: security
147
+ subcategory:
148
+ - vuln
149
+ technology:
150
+ - php
151
+ likelihood: MEDIUM
152
+ impact: MEDIUM
153
+ confidence: HIGH
154
+ vulnerability_class:
155
+ - Security Misconfiguration
156
+ references:
157
+ - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
158
+ patterns:
159
+ - pattern-either:
160
+ - pattern: 'header("Access-Control-Allow-Origin: *")'
161
+ - pattern: 'header(''Access-Control-Allow-Origin: *'')'
162
+ - id: narvy.php.cors.reflected-origin-header.reflected-origin-header
163
+ message: 'The `Origin` request header is echoed straight back as the `Access-Control-Allow-Origin` response value. This
164
+ is functionally equivalent to a wildcard (every origin is allowed) but additionally permits `Access-Control-Allow-Credentials:
165
+ true` to work with it, letting ANY site make authenticated cross-origin requests on a logged-in user''s behalf (CWE-942).
166
+ Validate `Origin` against an explicit allow-list before reflecting it.'
167
+ severity: WARNING
168
+ languages:
169
+ - php
170
+ metadata:
171
+ cwe:
172
+ - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains'
173
+ owasp:
174
+ - A05:2021 - Security Misconfiguration
175
+ category: security
176
+ subcategory:
177
+ - vuln
178
+ technology:
179
+ - php
180
+ likelihood: MEDIUM
181
+ impact: HIGH
182
+ confidence: MEDIUM
183
+ vulnerability_class:
184
+ - Security Misconfiguration
185
+ references:
186
+ - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
187
+ patterns:
188
+ - pattern-either:
189
+ - pattern: 'header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"])'
190
+ - pattern: 'header(''Access-Control-Allow-Origin: '' . $_SERVER[''HTTP_ORIGIN''])'
191
+ - id: narvy.php.curl.tls-verify-peer-off.tls-verify-peer-off
192
+ message: '`CURLOPT_SSL_VERIFYPEER` set to `false` / `0`. This disables TLS certificate validation entirely - the request
193
+ will accept any certificate (including a self-signed one presented by an attacker-in-the-middle), defeating TLS (CWE-295).
194
+ Remove the option (it defaults to verifying) or set it to `true`.'
195
+ severity: ERROR
196
+ languages:
197
+ - php
198
+ metadata:
199
+ category: security
200
+ cwe:
201
+ - 'CWE-295: Improper Certificate Validation'
202
+ owasp:
203
+ - A02:2021 - Cryptographic Failures
204
+ subcategory:
205
+ - vuln
206
+ likelihood: MEDIUM
207
+ impact: HIGH
208
+ confidence: HIGH
209
+ technology:
210
+ - php
211
+ patterns:
212
+ - pattern-either:
213
+ - pattern: curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, false)
214
+ - pattern: curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, 0)
215
+ - pattern: curl_setopt_array($CH, [..., CURLOPT_SSL_VERIFYPEER => false, ...])
216
+ - pattern: curl_setopt_array($CH, [..., CURLOPT_SSL_VERIFYPEER => 0, ...])
217
+ - id: narvy.php.curl.tls-verify-host-off.tls-verify-host-off
218
+ message: '`CURLOPT_SSL_VERIFYHOST` set to `false` / `0`. This disables the hostname check against the certificate''s CN/SAN
219
+ - a valid certificate for *any* domain will be accepted, enabling man-in-the-middle attacks (CWE-295). Set it to `2` (the
220
+ secure default) instead.'
221
+ severity: ERROR
222
+ languages:
223
+ - php
224
+ metadata:
225
+ category: security
226
+ cwe:
227
+ - 'CWE-295: Improper Certificate Validation'
228
+ owasp:
229
+ - A02:2021 - Cryptographic Failures
230
+ subcategory:
231
+ - vuln
232
+ likelihood: MEDIUM
233
+ impact: HIGH
234
+ confidence: HIGH
235
+ technology:
236
+ - php
237
+ patterns:
238
+ - pattern-either:
239
+ - pattern: curl_setopt($CH, CURLOPT_SSL_VERIFYHOST, false)
240
+ - pattern: curl_setopt($CH, CURLOPT_SSL_VERIFYHOST, 0)
241
+ - pattern: curl_setopt_array($CH, [..., CURLOPT_SSL_VERIFYHOST => false, ...])
242
+ - pattern: curl_setopt_array($CH, [..., CURLOPT_SSL_VERIFYHOST => 0, ...])
243
+ - id: narvy.php.code-injection.eval-with-user-input.eval-with-user-input
244
+ message: 'Detected PHP `eval()` called with user-controlled input. eval() executes arbitrary PHP code; if the argument is
245
+ user-controlled this is a remote code execution vulnerability (CWE-94). Remove eval() or use a safe alternative (e.g.,
246
+ a whitelist dispatch table).
247
+
248
+ '
249
+ severity: ERROR
250
+ languages:
251
+ - php
252
+ metadata:
253
+ category: security
254
+ cwe:
255
+ - 'CWE-94: Improper Control of Generation of Code (''Code Injection'')'
256
+ owasp:
257
+ - A03:2021 - Injection
258
+ subcategory:
259
+ - vuln
260
+ likelihood: HIGH
261
+ impact: HIGH
262
+ confidence: HIGH
263
+ technology:
264
+ - php
265
+ mode: taint
266
+ pattern-sources:
267
+ - patterns:
268
+ - pattern-either:
269
+ - pattern: $_GET[...]
270
+ - pattern: $_POST[...]
271
+ - pattern: $_REQUEST[...]
272
+ - pattern: $_COOKIE[...]
273
+ - pattern: $_SERVER['HTTP_$VAR']
274
+ - pattern: file_get_contents("php://input")
275
+ pattern-sinks:
276
+ - patterns:
277
+ - pattern: eval($CODE)
278
+ pattern-sanitizers:
279
+ - patterns:
280
+ - pattern: htmlspecialchars($X, ...)
281
+ - pattern: htmlentities($X, ...)
282
+ - id: narvy.php.file-inclusion.dynamic-include-with-user-input.dynamic-include-with-user-input
283
+ message: 'Detected PHP `include` / `require` with a user-controlled filename. This allows local file inclusion (LFI) and
284
+ potentially remote file inclusion (RFI), enabling arbitrary code execution (CWE-98). Validate the include path against
285
+ a strict allow-list.
286
+
287
+ '
288
+ severity: ERROR
289
+ languages:
290
+ - php
291
+ metadata:
292
+ category: security
293
+ cwe:
294
+ - 'CWE-98: Improper Control of Filename for Include/Require Statement in PHP Program (''PHP Remote File Inclusion'')'
295
+ - 'CWE-22: Improper Limitation of a Pathname to a Restricted Directory (''Path Traversal'')'
296
+ owasp:
297
+ - A03:2021 - Injection
298
+ subcategory:
299
+ - vuln
300
+ likelihood: HIGH
301
+ impact: HIGH
302
+ confidence: HIGH
303
+ technology:
304
+ - php
305
+ mode: taint
306
+ pattern-sources:
307
+ - patterns:
308
+ - pattern-either:
309
+ - pattern: $_GET[...]
310
+ - pattern: $_POST[...]
311
+ - pattern: $_REQUEST[...]
312
+ - pattern: $_COOKIE[...]
313
+ pattern-sinks:
314
+ - patterns:
315
+ - pattern-either:
316
+ - pattern: include($FILE)
317
+ - pattern: include_once($FILE)
318
+ - pattern: require($FILE)
319
+ - pattern: require_once($FILE)
320
+ - id: narvy.php.crypto.hardcoded-env-fallback-to-hmac-inline.hardcoded-env-fallback-to-hmac-inline
321
+ message: 'Hardcoded fallback secret ''$LITERAL'' is used as the HMAC key when the environment variable is unset. Anyone
322
+ reading this source can forge valid MACs. Fix: fail fast at startup.'
323
+ severity: ERROR
324
+ languages:
325
+ - php
326
+ metadata:
327
+ cwe:
328
+ - 'CWE-321: Use of Hard-coded Cryptographic Key'
329
+ - 'CWE-798: Use of Hard-coded Credentials'
330
+ owasp:
331
+ - A02:2021 - Cryptographic Failures
332
+ category: security
333
+ subcategory:
334
+ - vuln
335
+ technology:
336
+ - php
337
+ likelihood: HIGH
338
+ impact: HIGH
339
+ confidence: HIGH
340
+ vulnerability_class:
341
+ - Cryptographic Issues
342
+ - Hard-coded Credentials
343
+ patterns:
344
+ - pattern-either:
345
+ - pattern: 'hash_hmac($ALGO, $DATA, getenv($ENV) ?: "$LITERAL")
346
+
347
+ '
348
+ - pattern: 'hash_hmac($ALGO, $DATA, $_ENV[$ENV] ?? "$LITERAL")
349
+
350
+ '
351
+ - pattern: 'hash_hmac($ALGO, $DATA, $_SERVER[$ENV] ?? "$LITERAL")
352
+
353
+ '
354
+ - pattern: 'hash_hmac($ALGO, $DATA, getenv($ENV) ?? "$LITERAL")
355
+
356
+ '
357
+ - metavariable-regex:
358
+ metavariable: $LITERAL
359
+ regex: ^[A-Za-z0-9 _!@#$%^&*()+=,.:?<>\[\]{}|/\\-]{1,64}$
360
+ - id: narvy.php.crypto.hardcoded-env-fallback-to-hmac-twostep.hardcoded-env-fallback-to-hmac-twostep
361
+ message: 'Hardcoded fallback secret ''$LITERAL'' (assigned from `getenv` / `$_ENV` with default) is used as the HMAC key.
362
+ Fix: fail fast at startup.'
363
+ severity: ERROR
364
+ languages:
365
+ - php
366
+ metadata:
367
+ cwe:
368
+ - 'CWE-321: Use of Hard-coded Cryptographic Key'
369
+ - 'CWE-798: Use of Hard-coded Credentials'
370
+ owasp:
371
+ - A02:2021 - Cryptographic Failures
372
+ category: security
373
+ subcategory:
374
+ - vuln
375
+ technology:
376
+ - php
377
+ likelihood: HIGH
378
+ impact: HIGH
379
+ confidence: HIGH
380
+ vulnerability_class:
381
+ - Cryptographic Issues
382
+ - Hard-coded Credentials
383
+ patterns:
384
+ - pattern-either:
385
+ - pattern-inside: '$K = getenv($ENV) ?: "$LITERAL";
386
+
387
+ ...
388
+
389
+ '
390
+ - pattern-inside: '$K = $_ENV[$ENV] ?? "$LITERAL";
391
+
392
+ ...
393
+
394
+ '
395
+ - pattern-inside: '$K = $_SERVER[$ENV] ?? "$LITERAL";
396
+
397
+ ...
398
+
399
+ '
400
+ - pattern-inside: '$K = isset($_ENV[$ENV]) ? $_ENV[$ENV] : "$LITERAL";
401
+
402
+ ...
403
+
404
+ '
405
+ - pattern: 'hash_hmac($ALGO, $DATA, $K)
406
+
407
+ '
408
+ - metavariable-regex:
409
+ metavariable: $LITERAL
410
+ regex: ^[A-Za-z0-9 _!@#$%^&*()+=,.:?<>\[\]{}|/\\-]{1,64}$
411
+ - id: narvy.php.crypto.hardcoded-env-fallback-to-openssl-inline.hardcoded-env-fallback-to-openssl-inline
412
+ message: 'Hardcoded fallback secret ''$LITERAL'' is used as the symmetric cipher key in openssl_encrypt / openssl_decrypt
413
+ when the env var is unset. All ciphertexts can be decrypted by anyone reading this source. Fix: fail fast at startup and
414
+ derive the cipher key via hash_hkdf / PBKDF2 with a per-record salt.'
415
+ severity: ERROR
416
+ languages:
417
+ - php
418
+ metadata:
419
+ cwe:
420
+ - 'CWE-321: Use of Hard-coded Cryptographic Key'
421
+ - 'CWE-798: Use of Hard-coded Credentials'
422
+ owasp:
423
+ - A02:2021 - Cryptographic Failures
424
+ category: security
425
+ subcategory:
426
+ - vuln
427
+ technology:
428
+ - php
429
+ - openssl
430
+ likelihood: HIGH
431
+ impact: HIGH
432
+ confidence: HIGH
433
+ vulnerability_class:
434
+ - Cryptographic Issues
435
+ - Hard-coded Credentials
436
+ patterns:
437
+ - pattern-either:
438
+ - pattern: 'openssl_encrypt($PLAIN, $CIPHER, getenv($ENV) ?: "$LITERAL", ...)
439
+
440
+ '
441
+ - pattern: 'openssl_encrypt($PLAIN, $CIPHER, $_ENV[$ENV] ?? "$LITERAL", ...)
442
+
443
+ '
444
+ - pattern: 'openssl_decrypt($CT, $CIPHER, getenv($ENV) ?: "$LITERAL", ...)
445
+
446
+ '
447
+ - pattern: 'openssl_decrypt($CT, $CIPHER, $_ENV[$ENV] ?? "$LITERAL", ...)
448
+
449
+ '
450
+ - metavariable-regex:
451
+ metavariable: $LITERAL
452
+ regex: ^[A-Za-z0-9 _!@#$%^&*()+=,.:?<>\[\]{}|/\\-]{1,64}$
453
+ - id: narvy.php.crypto.hardcoded-env-fallback-to-openssl-twostep.hardcoded-env-fallback-to-openssl-twostep
454
+ message: Hardcoded fallback secret '$LITERAL' (assigned via env-fallback) is used as the openssl cipher key. Fail fast at
455
+ startup.
456
+ severity: ERROR
457
+ languages:
458
+ - php
459
+ metadata:
460
+ cwe:
461
+ - 'CWE-321: Use of Hard-coded Cryptographic Key'
462
+ - 'CWE-798: Use of Hard-coded Credentials'
463
+ owasp:
464
+ - A02:2021 - Cryptographic Failures
465
+ category: security
466
+ subcategory:
467
+ - vuln
468
+ technology:
469
+ - php
470
+ - openssl
471
+ likelihood: HIGH
472
+ impact: HIGH
473
+ confidence: HIGH
474
+ vulnerability_class:
475
+ - Cryptographic Issues
476
+ - Hard-coded Credentials
477
+ patterns:
478
+ - pattern-either:
479
+ - pattern-inside: '$K = getenv($ENV) ?: "$LITERAL";
480
+
481
+ ...
482
+
483
+ '
484
+ - pattern-inside: '$K = $_ENV[$ENV] ?? "$LITERAL";
485
+
486
+ ...
487
+
488
+ '
489
+ - pattern-either:
490
+ - pattern: 'openssl_encrypt($PLAIN, $CIPHER, $K, ...)
491
+
492
+ '
493
+ - pattern: 'openssl_decrypt($CT, $CIPHER, $K, ...)
494
+
495
+ '
496
+ - metavariable-regex:
497
+ metavariable: $LITERAL
498
+ regex: ^[A-Za-z0-9 _!@#$%^&*()+=,.:?<>\[\]{}|/\\-]{1,64}$
499
+ - id: narvy.php.ldap.request-input-to-search-filter.request-input-to-search-filter
500
+ message: A value from $_GET/$_POST/$_REQUEST/$_COOKIE is concatenated into an LDAP search/bind filter without escaping.
501
+ An attacker can inject LDAP filter metacharacters to bypass authentication or exfiltrate directory data (LDAP injection,
502
+ CWE-90). Escape the value with `ldap_escape($value, "", LDAP_ESCAPE_FILTER)` before building the filter string.
503
+ severity: ERROR
504
+ languages:
505
+ - php
506
+ mode: taint
507
+ metadata:
508
+ cwe:
509
+ - 'CWE-90: Improper Neutralization of Special Elements used in an LDAP Query (''LDAP Injection'')'
510
+ owasp:
511
+ - A03:2021 - Injection
512
+ category: security
513
+ subcategory:
514
+ - vuln
515
+ technology:
516
+ - php
517
+ likelihood: MEDIUM
518
+ impact: HIGH
519
+ confidence: MEDIUM
520
+ vulnerability_class:
521
+ - LDAP Injection
522
+ references:
523
+ - https://cwe.mitre.org/data/definitions/90.html
524
+ - https://owasp.org/www-community/attacks/LDAP_Injection
525
+ paths:
526
+ exclude:
527
+ - '**/test/**'
528
+ - '**/tests/**'
529
+ pattern-sources:
530
+ - pattern: $_GET[...]
531
+ - pattern: $_POST[...]
532
+ - pattern: $_REQUEST[...]
533
+ - pattern: $_COOKIE[...]
534
+ pattern-sanitizers:
535
+ - pattern: ldap_escape(...)
536
+ pattern-sinks:
537
+ - pattern: ldap_search($CONN, $BASE, $SINK)
538
+ - pattern: ldap_search($CONN, $BASE, $SINK, ...)
539
+ - pattern: ldap_list($CONN, $BASE, $SINK)
540
+ - pattern: ldap_list($CONN, $BASE, $SINK, ...)
541
+ - pattern: ldap_bind($CONN, $SINK, ...)
542
+ - id: narvy.php.misc.laravel-mass-assignment-request-all.laravel-mass-assignment-request-all
543
+ message: Eloquent `::create()` / `->fill()` / `->update()` is passed the entire request payload (`$request->all()`) with
544
+ no field allow-list. If the model has security-sensitive attributes (e.g. `is_admin`, `role`, `verified`, `balance`) and
545
+ does not restrict them via `$fillable` / `$guarded`, an attacker can set them by adding extra keys to the request body
546
+ (mass assignment, CWE-915). Pass an explicit array of permitted fields, or use `$request->only([...])` / `$request->validated()`.
547
+ severity: WARNING
548
+ languages:
549
+ - php
550
+ metadata:
551
+ cwe:
552
+ - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes'
553
+ owasp:
554
+ - A08:2021 - Software and Data Integrity Failures
555
+ category: security
556
+ subcategory:
557
+ - audit
558
+ technology:
559
+ - php
560
+ - laravel
561
+ - eloquent
562
+ likelihood: MEDIUM
563
+ impact: MEDIUM
564
+ confidence: LOW
565
+ vulnerability_class:
566
+ - Improper Access Control
567
+ patterns:
568
+ - pattern-either:
569
+ - pattern: $MODEL::create($REQUEST->all())
570
+ - pattern: $MODEL->fill($REQUEST->all())
571
+ - pattern: $MODEL->update($REQUEST->all())
572
+ - id: narvy.php.misc.insecure-chmod-permission.insecure-chmod-permission
573
+ message: '`chmod()` sets world-writable (and often world-readable) permissions (0777/0666). Any local user or process can
574
+ then modify or read this file, which is dangerous for config files, uploaded content directories, or scripts that get
575
+ executed later (CWE-732). Use the narrowest mode that works, e.g. 0600 for secrets or 0644 for regular files.'
576
+ severity: WARNING
577
+ languages:
578
+ - php
579
+ metadata:
580
+ cwe:
581
+ - 'CWE-732: Incorrect Permission Assignment for Critical Resource'
582
+ owasp:
583
+ - A01:2021 - Broken Access Control
584
+ category: security
585
+ subcategory:
586
+ - audit
587
+ technology:
588
+ - php
589
+ likelihood: LOW
590
+ impact: MEDIUM
591
+ confidence: HIGH
592
+ vulnerability_class:
593
+ - Improper Access Control
594
+ patterns:
595
+ - pattern-either:
596
+ - pattern: chmod($PATH, 0777)
597
+ - pattern: chmod($PATH, 0666)
598
+ - id: narvy.php.lang.open-redirect-header-location.open-redirect-header-location
599
+ message: '`header(''Location: ...'')` built with a value taken directly from user input. An attacker can craft a link to
600
+ your trusted domain that then redirects the victim to an attacker-controlled site - used in phishing to borrow the trusted
601
+ domain''s credibility (CWE-601). Validate the target against a fixed allow-list of paths/hosts, or only allow relative
602
+ paths starting with `/`.'
603
+ severity: WARNING
604
+ languages:
605
+ - php
606
+ metadata:
607
+ category: security
608
+ cwe:
609
+ - 'CWE-601: URL Redirection to Untrusted Site (''Open Redirect'')'
610
+ owasp:
611
+ - A01:2021 - Broken Access Control
612
+ subcategory:
613
+ - vuln
614
+ likelihood: MEDIUM
615
+ impact: MEDIUM
616
+ confidence: MEDIUM
617
+ technology:
618
+ - php
619
+ mode: taint
620
+ pattern-sources:
621
+ - patterns:
622
+ - pattern-either:
623
+ - pattern: $_GET[...]
624
+ - pattern: $_POST[...]
625
+ - pattern: $_REQUEST[...]
626
+ pattern-sinks:
627
+ - patterns:
628
+ - pattern-either:
629
+ - pattern: 'header("Location: " . $SINK)'
630
+ - pattern: 'header("Location: $SINK")'
631
+ - pattern: 'header("Location: " . $SINK . "...")'
632
+ - id: narvy.php.laravel.open-redirect-redirect-tainted.open-redirect-redirect-tainted
633
+ message: Laravel `redirect()` / `Redirect::to()` called with a URL taken directly from user input (typically a `?next=`/`?redirect=`
634
+ query parameter). Without validating the target, an attacker can send victims through your trusted domain to an attacker-controlled
635
+ site (CWE-601). Use `redirect()->intended()` with a safe fallback, or validate the target against `url()->isValidRedirect()`
636
+ / a fixed allow-list before passing it to `redirect()->to()`.
637
+ severity: WARNING
638
+ languages:
639
+ - php
640
+ metadata:
641
+ category: security
642
+ cwe:
643
+ - 'CWE-601: URL Redirection to Untrusted Site (''Open Redirect'')'
644
+ owasp:
645
+ - A01:2021 - Broken Access Control
646
+ subcategory:
647
+ - vuln
648
+ likelihood: MEDIUM
649
+ impact: MEDIUM
650
+ confidence: MEDIUM
651
+ technology:
652
+ - php
653
+ - laravel
654
+ mode: taint
655
+ pattern-sources:
656
+ - patterns:
657
+ - pattern-either:
658
+ - pattern: $_GET[...]
659
+ - pattern: $_POST[...]
660
+ - pattern: request($X)
661
+ - pattern: request()->input(...)
662
+ - pattern: request()->get(...)
663
+ - pattern: request()->query(...)
664
+ pattern-sinks:
665
+ - patterns:
666
+ - pattern-either:
667
+ - pattern: redirect($SINK)
668
+ - pattern: redirect()->to($SINK)
669
+ - pattern: Redirect::to($SINK)
670
+ - pattern: response()->redirectTo($SINK)
671
+ - id: narvy.php.info.phpinfo-call.phpinfo-call
672
+ message: '`phpinfo()` call found in application code reachable via a web request. It dumps the full PHP configuration -
673
+ loaded extensions, disabled functions, include paths, environment variables, and (with `INFO_ALL`/default flags) request
674
+ headers and server variables - which materially helps an attacker fingerprint the stack and find further weaknesses (CWE-200).
675
+ Remove it from production code, or gate it behind an authenticated admin-only route with a strict IP allow-list.'
676
+ severity: WARNING
677
+ languages:
678
+ - php
679
+ metadata:
680
+ category: security
681
+ cwe:
682
+ - 'CWE-200: Exposure of Sensitive Information to an Unauthorized Actor'
683
+ owasp:
684
+ - A05:2021 - Security Misconfiguration
685
+ subcategory:
686
+ - vuln
687
+ likelihood: MEDIUM
688
+ impact: MEDIUM
689
+ confidence: MEDIUM
690
+ technology:
691
+ - php
692
+ patterns:
693
+ - pattern-either:
694
+ - pattern: phpinfo()
695
+ - pattern: phpinfo($X)
696
+ - id: narvy.php.sqli.request-input-to-query.request-input-to-query
697
+ message: A value derived from $_GET/$_POST/$_REQUEST/$_COOKIE flows into a raw SQL query executed via mysqli_query/mysql_query/pg_query/PDO::query/
698
+ PDO::exec without parameterization. This is SQL injection (CWE-89). Use a prepared statement with bound parameters instead
699
+ of building the query string with request-derived data.
700
+ severity: ERROR
701
+ languages:
702
+ - php
703
+ mode: taint
704
+ metadata:
705
+ cwe:
706
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
707
+ owasp:
708
+ - A03:2021 - Injection
709
+ category: security
710
+ subcategory:
711
+ - vuln
712
+ technology:
713
+ - php
714
+ likelihood: HIGH
715
+ impact: HIGH
716
+ confidence: HIGH
717
+ vulnerability_class:
718
+ - SQL Injection
719
+ references:
720
+ - https://cwe.mitre.org/data/definitions/89.html
721
+ - https://owasp.org/www-community/attacks/SQL_Injection
722
+ paths:
723
+ exclude:
724
+ - '**/test/**'
725
+ - '**/tests/**'
726
+ - '**/*Test.php'
727
+ pattern-sources:
728
+ - pattern: $_GET[...]
729
+ - pattern: $_POST[...]
730
+ - pattern: $_REQUEST[...]
731
+ - pattern: $_COOKIE[...]
732
+ pattern-sanitizers:
733
+ - pattern: mysqli_real_escape_string(...)
734
+ - pattern: $CONN->real_escape_string(...)
735
+ - pattern: addslashes(...)
736
+ - pattern: intval(...)
737
+ - pattern: (int)$X
738
+ - pattern: (int) $X
739
+ pattern-sinks:
740
+ - pattern: mysqli_query($CONN, $SINK)
741
+ - pattern: mysql_query($SINK)
742
+ - pattern: pg_query($CONN, $SINK)
743
+ - pattern: pg_query($SINK)
744
+ - pattern: $CONN->query($SINK)
745
+ - pattern: $PDO->query($SINK)
746
+ - pattern: $PDO->exec($SINK)
747
+ - pattern: $PDO->prepare($SINK)
748
+ - id: narvy.php.generic.sqli-mysqli-query-tainted.sqli-mysqli-query-tainted
749
+ message: SQL query built with string concatenation/interpolation and passed to `mysqli_query()` / `$mysqli->query()` / `mysql_query()`.
750
+ These functions run the string as-is with no parameter binding; a tainted value is a SQL injection (CWE-89). Use `mysqli_prepare()`
751
+ with bound parameters.
752
+ severity: ERROR
753
+ languages:
754
+ - php
755
+ metadata:
756
+ category: security
757
+ cwe:
758
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
759
+ owasp:
760
+ - A03:2021 - Injection
761
+ subcategory:
762
+ - vuln
763
+ likelihood: HIGH
764
+ impact: HIGH
765
+ confidence: MEDIUM
766
+ technology:
767
+ - php
768
+ mode: taint
769
+ pattern-sources:
770
+ - patterns:
771
+ - pattern-either:
772
+ - pattern: $_GET[...]
773
+ - pattern: $_POST[...]
774
+ - pattern: $_REQUEST[...]
775
+ - pattern: $_COOKIE[...]
776
+ pattern-sinks:
777
+ - patterns:
778
+ - pattern-either:
779
+ - pattern: mysqli_query($CONN, "..." . $SINK . "...")
780
+ - pattern: mysqli_query($CONN, "...$SINK...")
781
+ - pattern: $CONN->query("..." . $SINK . "...")
782
+ - pattern: $CONN->query("...$SINK...")
783
+ - pattern: mysql_query("..." . $SINK . "...")
784
+ - pattern: mysql_query("...$SINK...")
785
+ pattern-sanitizers:
786
+ - patterns:
787
+ - pattern: mysqli_real_escape_string(...)
788
+ - pattern: $CONN->real_escape_string(...)
789
+ - pattern: intval(...)
790
+ - pattern: (int)$X
791
+ - id: narvy.php.generic.sqli-pdo-query-exec-tainted.sqli-pdo-query-exec-tainted
792
+ message: SQL query built with string concatenation/interpolation and passed to `PDO::query()` / `PDO::exec()`. Both run
793
+ the string as literal SQL with no parameter binding; a tainted value is a SQL injection (CWE-89). Use `PDO::prepare()`
794
+ with bound parameters instead.
795
+ severity: ERROR
796
+ languages:
797
+ - php
798
+ metadata:
799
+ category: security
800
+ cwe:
801
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
802
+ owasp:
803
+ - A03:2021 - Injection
804
+ subcategory:
805
+ - vuln
806
+ likelihood: HIGH
807
+ impact: HIGH
808
+ confidence: MEDIUM
809
+ technology:
810
+ - php
811
+ mode: taint
812
+ pattern-sources:
813
+ - patterns:
814
+ - pattern-either:
815
+ - pattern: $_GET[...]
816
+ - pattern: $_POST[...]
817
+ - pattern: $_REQUEST[...]
818
+ - pattern: $_COOKIE[...]
819
+ pattern-sinks:
820
+ - patterns:
821
+ - pattern-either:
822
+ - pattern: $PDO->query("..." . $SINK . "...")
823
+ - pattern: $PDO->query("...$SINK...")
824
+ - pattern: $PDO->exec("..." . $SINK . "...")
825
+ - pattern: $PDO->exec("...$SINK...")
826
+ pattern-sanitizers:
827
+ - patterns:
828
+ - pattern: intval(...)
829
+ - pattern: (int)$X
830
+ - id: narvy.php.generic.sqli-prepare-string-built-tainted.sqli-prepare-string-built-tainted
831
+ message: '`PDO::prepare()` / `mysqli_prepare()` called with a query string that is itself built by concatenating/interpolating
832
+ a tainted value into the SQL text (e.g. a table/column name). Preparing the statement does not help if the injection point
833
+ is baked into the SQL text before `prepare()` is called (CWE-89). Validate identifiers against a fixed allow-list.'
834
+ severity: WARNING
835
+ languages:
836
+ - php
837
+ metadata:
838
+ category: security
839
+ cwe:
840
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
841
+ owasp:
842
+ - A03:2021 - Injection
843
+ subcategory:
844
+ - vuln
845
+ likelihood: MEDIUM
846
+ impact: HIGH
847
+ confidence: MEDIUM
848
+ technology:
849
+ - php
850
+ mode: taint
851
+ pattern-sources:
852
+ - patterns:
853
+ - pattern-either:
854
+ - pattern: $_GET[...]
855
+ - pattern: $_POST[...]
856
+ - pattern: $_REQUEST[...]
857
+ pattern-sinks:
858
+ - patterns:
859
+ - pattern-either:
860
+ - pattern: $PDO->prepare("..." . $SINK . "...")
861
+ - pattern: $PDO->prepare("...$SINK...")
862
+ - pattern: mysqli_prepare($CONN, "..." . $SINK . "...")
863
+ - pattern: mysqli_prepare($CONN, "...$SINK...")
864
+ pattern-sanitizers:
865
+ - patterns:
866
+ - pattern: intval(...)
867
+ - pattern: (int)$X
868
+ - id: narvy.php.laravel.sqli-whereraw-concat.sqli-whereraw-concat
869
+ message: 'Laravel `whereRaw()` / `orWhereRaw()` / `havingRaw()` built with string concatenation or interpolation instead
870
+ of bound parameters. The query builder does not escape raw-SQL fragments, so a tainted value reaching this string is a
871
+ SQL injection (CWE-89). Pass the value as a bound parameter: `whereRaw(''col = ?'', [$value])`.'
872
+ severity: ERROR
873
+ languages:
874
+ - php
875
+ metadata:
876
+ category: security
877
+ cwe:
878
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
879
+ owasp:
880
+ - A03:2021 - Injection
881
+ subcategory:
882
+ - vuln
883
+ likelihood: HIGH
884
+ impact: HIGH
885
+ confidence: MEDIUM
886
+ technology:
887
+ - php
888
+ - laravel
889
+ paths:
890
+ exclude:
891
+ - '**/migrations/**'
892
+ - '**/seeders/**'
893
+ - '**/database/migrations/**'
894
+ patterns:
895
+ - pattern-either:
896
+ - pattern: $Q->whereRaw("..." . $X . "...", ...)
897
+ - pattern: $Q->whereRaw($X . "...", ...)
898
+ - pattern: $Q->whereRaw("...$X...", ...)
899
+ - pattern: $Q->orWhereRaw("..." . $X . "...", ...)
900
+ - pattern: $Q->orWhereRaw("...$X...", ...)
901
+ - pattern: $Q->havingRaw("..." . $X . "...", ...)
902
+ - pattern: $Q->havingRaw("...$X...", ...)
903
+ - pattern-not: $Q->whereRaw("...", [...])
904
+ - metavariable-pattern:
905
+ metavariable: $X
906
+ patterns:
907
+ - pattern-not: '"..."'
908
+ - id: narvy.php.laravel.sqli-dbraw-concat.sqli-dbraw-concat
909
+ message: Laravel `DB::raw()` / `selectRaw()` built with string concatenation or interpolation. `DB::raw()` output is inserted
910
+ into the query verbatim with no escaping; if this value traces back to request input this is a SQL injection (CWE-89).
911
+ Confirm whether the concatenated value is request-derived; if so, build the fragment from a fixed allow-list or move the
912
+ value to a bound parameter instead.
913
+ severity: WARNING
914
+ languages:
915
+ - php
916
+ metadata:
917
+ category: security
918
+ cwe:
919
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
920
+ owasp:
921
+ - A03:2021 - Injection
922
+ subcategory:
923
+ - vuln
924
+ likelihood: MEDIUM
925
+ impact: HIGH
926
+ confidence: LOW
927
+ technology:
928
+ - php
929
+ - laravel
930
+ paths:
931
+ exclude:
932
+ - '**/migrations/**'
933
+ - '**/seeders/**'
934
+ - '**/database/migrations/**'
935
+ patterns:
936
+ - pattern-either:
937
+ - pattern: DB::raw("..." . $X . "...")
938
+ - pattern: DB::raw("...$X...")
939
+ - pattern: DB::raw($X . "...")
940
+ - pattern: $Q->selectRaw("..." . $X . "...", ...)
941
+ - pattern: $Q->selectRaw("...$X...", ...)
942
+ - metavariable-pattern:
943
+ metavariable: $X
944
+ patterns:
945
+ - pattern-not: '"..."'
946
+ - pattern-not: DB::getTablePrefix()
947
+ - metavariable-regex:
948
+ metavariable: $X
949
+ regex: (?i)^(?!.*prefix).*$
950
+ - id: narvy.php.laravel.sqli-db-statement-tainted.sqli-db-statement-tainted
951
+ message: Laravel `DB::statement()` / `DB::unprepared()` / `DB::select()` called with a concatenated or interpolated query
952
+ string. Unlike `DB::select($sql, $bindings)` with a bindings array, a built string here is executed as-is; if this value
953
+ traces back to request input this is a SQL injection (CWE-89). Confirm whether the concatenated value is request-derived,
954
+ then use the bindings-array form instead.
955
+ severity: WARNING
956
+ languages:
957
+ - php
958
+ metadata:
959
+ category: security
960
+ cwe:
961
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
962
+ owasp:
963
+ - A03:2021 - Injection
964
+ subcategory:
965
+ - vuln
966
+ likelihood: MEDIUM
967
+ impact: HIGH
968
+ confidence: LOW
969
+ technology:
970
+ - php
971
+ - laravel
972
+ paths:
973
+ exclude:
974
+ - '**/migrations/**'
975
+ - '**/seeders/**'
976
+ - '**/database/migrations/**'
977
+ patterns:
978
+ - pattern-either:
979
+ - pattern: DB::statement("..." . $X . "...")
980
+ - pattern: DB::statement("...$X...")
981
+ - pattern: DB::unprepared("..." . $X . "...")
982
+ - pattern: DB::unprepared("...$X...")
983
+ - pattern: DB::select("..." . $X . "...")
984
+ - pattern: DB::select("...$X...")
985
+ - metavariable-pattern:
986
+ metavariable: $X
987
+ patterns:
988
+ - pattern-not: '"..."'
989
+ - id: narvy.php.crypto.aes-cbc-static-iv-literal.aes-cbc-static-iv-literal
990
+ message: '`openssl_encrypt()` in CBC mode called with a hardcoded string literal (or all-zero string) as the IV. Every message
991
+ encrypted with this key+IV pair leaks whether two plaintexts share a prefix, and reuse across messages breaks CBC''s semantic-security
992
+ guarantee (CWE-329). Generate a fresh random IV per encryption with `random_bytes(openssl_cipher_iv_length($cipher))`
993
+ and store/transmit it alongside the ciphertext.'
994
+ severity: ERROR
995
+ languages:
996
+ - php
997
+ metadata:
998
+ category: security
999
+ cwe:
1000
+ - 'CWE-329: Generation of Predictable IV with CBC Mode'
1001
+ - 'CWE-330: Use of Insufficiently Random Values'
1002
+ owasp:
1003
+ - A02:2021 - Cryptographic Failures
1004
+ subcategory:
1005
+ - vuln
1006
+ likelihood: MEDIUM
1007
+ impact: HIGH
1008
+ confidence: HIGH
1009
+ technology:
1010
+ - php
1011
+ patterns:
1012
+ - pattern: openssl_encrypt($DATA, $CIPHER, $KEY, $OPT, "...", ...)
1013
+ - metavariable-regex:
1014
+ metavariable: $CIPHER
1015
+ regex: (?i).*-cbc.*
1016
+ - metavariable-pattern:
1017
+ metavariable: $CIPHER
1018
+ patterns:
1019
+ - pattern-not: $VAR
1020
+ - id: narvy.php.crypto.aes-cbc-iv-derived-from-key.aes-cbc-iv-derived-from-key
1021
+ message: '`openssl_encrypt()` IV argument is the same variable as (or is directly derived via `substr()`/hashing of) the
1022
+ encryption key. Deriving the IV from the key removes the independence CBC relies on and produces a predictable, reused
1023
+ IV across every message encrypted under that key (CWE-329). Use a fresh cryptographically random IV per call, independent
1024
+ of the key.'
1025
+ severity: WARNING
1026
+ languages:
1027
+ - php
1028
+ metadata:
1029
+ category: security
1030
+ cwe:
1031
+ - 'CWE-329: Generation of Predictable IV with CBC Mode'
1032
+ owasp:
1033
+ - A02:2021 - Cryptographic Failures
1034
+ subcategory:
1035
+ - vuln
1036
+ likelihood: LOW
1037
+ impact: HIGH
1038
+ confidence: MEDIUM
1039
+ technology:
1040
+ - php
1041
+ patterns:
1042
+ - pattern-either:
1043
+ - pattern: openssl_encrypt($DATA, $CIPHER, $KEY, $OPT, $KEY)
1044
+ - pattern: openssl_encrypt($DATA, $CIPHER, $KEY, $OPT, substr($KEY, ...))
1045
+ - metavariable-regex:
1046
+ metavariable: $CIPHER
1047
+ regex: (?i).*-cbc.*
1048
+ - id: narvy.php.crypto.mcrypt-static-iv.mcrypt-static-iv
1049
+ message: Legacy `mcrypt_encrypt()` called with a hardcoded string literal as the IV. `mcrypt` itself is deprecated/removed
1050
+ since PHP 7.2, but code kept running on older runtimes with a fixed IV loses CBC's semantic-security guarantee the same
1051
+ way `openssl_encrypt` does (CWE-329). Migrate to `openssl_encrypt`/`sodium_crypto_secretbox` with a fresh random IV/nonce
1052
+ per message.
1053
+ severity: WARNING
1054
+ languages:
1055
+ - php
1056
+ metadata:
1057
+ category: security
1058
+ cwe:
1059
+ - 'CWE-329: Generation of Predictable IV with CBC Mode'
1060
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1061
+ owasp:
1062
+ - A02:2021 - Cryptographic Failures
1063
+ subcategory:
1064
+ - vuln
1065
+ likelihood: LOW
1066
+ impact: MEDIUM
1067
+ confidence: MEDIUM
1068
+ technology:
1069
+ - php
1070
+ pattern: mcrypt_encrypt($CIPHER, $KEY, $DATA, $MODE, "...")
1071
+ - id: narvy.php.lang.tainted-call-user-func.tainted-call-user-func
1072
+ message: '`call_user_func()` / `call_user_func_array()` called with a callable name/array taken directly from user input.
1073
+ An attacker who controls the function name can invoke any reachable function, including dangerous built-ins (`exec`, `system`,
1074
+ `unlink`, ...) - unsafe reflection / code execution by proxy (CWE-470). Restrict the callable to a fixed allow-list keyed
1075
+ by a validated token, never the raw input.'
1076
+ severity: ERROR
1077
+ languages:
1078
+ - php
1079
+ metadata:
1080
+ category: security
1081
+ cwe:
1082
+ - 'CWE-470: Use of Externally-Controlled Input to Select Classes or Code (''Unsafe Reflection'')'
1083
+ owasp:
1084
+ - A03:2021 - Injection
1085
+ subcategory:
1086
+ - vuln
1087
+ likelihood: MEDIUM
1088
+ impact: HIGH
1089
+ confidence: MEDIUM
1090
+ technology:
1091
+ - php
1092
+ mode: taint
1093
+ pattern-sources:
1094
+ - patterns:
1095
+ - pattern-either:
1096
+ - pattern: $_GET[...]
1097
+ - pattern: $_POST[...]
1098
+ - pattern: $_REQUEST[...]
1099
+ - pattern: $_COOKIE[...]
1100
+ pattern-sinks:
1101
+ - patterns:
1102
+ - pattern-either:
1103
+ - pattern: call_user_func($SINK, ...)
1104
+ - pattern: call_user_func_array($SINK, ...)
1105
+ - pattern: forward_static_call($SINK, ...)
1106
+ - pattern: forward_static_call_array($SINK, ...)
1107
+ - id: narvy.php.lang.tainted-variable-function-call.tainted-variable-function-call
1108
+ message: Variable function call `$fn(...)` where `$fn` is assigned directly from user input. PHP calls whatever function
1109
+ name the string holds - this is the same unsafe-reflection risk as `call_user_func()` with a tainted name (CWE-470). Restrict
1110
+ to a fixed allow-list of function names.
1111
+ severity: WARNING
1112
+ languages:
1113
+ - php
1114
+ metadata:
1115
+ category: security
1116
+ cwe:
1117
+ - 'CWE-470: Use of Externally-Controlled Input to Select Classes or Code (''Unsafe Reflection'')'
1118
+ owasp:
1119
+ - A03:2021 - Injection
1120
+ subcategory:
1121
+ - vuln
1122
+ likelihood: LOW
1123
+ impact: HIGH
1124
+ confidence: LOW
1125
+ technology:
1126
+ - php
1127
+ patterns:
1128
+ - pattern-either:
1129
+ - pattern: '$FN = $_GET[...];
1130
+
1131
+ ...
1132
+
1133
+ $FN(...);
1134
+
1135
+ '
1136
+ - pattern: '$FN = $_POST[...];
1137
+
1138
+ ...
1139
+
1140
+ $FN(...);
1141
+
1142
+ '
1143
+ - pattern: '$FN = $_REQUEST[...];
1144
+
1145
+ ...
1146
+
1147
+ $FN(...);
1148
+
1149
+ '
1150
+ - id: narvy.php.lang.tainted-exec-family.tainted-exec-family
1151
+ message: '`exec()` / `shell_exec()` / `system()` / `passthru()` / `` `backtick` `` called with a command string built from
1152
+ user input. The command is handed to the shell - an attacker can append `;`, `&&`, `|`, or backticks to run arbitrary
1153
+ OS commands (CWE-78). Use `escapeshellarg()`/`escapeshellcmd()` on every tainted argument, or better, avoid a shell entirely
1154
+ by calling the target program directly.'
1155
+ severity: ERROR
1156
+ languages:
1157
+ - php
1158
+ metadata:
1159
+ category: security
1160
+ cwe:
1161
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
1162
+ owasp:
1163
+ - A03:2021 - Injection
1164
+ subcategory:
1165
+ - vuln
1166
+ likelihood: HIGH
1167
+ impact: HIGH
1168
+ confidence: MEDIUM
1169
+ technology:
1170
+ - php
1171
+ mode: taint
1172
+ pattern-sources:
1173
+ - patterns:
1174
+ - pattern-either:
1175
+ - pattern: $_GET[...]
1176
+ - pattern: $_POST[...]
1177
+ - pattern: $_REQUEST[...]
1178
+ - pattern: $_COOKIE[...]
1179
+ pattern-sinks:
1180
+ - patterns:
1181
+ - pattern-either:
1182
+ - pattern: exec("..." . $SINK . "...", ...)
1183
+ - pattern: exec("...$SINK...", ...)
1184
+ - pattern: shell_exec("..." . $SINK . "...")
1185
+ - pattern: shell_exec("...$SINK...")
1186
+ - pattern: system("..." . $SINK . "...", ...)
1187
+ - pattern: system("...$SINK...", ...)
1188
+ - pattern: passthru("..." . $SINK . "...", ...)
1189
+ - pattern: passthru("...$SINK...", ...)
1190
+ pattern-sanitizers:
1191
+ - patterns:
1192
+ - pattern: escapeshellarg(...)
1193
+ - pattern: escapeshellcmd(...)
1194
+ - pattern: intval(...)
1195
+ - pattern: (int)$X
1196
+ - id: narvy.php.lang.tainted-proc-popen.tainted-proc-popen
1197
+ message: '`proc_open()` / `popen()` called with a command string built from user input. Both spawn the command through the
1198
+ shell; a tainted value is an OS command injection (CWE-78). Prefer `proc_open()` with the command passed as an argv array
1199
+ (bypasses the shell) and `escapeshellarg()`/`escapeshellcmd()` on any remaining tainted piece.'
1200
+ severity: ERROR
1201
+ languages:
1202
+ - php
1203
+ metadata:
1204
+ category: security
1205
+ cwe:
1206
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
1207
+ owasp:
1208
+ - A03:2021 - Injection
1209
+ subcategory:
1210
+ - vuln
1211
+ likelihood: MEDIUM
1212
+ impact: HIGH
1213
+ confidence: MEDIUM
1214
+ technology:
1215
+ - php
1216
+ mode: taint
1217
+ pattern-sources:
1218
+ - patterns:
1219
+ - pattern-either:
1220
+ - pattern: $_GET[...]
1221
+ - pattern: $_POST[...]
1222
+ - pattern: $_REQUEST[...]
1223
+ - pattern: $_COOKIE[...]
1224
+ pattern-sinks:
1225
+ - patterns:
1226
+ - pattern-either:
1227
+ - pattern: proc_open("..." . $SINK . "...", ...)
1228
+ - pattern: proc_open("...$SINK...", ...)
1229
+ - pattern: popen("..." . $SINK . "...", ...)
1230
+ - pattern: popen("...$SINK...", ...)
1231
+ pattern-sanitizers:
1232
+ - patterns:
1233
+ - pattern: escapeshellarg(...)
1234
+ - pattern: escapeshellcmd(...)
1235
+ - id: narvy.php.session.session-id-tainted.session-id-tainted
1236
+ message: '`session_id()` called with a value taken from user-controlled input (query string, cookie, or POST body). This
1237
+ allows session fixation - an attacker sets the session ID before the victim logs in, then reuses that same ID after authentication
1238
+ succeeds (CWE-384). Never accept a caller-supplied session ID; call `session_id()` with no argument to let PHP generate
1239
+ one, and call `session_regenerate_id(true)` immediately after a successful login.'
1240
+ severity: ERROR
1241
+ languages:
1242
+ - php
1243
+ metadata:
1244
+ category: security
1245
+ cwe:
1246
+ - 'CWE-384: Session Fixation'
1247
+ owasp:
1248
+ - A07:2021 - Identification and Authentication Failures
1249
+ subcategory:
1250
+ - vuln
1251
+ likelihood: MEDIUM
1252
+ impact: HIGH
1253
+ confidence: MEDIUM
1254
+ technology:
1255
+ - php
1256
+ mode: taint
1257
+ pattern-sources:
1258
+ - patterns:
1259
+ - pattern-either:
1260
+ - pattern: $_GET[...]
1261
+ - pattern: $_POST[...]
1262
+ - pattern: $_REQUEST[...]
1263
+ - pattern: $_COOKIE[...]
1264
+ pattern-sinks:
1265
+ - patterns:
1266
+ - pattern: session_id($SINK)
1267
+ - id: narvy.php.session.session-name-tainted.session-name-tainted
1268
+ message: '`session_name()` set from user-controlled input. The session cookie name should be a fixed application constant;
1269
+ letting an attacker influence it can be combined with other bugs to fixate or confuse session handling across sub-applications
1270
+ on the same domain (CWE-384). Use a hardcoded session name.'
1271
+ severity: WARNING
1272
+ languages:
1273
+ - php
1274
+ metadata:
1275
+ category: security
1276
+ cwe:
1277
+ - 'CWE-384: Session Fixation'
1278
+ owasp:
1279
+ - A07:2021 - Identification and Authentication Failures
1280
+ subcategory:
1281
+ - vuln
1282
+ likelihood: LOW
1283
+ impact: MEDIUM
1284
+ confidence: LOW
1285
+ technology:
1286
+ - php
1287
+ mode: taint
1288
+ pattern-sources:
1289
+ - patterns:
1290
+ - pattern-either:
1291
+ - pattern: $_GET[...]
1292
+ - pattern: $_POST[...]
1293
+ - pattern: $_REQUEST[...]
1294
+ pattern-sinks:
1295
+ - patterns:
1296
+ - pattern: session_name($SINK)
1297
+ - id: narvy.php.ssrf.tainted-url-file-get-contents.tainted-url-file-get-contents
1298
+ message: '`file_get_contents()` / `fopen()` called with a URL built from user input. If the scheme/host is attacker-controlled,
1299
+ this lets the attacker make the server issue requests to internal services (metadata endpoints, admin panels, other hosts
1300
+ on the internal network) - SSRF (CWE-918). Validate the target against a strict allow-list of hosts and reject non-`https`
1301
+ schemes before fetching.'
1302
+ severity: ERROR
1303
+ languages:
1304
+ - php
1305
+ metadata:
1306
+ category: security
1307
+ cwe:
1308
+ - 'CWE-918: Server-Side Request Forgery (SSRF)'
1309
+ owasp:
1310
+ - A10:2021 - Server-Side Request Forgery (SSRF)
1311
+ subcategory:
1312
+ - vuln
1313
+ likelihood: MEDIUM
1314
+ impact: HIGH
1315
+ confidence: MEDIUM
1316
+ technology:
1317
+ - php
1318
+ mode: taint
1319
+ pattern-sources:
1320
+ - patterns:
1321
+ - pattern-either:
1322
+ - pattern: $_GET[...]
1323
+ - pattern: $_POST[...]
1324
+ - pattern: $_REQUEST[...]
1325
+ pattern-sinks:
1326
+ - patterns:
1327
+ - pattern-either:
1328
+ - pattern: file_get_contents($SINK)
1329
+ - pattern: file_get_contents("..." . $SINK . "...")
1330
+ - pattern: file_get_contents("...$SINK...")
1331
+ - pattern: fopen($SINK, ...)
1332
+ - pattern: fopen("..." . $SINK . "...", ...)
1333
+ - pattern: readfile($SINK)
1334
+ pattern-sanitizers:
1335
+ - patterns:
1336
+ - pattern: parse_url(...)
1337
+ - id: narvy.php.ssrf.tainted-curl-url.tainted-curl-url
1338
+ message: '`CURLOPT_URL` (or `curl_init()`''s URL argument) set from user input. An attacker who controls the target host
1339
+ can make the server issue requests on their behalf to internal-only endpoints - SSRF (CWE-918). Validate the host against
1340
+ a strict allow-list before setting it, and reject `file://`/`gopher://`/`dict://` schemes.'
1341
+ severity: ERROR
1342
+ languages:
1343
+ - php
1344
+ metadata:
1345
+ category: security
1346
+ cwe:
1347
+ - 'CWE-918: Server-Side Request Forgery (SSRF)'
1348
+ owasp:
1349
+ - A10:2021 - Server-Side Request Forgery (SSRF)
1350
+ subcategory:
1351
+ - vuln
1352
+ likelihood: MEDIUM
1353
+ impact: HIGH
1354
+ confidence: MEDIUM
1355
+ technology:
1356
+ - php
1357
+ mode: taint
1358
+ pattern-sources:
1359
+ - patterns:
1360
+ - pattern-either:
1361
+ - pattern: $_GET[...]
1362
+ - pattern: $_POST[...]
1363
+ - pattern: $_REQUEST[...]
1364
+ pattern-sinks:
1365
+ - patterns:
1366
+ - pattern-either:
1367
+ - pattern: curl_setopt($CH, CURLOPT_URL, $SINK)
1368
+ - pattern: curl_setopt($CH, CURLOPT_URL, "..." . $SINK . "...")
1369
+ - pattern: curl_init($SINK)
1370
+ - pattern: curl_init("..." . $SINK . "...")
1371
+ pattern-sanitizers:
1372
+ - patterns:
1373
+ - pattern: parse_url(...)
1374
+ - id: narvy.php.crypto.md5-sha1-as-password-hash.md5-sha1-as-password-hash
1375
+ message: MD5/SHA1 digest applied to a value whose name indicates a password/credential. Both algorithms are fast, unsalted,
1376
+ and brute-forceable with commodity GPUs; MD5 is also collision-broken. Use `password_hash($password, PASSWORD_DEFAULT)`
1377
+ (bcrypt/Argon2) for credential storage, and verify with `password_verify()`. CWE-916.
1378
+ severity: ERROR
1379
+ languages:
1380
+ - php
1381
+ metadata:
1382
+ cwe:
1383
+ - 'CWE-916: Use of Password Hash With Insufficient Computational Effort'
1384
+ owasp:
1385
+ - A02:2021 - Cryptographic Failures
1386
+ category: security
1387
+ subcategory:
1388
+ - vuln
1389
+ technology:
1390
+ - php
1391
+ likelihood: HIGH
1392
+ impact: HIGH
1393
+ confidence: MEDIUM
1394
+ vulnerability_class:
1395
+ - Cryptographic Issues
1396
+ patterns:
1397
+ - pattern-either:
1398
+ - pattern: md5($PW)
1399
+ - pattern: sha1($PW)
1400
+ - metavariable-regex:
1401
+ metavariable: $PW
1402
+ regex: (?i).*(pass|pwd|secret|credential).*
1403
+ - id: narvy.php.crypto.mcrypt-weak-algo-or-mode.mcrypt-weak-algo-or-mode
1404
+ message: '`mcrypt_encrypt()` called with a broken cipher (DES/TripleDES/RC4) or ECB mode. DES has a brute-forceable 56-bit
1405
+ key, RC4 has known keystream biases, and ECB leaks plaintext structure. The `mcrypt` extension itself is deprecated/removed
1406
+ since PHP 7.2 - migrate to `openssl_encrypt()` with `aes-256-gcm`. CWE-327.'
1407
+ severity: ERROR
1408
+ languages:
1409
+ - php
1410
+ metadata:
1411
+ cwe:
1412
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1413
+ owasp:
1414
+ - A02:2021 - Cryptographic Failures
1415
+ category: security
1416
+ subcategory:
1417
+ - vuln
1418
+ technology:
1419
+ - php
1420
+ - mcrypt
1421
+ likelihood: LOW
1422
+ impact: HIGH
1423
+ confidence: HIGH
1424
+ vulnerability_class:
1425
+ - Cryptographic Issues
1426
+ patterns:
1427
+ - pattern: mcrypt_encrypt($CIPHER, ...)
1428
+ - metavariable-regex:
1429
+ metavariable: $CIPHER
1430
+ regex: (?i).*(des|rc4|arcfour|ecb).*
1431
+ - id: narvy.php.crypto.openssl-encrypt-ecb-mode.openssl-encrypt-ecb-mode
1432
+ message: '`openssl_encrypt()` called with an ECB-mode cipher string (e.g. "aes-128-ecb"). ECB encrypts identical plaintext
1433
+ blocks to identical ciphertext blocks, leaking structural information about the data. Use an authenticated mode such as
1434
+ "aes-256-gcm" instead. CWE-327.'
1435
+ severity: ERROR
1436
+ languages:
1437
+ - php
1438
+ metadata:
1439
+ cwe:
1440
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1441
+ owasp:
1442
+ - A02:2021 - Cryptographic Failures
1443
+ category: security
1444
+ subcategory:
1445
+ - vuln
1446
+ technology:
1447
+ - php
1448
+ - openssl
1449
+ likelihood: LOW
1450
+ impact: HIGH
1451
+ confidence: HIGH
1452
+ vulnerability_class:
1453
+ - Cryptographic Issues
1454
+ patterns:
1455
+ - pattern: openssl_encrypt($DATA, "$CIPHER", ...)
1456
+ - metavariable-regex:
1457
+ metavariable: $CIPHER
1458
+ regex: (?i).*-ecb$
1459
+ - id: narvy.php.crypto.weak-random-security-token.weak-random-security-token
1460
+ message: '`mt_rand()` / `rand()` output is assigned to a variable whose name indicates security-sensitive use (token, secret,
1461
+ password, otp, session, nonce, reset code, csrf). Both are Mersenne-Twister-based and not cryptographically secure - their
1462
+ output is predictable once a few samples are observed. Use `random_bytes()` or `random_int()`, which are CSPRNG-backed.
1463
+ CWE-338.'
1464
+ severity: WARNING
1465
+ languages:
1466
+ - php
1467
+ metadata:
1468
+ cwe:
1469
+ - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)'
1470
+ - 'CWE-330: Use of Insufficiently Random Values'
1471
+ owasp:
1472
+ - A02:2021 - Cryptographic Failures
1473
+ category: security
1474
+ subcategory:
1475
+ - audit
1476
+ technology:
1477
+ - php
1478
+ likelihood: MEDIUM
1479
+ impact: HIGH
1480
+ confidence: MEDIUM
1481
+ vulnerability_class:
1482
+ - Insufficient Entropy
1483
+ patterns:
1484
+ - pattern-either:
1485
+ - pattern: $TOKEN = mt_rand(...);
1486
+ - pattern: $TOKEN = rand(...);
1487
+ - metavariable-regex:
1488
+ metavariable: $TOKEN
1489
+ regex: (?i).*(token|secret|password|passwd|pwd|otp|session|nonce|reset|csrf).*
1490
+ - id: narvy.php.xss.echo-superglobal-unescaped.echo-superglobal-unescaped
1491
+ mode: taint
1492
+ message: User-controlled request data ($_GET/$_POST/$_REQUEST/$_COOKIE/ $_SERVER['HTTP_*']) reaches an `echo`/`print` output
1493
+ sink without passing through `htmlspecialchars()` / `htmlentities()`. The value is written into the HTML response verbatim;
1494
+ an attacker who controls it can inject `<script>` or event-handler markup (reflected XSS, CWE-79). Escape with `htmlspecialchars($X,
1495
+ ENT_QUOTES, 'UTF-8')` before output.
1496
+ severity: ERROR
1497
+ languages:
1498
+ - php
1499
+ metadata:
1500
+ cwe:
1501
+ - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site Scripting'')'
1502
+ owasp:
1503
+ - A03:2021 - Injection
1504
+ category: security
1505
+ subcategory:
1506
+ - vuln
1507
+ technology:
1508
+ - php
1509
+ likelihood: HIGH
1510
+ impact: MEDIUM
1511
+ confidence: MEDIUM
1512
+ vulnerability_class:
1513
+ - Cross-Site-Scripting (XSS)
1514
+ pattern-sources:
1515
+ - patterns:
1516
+ - pattern-either:
1517
+ - pattern: $_GET[...]
1518
+ - pattern: $_POST[...]
1519
+ - pattern: $_REQUEST[...]
1520
+ - pattern: $_COOKIE[...]
1521
+ pattern-sinks:
1522
+ - patterns:
1523
+ - pattern-either:
1524
+ - pattern: echo $X;
1525
+ - pattern: print $X;
1526
+ - pattern: printf($FMT, $X)
1527
+ pattern-sanitizers:
1528
+ - patterns:
1529
+ - pattern: htmlspecialchars($X, ...)
1530
+ - patterns:
1531
+ - pattern: htmlentities($X, ...)
1532
+ - patterns:
1533
+ - pattern: strip_tags($X, ...)
1534
+ - patterns:
1535
+ - pattern: (int)$X
1536
+ - patterns:
1537
+ - pattern: (float)$X
1538
+ - patterns:
1539
+ - pattern: esc_html($X)
1540
+ - patterns:
1541
+ - pattern: esc_html__($X, ...)
1542
+ - patterns:
1543
+ - pattern: esc_attr($X)
1544
+ - patterns:
1545
+ - pattern: esc_attr__($X, ...)
1546
+ - patterns:
1547
+ - pattern: esc_url($X)
1548
+ - patterns:
1549
+ - pattern: esc_url_raw($X)
1550
+ - patterns:
1551
+ - pattern: esc_js($X)
1552
+ - patterns:
1553
+ - pattern: esc_textarea($X)
1554
+ - patterns:
1555
+ - pattern: wp_kses($X, ...)
1556
+ - patterns:
1557
+ - pattern: wp_kses_post($X)
1558
+ - patterns:
1559
+ - pattern: sanitize_text_field($X)
1560
+ - patterns:
1561
+ - pattern: sanitize_email($X)
1562
+ - patterns:
1563
+ - pattern: sanitize_key($X)
1564
+ - patterns:
1565
+ - pattern: absint($X)
1566
+ - patterns:
1567
+ - pattern: intval($X, ...)
1568
+ - patterns:
1569
+ - pattern: wc_clean($X)
1570
+ - id: narvy.php.xss.blade-raw-echo-tainted.blade-raw-echo-tainted
1571
+ message: Laravel Blade's raw-output syntax `{!! $VAR !!}` skips the automatic HTML escaping that the regular `{{ $VAR }}`
1572
+ syntax applies. If `$VAR` carries request-derived or otherwise attacker-influenced data, this is stored/reflected XSS
1573
+ (CWE-79). Use `{{ $VAR }}` unless the value is already-sanitized trusted HTML (e.g. output of a markdown-to-HTML converter
1574
+ you control).
1575
+ severity: WARNING
1576
+ languages:
1577
+ - generic
1578
+ metadata:
1579
+ cwe:
1580
+ - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site Scripting'')'
1581
+ owasp:
1582
+ - A03:2021 - Injection
1583
+ category: security
1584
+ subcategory:
1585
+ - audit
1586
+ technology:
1587
+ - php
1588
+ - laravel
1589
+ - blade
1590
+ likelihood: LOW
1591
+ impact: HIGH
1592
+ confidence: LOW
1593
+ vulnerability_class:
1594
+ - Cross-Site-Scripting (XSS)
1595
+ paths:
1596
+ include:
1597
+ - '*.blade.php'
1598
+ patterns:
1599
+ - pattern: '{!! $VAR !!}'
1600
+ - pattern-not: '{!! __($X) !!}'
1601
+ - id: narvy.php.deserialization.unserialize-request-input.unserialize-request-input
1602
+ message: '`unserialize()` is called on data derived from $_GET/$_POST/ $_REQUEST/$_COOKIE. PHP object injection (CWE-502):
1603
+ if any class reachable from the deserialized graph implements a magic method (__wakeup, __destruct, __toString, ...),
1604
+ an attacker can craft a serialized payload that triggers a POP-chain gadget for RCE, file write, or SQL injection. Use
1605
+ `json_decode()` for untrusted data, or `unserialize($X, [''allowed_classes'' => false])` if PHP objects are unavoidable.'
1606
+ severity: ERROR
1607
+ languages:
1608
+ - php
1609
+ mode: taint
1610
+ metadata:
1611
+ cwe:
1612
+ - 'CWE-502: Deserialization of Untrusted Data'
1613
+ owasp:
1614
+ - A08:2021 - Software and Data Integrity Failures
1615
+ category: security
1616
+ subcategory:
1617
+ - vuln
1618
+ technology:
1619
+ - php
1620
+ likelihood: MEDIUM
1621
+ impact: HIGH
1622
+ confidence: HIGH
1623
+ vulnerability_class:
1624
+ - Insecure Deserialization
1625
+ references:
1626
+ - https://cwe.mitre.org/data/definitions/502.html
1627
+ - https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection
1628
+ paths:
1629
+ exclude:
1630
+ - '**/test/**'
1631
+ - '**/tests/**'
1632
+ pattern-sources:
1633
+ - pattern: $_GET[...]
1634
+ - pattern: $_POST[...]
1635
+ - pattern: $_REQUEST[...]
1636
+ - pattern: $_COOKIE[...]
1637
+ pattern-sanitizers:
1638
+ - pattern: json_decode(...)
1639
+ pattern-sinks:
1640
+ - patterns:
1641
+ - pattern-either:
1642
+ - pattern: unserialize($SINK)
1643
+ - pattern: unserialize($SINK, $OPTS)
1644
+ - pattern-not: unserialize($SINK, ['allowed_classes' => false])