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,1576 @@
1
+ # Java security rules, authored by Narvy.
2
+ # Injection, path traversal, XSS, LDAP and XPath, TLS, CSRF, CORS, weak crypto.
3
+
4
+ rules:
5
+ - id: narvy.java.cmdi.runtime-exec-concat.runtime-exec-concat
6
+ message: '`Runtime.getRuntime().exec(...)` is called with a command string built by `+` concatenation. When invoked with
7
+ a single string argument, the JVM itself performs a naive shell-style tokenisation and any tainted operand can inject
8
+ additional arguments or, on platforms that route through a shell, additional commands (CWE-78). Use the `exec(String[])`
9
+ overload with the executable and each argument as a separate array element, and validate the executable against an allow-list.'
10
+ severity: ERROR
11
+ languages:
12
+ - java
13
+ metadata:
14
+ category: security
15
+ cwe:
16
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
17
+ owasp:
18
+ - A03:2021 - Injection
19
+ subcategory:
20
+ - vuln
21
+ likelihood: HIGH
22
+ impact: HIGH
23
+ confidence: MEDIUM
24
+ technology:
25
+ - java
26
+ patterns:
27
+ - pattern-either:
28
+ - pattern: Runtime.getRuntime().exec($A + $B)
29
+ - pattern: $RT.exec($A + $B)
30
+ - pattern-not: Runtime.getRuntime().exec("..." + "...")
31
+ - pattern-not: $RT.exec("..." + "...")
32
+ - id: narvy.java.cmdi.processbuilder-shell-flag.processbuilder-shell-flag
33
+ message: '`ProcessBuilder` invokes a shell (`sh -c` / `bash -c` / `cmd.exe /c`) with a command string that is not a literal.
34
+ Even though `ProcessBuilder` normally avoids shell interpretation, explicitly re-introducing a shell via `-c`/`/c` hands
35
+ the tainted string to shell metacharacter expansion (`;`, `|`, `` ` ``, `$(...)`) (CWE-78). Invoke the target binary directly
36
+ with its arguments as separate array elements instead of going through a shell.'
37
+ severity: ERROR
38
+ languages:
39
+ - java
40
+ metadata:
41
+ category: security
42
+ cwe:
43
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
44
+ owasp:
45
+ - A03:2021 - Injection
46
+ subcategory:
47
+ - vuln
48
+ likelihood: MEDIUM
49
+ impact: HIGH
50
+ confidence: HIGH
51
+ technology:
52
+ - java
53
+ patterns:
54
+ - pattern-either:
55
+ - pattern: new ProcessBuilder("sh", "-c", $X)
56
+ - pattern: new ProcessBuilder("bash", "-c", $X)
57
+ - pattern: new ProcessBuilder("/bin/sh", "-c", $X)
58
+ - pattern: new ProcessBuilder("/bin/bash", "-c", $X)
59
+ - pattern: new ProcessBuilder("cmd.exe", "/c", $X)
60
+ - pattern: new ProcessBuilder("cmd", "/c", $X)
61
+ - pattern-not: new ProcessBuilder("sh", "-c", "...")
62
+ - pattern-not: new ProcessBuilder("bash", "-c", "...")
63
+ - pattern-not: new ProcessBuilder("/bin/sh", "-c", "...")
64
+ - pattern-not: new ProcessBuilder("/bin/bash", "-c", "...")
65
+ - pattern-not: new ProcessBuilder("cmd.exe", "/c", "...")
66
+ - pattern-not: new ProcessBuilder("cmd", "/c", "...")
67
+ - id: narvy.java.cmdi.tainted-request-param-to-exec.tainted-request-param-to-exec
68
+ message: 'A value read directly from the HTTP request reaches `Runtime.exec`/`ProcessBuilder` as (part of) the command to
69
+ execute, with no allow-list or escaping in between. This is a remote command injection path (CWE-78): an attacker who
70
+ controls the request can run arbitrary OS commands with the application''s privileges. Validate the value against a strict
71
+ allow-list before it reaches the process-spawning call, or avoid building the command from request data entirely.'
72
+ severity: ERROR
73
+ languages:
74
+ - java
75
+ metadata:
76
+ category: security
77
+ cwe:
78
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
79
+ owasp:
80
+ - A03:2021 - Injection
81
+ subcategory:
82
+ - vuln
83
+ likelihood: HIGH
84
+ impact: HIGH
85
+ confidence: HIGH
86
+ technology:
87
+ - java
88
+ mode: taint
89
+ pattern-sources:
90
+ - patterns:
91
+ - pattern-either:
92
+ - pattern: $REQ.getParameter(...)
93
+ - pattern: $REQ.getHeader(...)
94
+ pattern-sinks:
95
+ - patterns:
96
+ - pattern-either:
97
+ - pattern: Runtime.getRuntime().exec($SINK)
98
+ - pattern: Runtime.getRuntime().exec("..." + $SINK + "...")
99
+ - pattern: $RT.exec($SINK)
100
+ - pattern: new ProcessBuilder($SINK)
101
+ pattern-sanitizers:
102
+ - patterns:
103
+ - pattern: Integer.parseInt(...)
104
+ - id: narvy.java.crlf.tainted-response-header.tainted-response-header
105
+ message: A value read directly from the HTTP request is passed to `HttpServletResponse.setHeader`/`addHeader`/`sendRedirect`
106
+ with no newline stripping. A tainted value containing `\r\n` injects extra response headers or splits the response into
107
+ a second, attacker-defined one (HTTP response splitting, CWE-113); on Servlet containers that reject raw CR/LF in header
108
+ values automatically this degrades to a caught exception, but code should not rely on the container to do that validation.
109
+ Strip/reject `\r` and `\n` from the value before using it as a header.
110
+ severity: WARNING
111
+ languages:
112
+ - java
113
+ metadata:
114
+ category: security
115
+ cwe:
116
+ - 'CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers (''HTTP Response Splitting'')'
117
+ owasp:
118
+ - A03:2021 - Injection
119
+ subcategory:
120
+ - vuln
121
+ likelihood: LOW
122
+ impact: MEDIUM
123
+ confidence: MEDIUM
124
+ technology:
125
+ - java
126
+ mode: taint
127
+ pattern-sources:
128
+ - patterns:
129
+ - pattern-either:
130
+ - pattern: $REQ.getParameter(...)
131
+ - pattern: $REQ.getHeader(...)
132
+ pattern-sinks:
133
+ - patterns:
134
+ - pattern-either:
135
+ - pattern: $RESP.setHeader($NAME, $SINK)
136
+ - pattern: $RESP.addHeader($NAME, $SINK)
137
+ - pattern: $RESP.sendRedirect($SINK)
138
+ pattern-sanitizers:
139
+ - patterns:
140
+ - pattern: $X.replaceAll(...)
141
+ - patterns:
142
+ - pattern: URLEncoder.encode(...)
143
+ - id: narvy.java.log-injection.tainted-request-param-in-log.tainted-request-param-in-log
144
+ message: A value read directly from the HTTP request is written into a log statement with no newline neutralisation. An
145
+ attacker can embed `\r\n` plus a fabricated log line to forge audit entries, or embed a payload that a downstream log
146
+ viewer renders as HTML/JS if it does not escape (CWE-117). Strip/replace `\r`/`\n` before logging user-controlled values,
147
+ or use a logging framework's structured/parameterised logging so the value is never spliced into the raw log line.
148
+ severity: WARNING
149
+ languages:
150
+ - java
151
+ metadata:
152
+ category: security
153
+ cwe:
154
+ - 'CWE-117: Improper Output Neutralization for Logs'
155
+ owasp:
156
+ - A09:2021 - Security Logging and Monitoring Failures
157
+ subcategory:
158
+ - audit
159
+ likelihood: LOW
160
+ impact: LOW
161
+ confidence: LOW
162
+ technology:
163
+ - java
164
+ mode: taint
165
+ pattern-sources:
166
+ - patterns:
167
+ - pattern-either:
168
+ - pattern: $REQ.getParameter(...)
169
+ - pattern: $REQ.getHeader(...)
170
+ pattern-sinks:
171
+ - patterns:
172
+ - pattern-either:
173
+ - pattern: logger.info("..." + $SINK + "...")
174
+ - pattern: logger.warn("..." + $SINK + "...")
175
+ - pattern: logger.error("..." + $SINK + "...")
176
+ - pattern: log.info("..." + $SINK + "...")
177
+ - pattern: log.warn("..." + $SINK + "...")
178
+ - pattern: log.error("..." + $SINK + "...")
179
+ pattern-sanitizers:
180
+ - patterns:
181
+ - pattern: $X.replaceAll(...)
182
+ - id: narvy.java.ldapi.tainted-search-filter.tainted-search-filter
183
+ message: An LDAP search filter is built by concatenating a value read from the HTTP request into the filter string passed
184
+ to `DirContext.search(...)`/`InitialDirContext`. An attacker can inject filter metacharacters (`*`, `)`, `(`, `|`, `&`)
185
+ to alter the query logic (bypass an authentication check, enumerate directory entries) (CWE-90). Escape the value with
186
+ `javax.naming.ldap` filter-escaping rules (escape `\`, `*`, `(`, `)`, NUL) before splicing it into the filter string,
187
+ or build the filter with a library that parameterises LDAP queries.
188
+ severity: ERROR
189
+ languages:
190
+ - java
191
+ metadata:
192
+ category: security
193
+ cwe:
194
+ - 'CWE-90: Improper Neutralization of Special Elements used in an LDAP Query (''LDAP Injection'')'
195
+ owasp:
196
+ - A03:2021 - Injection
197
+ subcategory:
198
+ - vuln
199
+ likelihood: LOW
200
+ impact: HIGH
201
+ confidence: MEDIUM
202
+ technology:
203
+ - java
204
+ mode: taint
205
+ pattern-sources:
206
+ - patterns:
207
+ - pattern-either:
208
+ - pattern: $REQ.getParameter(...)
209
+ - pattern: $REQ.getHeader(...)
210
+ pattern-sinks:
211
+ - patterns:
212
+ - pattern-either:
213
+ - pattern: $CTX.search("..." + $SINK + "...", ...)
214
+ - pattern: $CTX.search($SINK, ...)
215
+ pattern-sanitizers:
216
+ - patterns:
217
+ - pattern: $X.replace(...)
218
+ - id: narvy.java.xpathi.tainted-xpath-expression.tainted-xpath-expression
219
+ message: An XPath expression is built by concatenating a value read from the HTTP request into the expression string passed
220
+ to `XPath.evaluate(...)` / `XPath.compile(...)`. An attacker can inject XPath syntax to bypass a login check or extract
221
+ arbitrary nodes from the document (CWE-643). Use `XPath.setXPathVariableResolver(...)` with a bound variable instead of
222
+ concatenating the tainted value into the expression text.
223
+ severity: ERROR
224
+ languages:
225
+ - java
226
+ metadata:
227
+ category: security
228
+ cwe:
229
+ - 'CWE-643: Improper Neutralization of Data within XPath Expressions (''XPath Injection'')'
230
+ owasp:
231
+ - A03:2021 - Injection
232
+ subcategory:
233
+ - vuln
234
+ likelihood: LOW
235
+ impact: HIGH
236
+ confidence: MEDIUM
237
+ technology:
238
+ - java
239
+ mode: taint
240
+ pattern-sources:
241
+ - patterns:
242
+ - pattern-either:
243
+ - pattern: $REQ.getParameter(...)
244
+ - pattern: $REQ.getHeader(...)
245
+ pattern-sinks:
246
+ - patterns:
247
+ - pattern-either:
248
+ - pattern: $XP.evaluate("..." + $SINK + "...", ...)
249
+ - pattern: $XP.compile("..." + $SINK + "...")
250
+ - id: narvy.java.session.tainted-session-attribute-key.tainted-session-attribute-key
251
+ message: 'A value read directly from the HTTP request is used as the SESSION ID (`request.getSession(...)` chained off a
252
+ request-derived value, or a manual session-id cookie set from a request parameter) rather than letting the container generate
253
+ one. Accepting an attacker-supplied session identifier is session fixation: the attacker sets a known ID, waits for the
254
+ victim to authenticate under it, and reuses the same ID to hijack the now-authenticated session (CWE-384). Never accept
255
+ a client-supplied value as the session identifier; regenerate the session ID on privilege change (login) with `request.changeSessionId()`.'
256
+ severity: WARNING
257
+ languages:
258
+ - java
259
+ metadata:
260
+ category: security
261
+ cwe:
262
+ - 'CWE-384: Session Fixation'
263
+ owasp:
264
+ - A07:2021 - Identification and Authentication Failures
265
+ subcategory:
266
+ - vuln
267
+ likelihood: LOW
268
+ impact: HIGH
269
+ confidence: LOW
270
+ technology:
271
+ - java
272
+ patterns:
273
+ - pattern-either:
274
+ - pattern: new Cookie("JSESSIONID", $REQ.getParameter(...))
275
+ - pattern: new Cookie("sessionid", $REQ.getParameter(...))
276
+ - pattern: $RESP.addCookie(new Cookie("JSESSIONID", $X))
277
+ - id: narvy.java.ssrf.tainted-request-url-host.tainted-request-url-host
278
+ message: A value read directly from the HTTP request is used as (or to build) the full target URL/host for an outbound HTTP
279
+ call (`RestTemplate`, `HttpClient`, `URL`/`URLConnection`). An attacker can point the request at an internal-only service
280
+ (metadata endpoint, admin panel, database admin UI) that is not reachable directly from outside the network - a server-side
281
+ request forgery (CWE-918). Validate the target against an allow-list of expected hosts/schemes before making the request,
282
+ and block requests to loopback/link-local/private ranges.
283
+ severity: ERROR
284
+ languages:
285
+ - java
286
+ metadata:
287
+ category: security
288
+ cwe:
289
+ - 'CWE-918: Server-Side Request Forgery (SSRF)'
290
+ owasp:
291
+ - A10:2021 - Server-Side Request Forgery (SSRF)
292
+ subcategory:
293
+ - vuln
294
+ likelihood: MEDIUM
295
+ impact: HIGH
296
+ confidence: MEDIUM
297
+ technology:
298
+ - java
299
+ mode: taint
300
+ pattern-sources:
301
+ - patterns:
302
+ - pattern-either:
303
+ - pattern: $REQ.getParameter(...)
304
+ - pattern: $REQ.getHeader(...)
305
+ - patterns:
306
+ - pattern-either:
307
+ - pattern-inside: |
308
+ $METHOD(..., @$ANNO(...) $TYPE $SRC, ...) {
309
+ ...
310
+ }
311
+ - pattern-inside: |
312
+ $METHOD(..., @$ANNO $TYPE $SRC, ...) {
313
+ ...
314
+ }
315
+ - metavariable-regex:
316
+ metavariable: $ANNO
317
+ regex: (RequestParam|PathVariable|RequestHeader)
318
+ - focus-metavariable: $SRC
319
+ pattern-sanitizers:
320
+ - patterns:
321
+ - pattern: '"..." + $SAFE'
322
+ - focus-metavariable: $SAFE
323
+ pattern-sinks:
324
+ - patterns:
325
+ - pattern-either:
326
+ - pattern: $RT.getForObject($SINK, ...)
327
+ - pattern: $RT.postForObject($SINK, ...)
328
+ - pattern: $RT.exchange($SINK, ...)
329
+ - pattern: new URL($SINK).openConnection()
330
+ - pattern: new URL($SINK).openStream()
331
+ - id: narvy.java.reflection.tainted-classfor-name.tainted-classfor-name
332
+ message: '`Class.forName(...)` (or `getMethod`/`getDeclaredMethod`) is invoked with a class or method name that traces back
333
+ to HTTP request data. An attacker who controls the class/method name can instantiate or invoke an arbitrary class already
334
+ on the classpath - useful both as an RCE gadget and as a way to bypass an intended allow-list of operations (CWE-470).
335
+ Validate the name against an explicit allow-list before passing it to reflective APIs; never resolve a class/method purely
336
+ from request input.'
337
+ severity: WARNING
338
+ languages:
339
+ - java
340
+ metadata:
341
+ category: security
342
+ cwe:
343
+ - 'CWE-470: Use of Externally-Controlled Input to Select Classes or Code (''Unsafe Reflection'')'
344
+ owasp:
345
+ - A03:2021 - Injection
346
+ subcategory:
347
+ - vuln
348
+ likelihood: LOW
349
+ impact: HIGH
350
+ confidence: LOW
351
+ technology:
352
+ - java
353
+ mode: taint
354
+ pattern-sources:
355
+ - patterns:
356
+ - pattern-either:
357
+ - pattern: $REQ.getParameter(...)
358
+ - pattern: $REQ.getHeader(...)
359
+ pattern-sinks:
360
+ - patterns:
361
+ - pattern-either:
362
+ - pattern: Class.forName($SINK)
363
+ - pattern: $CLS.getMethod($SINK, ...)
364
+ - pattern: $CLS.getDeclaredMethod($SINK, ...)
365
+ - id: narvy.java.cookie.sensitive-cookie-flags-explicitly-false.sensitive-cookie-flags-explicitly-false
366
+ message: A `Cookie` explicitly disables `HttpOnly` or `Secure` (`setHttpOnly(false)` / `setSecure(false)`). `HttpOnly` blocks
367
+ JavaScript from reading the cookie (mitigates session-token theft via XSS); `Secure` stops the browser sending it over
368
+ plaintext HTTP (CWE-1004, CWE-614). Only disable either flag if there is a specific, documented reason (e.g. a legacy
369
+ HTTP-only integration) - otherwise set both to `true`.
370
+ severity: WARNING
371
+ languages:
372
+ - java
373
+ metadata:
374
+ category: security
375
+ cwe:
376
+ - 'CWE-1004: Sensitive Cookie Without ''HttpOnly'' Flag'
377
+ - 'CWE-614: Sensitive Cookie in HTTPS Session Without ''Secure'' Attribute'
378
+ owasp:
379
+ - A05:2021 - Security Misconfiguration
380
+ subcategory:
381
+ - vuln
382
+ likelihood: LOW
383
+ impact: MEDIUM
384
+ confidence: HIGH
385
+ technology:
386
+ - java
387
+ patterns:
388
+ - pattern-either:
389
+ - pattern: $C.setHttpOnly(false)
390
+ - pattern: $C.setSecure(false)
391
+ - id: narvy.java.mass-assignment.spring-bean-untyped-request-body.spring-bean-untyped-request-body
392
+ message: A Spring MVC handler binds an incoming `@RequestBody`/form-backed object directly to a JPA entity (rather than
393
+ a dedicated DTO) and persists it without an explicit allow-list of settable fields. If the entity has a field the client
394
+ should never control (`role`, `isAdmin`, `balance`, `ownerId`), the attacker can set it just by adding the JSON key -
395
+ mass assignment (CWE-915). Bind to a request-scoped DTO that only exposes the fields the client is meant to set, and map
396
+ it onto the entity explicitly.
397
+ severity: WARNING
398
+ languages:
399
+ - java
400
+ metadata:
401
+ category: security
402
+ cwe:
403
+ - 'CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes'
404
+ owasp:
405
+ - A08:2021 - Software and Data Integrity Failures
406
+ subcategory:
407
+ - audit
408
+ likelihood: LOW
409
+ impact: MEDIUM
410
+ confidence: LOW
411
+ technology:
412
+ - java
413
+ - spring
414
+ patterns:
415
+ - pattern-either:
416
+ - pattern: "@PostMapping(...)\npublic $RET $HANDLER(@RequestBody $ENTITY $BODY, ...) {\n ...\n $REPO.save($BODY);\n\
417
+ \ ...\n}\n"
418
+ - metavariable-pattern:
419
+ metavariable: $ENTITY
420
+ patterns:
421
+ - pattern-either:
422
+ - pattern-regex: .*Entity$
423
+ - id: narvy.java.open-redirect.tainted-sendredirect.tainted-sendredirect
424
+ message: '`HttpServletResponse.sendRedirect(...)` is called with a value read directly from the HTTP request. An attacker
425
+ can craft a link to the trusted site that redirects the victim''s browser to an arbitrary external URL - useful for phishing
426
+ and OAuth token theft (CWE-601). Validate the target against an allow-list of known-good paths/hosts, or only permit relative
427
+ paths within the application.'
428
+ severity: WARNING
429
+ languages:
430
+ - java
431
+ metadata:
432
+ category: security
433
+ cwe:
434
+ - 'CWE-601: URL Redirection to Untrusted Site (''Open Redirect'')'
435
+ owasp:
436
+ - A01:2021 - Broken Access Control
437
+ subcategory:
438
+ - vuln
439
+ likelihood: MEDIUM
440
+ impact: LOW
441
+ confidence: MEDIUM
442
+ technology:
443
+ - java
444
+ mode: taint
445
+ pattern-sources:
446
+ - patterns:
447
+ - pattern-either:
448
+ - pattern: $REQ.getParameter(...)
449
+ - pattern: $REQ.getHeader(...)
450
+ pattern-sinks:
451
+ - patterns:
452
+ - pattern-either:
453
+ - pattern: $RESP.sendRedirect($SINK)
454
+ - pattern: $RESP.sendRedirect("..." + $SINK)
455
+ - pattern: $RESP.setHeader("Location", $SINK)
456
+ - id: narvy.java.open-redirect.spring-redirect-prefix-tainted.spring-redirect-prefix-tainted
457
+ message: A Spring MVC handler builds a `"redirect:" + ...` view name from a `@RequestParam`/`@PathVariable` value. Spring
458
+ resolves that string as an HTTP redirect target; an attacker-controlled value can send the victim to an arbitrary external
459
+ site (CWE-601). Validate the target against an allow-list, or restrict it to a known set of internal view names.
460
+ severity: WARNING
461
+ languages:
462
+ - java
463
+ metadata:
464
+ category: security
465
+ cwe:
466
+ - 'CWE-601: URL Redirection to Untrusted Site (''Open Redirect'')'
467
+ owasp:
468
+ - A01:2021 - Broken Access Control
469
+ subcategory:
470
+ - vuln
471
+ likelihood: MEDIUM
472
+ impact: LOW
473
+ confidence: MEDIUM
474
+ technology:
475
+ - java
476
+ - spring
477
+ patterns:
478
+ - pattern-either:
479
+ - pattern: '"redirect:" + $PARAM'
480
+ - pattern: new RedirectView($PARAM)
481
+ - pattern-not: '"redirect:" + "..."'
482
+ - id: narvy.java.pathtraversal.tainted-request-param-to-file.tainted-request-param-to-file
483
+ message: A value read directly from the HTTP request (`getParameter`, `getHeader`, `getPathInfo`) is used to build a `File`/file
484
+ stream without validating that the resolved path stays inside the intended directory. A value containing `../` segments
485
+ (or an absolute path) lets an attacker read or write files outside the intended directory (CWE-22). Resolve the path,
486
+ canonicalise it, and verify with `startsWith(...)` that it stays inside the allowed base directory before use.
487
+ severity: ERROR
488
+ languages:
489
+ - java
490
+ metadata:
491
+ category: security
492
+ cwe:
493
+ - 'CWE-22: Improper Limitation of a Pathname to a Restricted Directory (''Path Traversal'')'
494
+ owasp:
495
+ - A01:2021 - Broken Access Control
496
+ subcategory:
497
+ - vuln
498
+ likelihood: MEDIUM
499
+ impact: HIGH
500
+ confidence: MEDIUM
501
+ technology:
502
+ - java
503
+ mode: taint
504
+ pattern-sources:
505
+ - patterns:
506
+ - pattern-either:
507
+ - pattern: $REQ.getParameter(...)
508
+ - pattern: $REQ.getHeader(...)
509
+ - pattern: $REQ.getPathInfo()
510
+ pattern-sinks:
511
+ - patterns:
512
+ - pattern-either:
513
+ - pattern: new File($BASE, $SINK)
514
+ - pattern: new File($SINK)
515
+ - pattern: new FileInputStream($SINK)
516
+ - pattern: new FileOutputStream($SINK)
517
+ - pattern: Files.newInputStream(Paths.get($SINK))
518
+ - pattern: Files.newOutputStream(Paths.get($SINK))
519
+ - pattern: Paths.get($BASE, $SINK)
520
+ pattern-sanitizers:
521
+ - patterns:
522
+ - pattern: $P.normalize()
523
+ - patterns:
524
+ - pattern: $P.toRealPath()
525
+ - patterns:
526
+ - pattern: FilenameUtils.getName(...)
527
+ - id: narvy.java.pathtraversal.jaxrs-pathparam-to-file.jaxrs-pathparam-to-file
528
+ message: 'A JAX-RS `@PathParam`/`@QueryParam` value flows into a `File`/`Path` constructor with no canonicalisation or allow-list
529
+ check. Same risk as the Servlet case: a `../` segment escapes the intended base directory (CWE-22). Canonicalise the resolved
530
+ path and verify it stays under the expected base directory before opening it.'
531
+ severity: WARNING
532
+ languages:
533
+ - java
534
+ metadata:
535
+ category: security
536
+ cwe:
537
+ - 'CWE-22: Improper Limitation of a Pathname to a Restricted Directory (''Path Traversal'')'
538
+ owasp:
539
+ - A01:2021 - Broken Access Control
540
+ subcategory:
541
+ - vuln
542
+ likelihood: LOW
543
+ impact: HIGH
544
+ confidence: LOW
545
+ technology:
546
+ - java
547
+ patterns:
548
+ - pattern-either:
549
+ - pattern: "public $RET $METHOD(@PathParam(...) $T $NAME, ...) {\n ...\n new File($BASE, $NAME);\n ...\n}\n"
550
+ - pattern: "public $RET $METHOD(@QueryParam(...) $T $NAME, ...) {\n ...\n new File($BASE, $NAME);\n ...\n}\n"
551
+ - id: narvy.java.pathtraversal.zip-entry-no-canonical-check.zip-entry-no-canonical-check
552
+ message: A `ZipInputStream`/`ZipFile` entry name is used to build an output `File` path with no check that the resulting
553
+ path stays inside the destination directory. A crafted archive entry named `../../evil.sh` (a "Zip Slip") writes outside
554
+ the intended extraction directory (CWE-22). Resolve the entry path against the destination directory, canonicalise it,
555
+ and reject any entry whose resolved path escapes that directory.
556
+ severity: ERROR
557
+ languages:
558
+ - java
559
+ metadata:
560
+ category: security
561
+ cwe:
562
+ - 'CWE-22: Improper Limitation of a Pathname to a Restricted Directory (''Path Traversal'')'
563
+ owasp:
564
+ - A01:2021 - Broken Access Control
565
+ subcategory:
566
+ - vuln
567
+ likelihood: MEDIUM
568
+ impact: HIGH
569
+ confidence: MEDIUM
570
+ technology:
571
+ - java
572
+ patterns:
573
+ - pattern-either:
574
+ - pattern: '$ENTRY = $ZIS.getNextEntry();
575
+
576
+ ...
577
+
578
+ $OUT = new File($DESTDIR, $ENTRY.getName());
579
+
580
+ ...
581
+
582
+ '
583
+ - pattern: '$NAME = $ENTRY.getName();
584
+
585
+ ...
586
+
587
+ $OUT = new File($DESTDIR, $NAME);
588
+
589
+ ...
590
+
591
+ '
592
+ - pattern-not: '$ENTRY = $ZIS.getNextEntry();
593
+
594
+ ...
595
+
596
+ $OUT = new File($DESTDIR, $ENTRY.getName());
597
+
598
+ ...
599
+
600
+ if (!$OUT.getCanonicalPath().startsWith(...)) { ... }
601
+
602
+ ...
603
+
604
+ '
605
+ - id: narvy.java.crypto.plaintext-socket-construction.plaintext-socket-construction
606
+ message: A plain `java.net.Socket`/`java.net.ServerSocket` is constructed directly. Everything sent or received on it travels
607
+ unencrypted, so anyone who can observe the network path can read or tamper with the traffic (CWE-319). This is an audit-level
608
+ flag, not a proven bug - a loopback-only or already-tunnelled connection is fine as-is, but if this socket carries credentials,
609
+ tokens, or other sensitive data over a network that is not otherwise trusted, wrap it with `SSLSocketFactory` / `SSLServerSocketFactory`
610
+ (or an equivalent TLS-terminating client) instead of the bare constructor.
611
+ severity: WARNING
612
+ languages:
613
+ - java
614
+ metadata:
615
+ category: security
616
+ cwe:
617
+ - 'CWE-319: Cleartext Transmission of Sensitive Information'
618
+ owasp:
619
+ - A02:2021 - Cryptographic Failures
620
+ subcategory:
621
+ - audit
622
+ likelihood: MEDIUM
623
+ impact: MEDIUM
624
+ confidence: MEDIUM
625
+ technology:
626
+ - java
627
+ patterns:
628
+ - pattern-either:
629
+ - pattern: new Socket(...)
630
+ - pattern: new ServerSocket(...)
631
+ - id: narvy.java.sqli.sprintf-var-to-jdbc-statement.sprintf-var-to-jdbc-statement
632
+ message: A SQL string built with `String.format(...)` (with real substitution arguments, not just a literal) is assigned
633
+ to a variable that later reaches a plain JDBC `Statement`/`PreparedStatement` call. `String.format` does not escape SQL
634
+ metacharacters, so if any of the substituted values is not fully trusted, this is a SQL injection (CWE-89). Build the
635
+ query text as a fixed literal and bind the dynamic parts with `?` placeholders and `setString`/`setInt`/etc instead of
636
+ formatting them into the text.
637
+ severity: WARNING
638
+ languages:
639
+ - java
640
+ metadata:
641
+ category: security
642
+ cwe:
643
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
644
+ owasp:
645
+ - A03:2021 - Injection
646
+ subcategory:
647
+ - audit
648
+ likelihood: MEDIUM
649
+ impact: HIGH
650
+ confidence: MEDIUM
651
+ technology:
652
+ - java
653
+ patterns:
654
+ - pattern-either:
655
+ - patterns:
656
+ - pattern: '$Q = String.format(...);
657
+
658
+ ...
659
+
660
+ $STMT.executeQuery($Q);
661
+
662
+ '
663
+ - pattern-not: '$Q = String.format("...");
664
+
665
+ ...
666
+
667
+ $STMT.executeQuery($Q);
668
+
669
+ '
670
+ - patterns:
671
+ - pattern: '$Q = String.format(...);
672
+
673
+ ...
674
+
675
+ $STMT.executeUpdate($Q);
676
+
677
+ '
678
+ - pattern-not: '$Q = String.format("...");
679
+
680
+ ...
681
+
682
+ $STMT.executeUpdate($Q);
683
+
684
+ '
685
+ - patterns:
686
+ - pattern: '$Q = String.format(...);
687
+
688
+ ...
689
+
690
+ $STMT.execute($Q);
691
+
692
+ '
693
+ - pattern-not: '$Q = String.format("...");
694
+
695
+ ...
696
+
697
+ $STMT.execute($Q);
698
+
699
+ '
700
+ - patterns:
701
+ - pattern: '$Q = String.format(...);
702
+
703
+ ...
704
+
705
+ $CONN.prepareStatement($Q);
706
+
707
+ ...
708
+
709
+ $P.$EXECFUNC(...);
710
+
711
+ '
712
+ - pattern-not: '$Q = String.format("...");
713
+
714
+ ...
715
+
716
+ $CONN.prepareStatement($Q);
717
+
718
+ ...
719
+
720
+ $P.$EXECFUNC(...);
721
+
722
+ '
723
+ - metavariable-regex:
724
+ metavariable: $EXECFUNC
725
+ regex: (?i)^execute
726
+ - id: narvy.java.sqli.plus-var-to-jdbc-statement.plus-var-to-jdbc-statement
727
+ message: A SQL string is built with `+` concatenation, assigned to a variable, then that variable is later passed to a JDBC
728
+ `Statement.execute*` call. This is the same defect `Statement`/`+`-inline concatenation already covers, but reached through
729
+ a separate assignment instead of the concatenation sitting directly in the call argument - splitting it across two statements
730
+ does not change the risk (CWE-89). Use a `PreparedStatement` with `?` placeholders instead of assembling the query text
731
+ yourself.
732
+ severity: WARNING
733
+ languages:
734
+ - java
735
+ metadata:
736
+ category: security
737
+ cwe:
738
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
739
+ owasp:
740
+ - A03:2021 - Injection
741
+ subcategory:
742
+ - audit
743
+ likelihood: MEDIUM
744
+ impact: HIGH
745
+ confidence: MEDIUM
746
+ technology:
747
+ - java
748
+ patterns:
749
+ - pattern-either:
750
+ - patterns:
751
+ - pattern: '$Q = $A + $B;
752
+
753
+ ...
754
+
755
+ $STMT.executeQuery($Q);
756
+
757
+ '
758
+ - pattern-not: '$Q = "..." + "...";
759
+
760
+ ...
761
+
762
+ $STMT.executeQuery($Q);
763
+
764
+ '
765
+ - patterns:
766
+ - pattern: '$Q = $A + $B;
767
+
768
+ ...
769
+
770
+ $STMT.executeUpdate($Q);
771
+
772
+ '
773
+ - pattern-not: '$Q = "..." + "...";
774
+
775
+ ...
776
+
777
+ $STMT.executeUpdate($Q);
778
+
779
+ '
780
+ - patterns:
781
+ - pattern: '$Q = $A + $B;
782
+
783
+ ...
784
+
785
+ $STMT.execute($Q);
786
+
787
+ '
788
+ - pattern-not: '$Q = "..." + "...";
789
+
790
+ ...
791
+
792
+ $STMT.execute($Q);
793
+
794
+ '
795
+ - id: narvy.java.sqli.stringbuilder-query-to-jdbc-statement.stringbuilder-query-to-jdbc-statement
796
+ message: A SQL query string is assembled across several `StringBuilder.append(...)` calls, with at least one appended value
797
+ that is not a string literal (a table name, column list, WHERE fragment, or similar coming from a variable), and the resulting
798
+ text reaches a JDBC `Statement` or `PreparedStatement` execute call once `.toString()`'d. Even when the surrounding code
799
+ later binds `?` placeholders for values, splicing identifiers or query fragments into the text this way is still SQL injection
800
+ risk for whatever produced that fragment (CWE-89). Prefer a fixed literal query text; if a piece of the query genuinely
801
+ has to vary (table/column name), validate it against an allow-list before splicing it in, since JDBC has no bind-parameter
802
+ syntax for identifiers.
803
+ severity: WARNING
804
+ languages:
805
+ - java
806
+ metadata:
807
+ category: security
808
+ cwe:
809
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
810
+ owasp:
811
+ - A03:2021 - Injection
812
+ subcategory:
813
+ - audit
814
+ likelihood: MEDIUM
815
+ impact: MEDIUM
816
+ confidence: MEDIUM
817
+ technology:
818
+ - java
819
+ patterns:
820
+ - pattern-either:
821
+ - patterns:
822
+ - pattern: '$SB = new StringBuilder(...);
823
+
824
+ ...
825
+
826
+ $SB.append($ARG);
827
+
828
+ ...
829
+
830
+ $Q = $SB.toString();
831
+
832
+ ...
833
+
834
+ $P = $CONN.prepareStatement($Q);
835
+
836
+ ...
837
+
838
+ $P.$EXECFUNC(...);
839
+
840
+ '
841
+ - metavariable-regex:
842
+ metavariable: $EXECFUNC
843
+ regex: (?i)^execute
844
+ - metavariable-pattern:
845
+ metavariable: $ARG
846
+ patterns:
847
+ - pattern-not: '"..."'
848
+ - patterns:
849
+ - pattern: '$SB = new StringBuilder(...);
850
+
851
+ ...
852
+
853
+ $SB.append($ARG);
854
+
855
+ ...
856
+
857
+ $Q = $SB.toString();
858
+
859
+ ...
860
+
861
+ $STMT.$EXECFUNC($Q);
862
+
863
+ '
864
+ - metavariable-regex:
865
+ metavariable: $EXECFUNC
866
+ regex: (?i)^execute
867
+ - metavariable-pattern:
868
+ metavariable: $ARG
869
+ patterns:
870
+ - pattern-not: '"..."'
871
+ - id: narvy.java.sqli.jdbc-statement-concat.jdbc-statement-concat
872
+ message: A plain JDBC `Statement` executes a query string built with `+` concatenation. `Statement` never parameterises,
873
+ so any tainted value reaching the concatenation is a direct SQL injection (CWE-89). Switch to `PreparedStatement` with
874
+ `?` placeholders and `setString`/`setInt`/etc.
875
+ severity: ERROR
876
+ languages:
877
+ - java
878
+ metadata:
879
+ category: security
880
+ cwe:
881
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
882
+ owasp:
883
+ - A03:2021 - Injection
884
+ subcategory:
885
+ - vuln
886
+ likelihood: HIGH
887
+ impact: HIGH
888
+ confidence: MEDIUM
889
+ technology:
890
+ - java
891
+ patterns:
892
+ - pattern-either:
893
+ - pattern: $STMT.executeQuery($A + $B)
894
+ - pattern: $STMT.executeUpdate($A + $B)
895
+ - pattern: $STMT.execute($A + $B)
896
+ - pattern-not: $STMT.executeQuery("..." + "...")
897
+ - pattern-not: $STMT.executeUpdate("..." + "...")
898
+ - pattern-not: $STMT.execute("..." + "...")
899
+ - id: narvy.java.sqli.jdbc-connection-createquery-concat.jdbc-connection-createquery-concat
900
+ message: '`Connection.prepareStatement(...)` is called with a SQL string built by `+` concatenation. Building the query
901
+ text via concatenation defeats the protection `PreparedStatement` exists to provide, because the tainted value is already
902
+ part of the parsed SQL grammar by the time the driver sees it (CWE-89). Keep the query text a fixed literal and bind values
903
+ with `?` + `setString`/`setInt`.'
904
+ severity: ERROR
905
+ languages:
906
+ - java
907
+ metadata:
908
+ category: security
909
+ cwe:
910
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
911
+ owasp:
912
+ - A03:2021 - Injection
913
+ subcategory:
914
+ - vuln
915
+ likelihood: HIGH
916
+ impact: HIGH
917
+ confidence: MEDIUM
918
+ technology:
919
+ - java
920
+ patterns:
921
+ - pattern-either:
922
+ - pattern: $CONN.prepareStatement($A + $B)
923
+ - pattern: $CONN.prepareStatement($A + $B, ...)
924
+ - pattern-not: $CONN.prepareStatement("..." + "...")
925
+ - pattern-not: $CONN.prepareStatement("..." + "...", ...)
926
+ - id: narvy.java.sqli.jdbctemplate-concat.jdbctemplate-concat
927
+ message: Spring `JdbcTemplate` is called with a SQL string built by `+` concatenation instead of the `?` placeholder + args
928
+ form. `JdbcTemplate` only protects arguments passed through its own varargs binder; splicing a value into the SQL text
929
+ bypasses that entirely (CWE-89). Use `jdbcTemplate.query("... WHERE id = ?", rowMapper, id)`.
930
+ severity: ERROR
931
+ languages:
932
+ - java
933
+ metadata:
934
+ category: security
935
+ cwe:
936
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
937
+ owasp:
938
+ - A03:2021 - Injection
939
+ subcategory:
940
+ - vuln
941
+ likelihood: HIGH
942
+ impact: HIGH
943
+ confidence: MEDIUM
944
+ technology:
945
+ - java
946
+ - spring
947
+ patterns:
948
+ - pattern-either:
949
+ - pattern: $JT.query($A + $B, ...)
950
+ - pattern: $JT.queryForObject($A + $B, ...)
951
+ - pattern: $JT.queryForList($A + $B, ...)
952
+ - pattern: $JT.update($A + $B, ...)
953
+ - pattern: $JT.execute($A + $B)
954
+ - pattern-not: $JT.query("..." + "...", ...)
955
+ - pattern-not: $JT.queryForObject("..." + "...", ...)
956
+ - pattern-not: $JT.queryForList("..." + "...", ...)
957
+ - pattern-not: $JT.update("..." + "...", ...)
958
+ - pattern-not: $JT.execute("..." + "...")
959
+ - id: narvy.java.sqli.tainted-request-param-to-statement.tainted-request-param-to-statement
960
+ message: A value read directly from the HTTP request (`getParameter`, `getHeader`, `getQueryString`) reaches a `Statement`/`PreparedStatement`
961
+ SQL sink through a local variable, with no bind-parameter API in the call. Even when the sink call itself is a `PreparedStatement`,
962
+ if the tainted value ends up as part of the SQL text (versus a bound `?` argument) it is a SQL injection (CWE-89). Bind
963
+ the value with `setString`/`setInt`/etc; never build the SQL string from request data.
964
+ severity: WARNING
965
+ languages:
966
+ - java
967
+ metadata:
968
+ category: security
969
+ cwe:
970
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
971
+ owasp:
972
+ - A03:2021 - Injection
973
+ subcategory:
974
+ - vuln
975
+ likelihood: MEDIUM
976
+ impact: HIGH
977
+ confidence: MEDIUM
978
+ technology:
979
+ - java
980
+ mode: taint
981
+ pattern-sources:
982
+ - patterns:
983
+ - pattern-either:
984
+ - pattern: $REQ.getParameter(...)
985
+ - pattern: $REQ.getHeader(...)
986
+ - pattern: $REQ.getQueryString()
987
+ pattern-sinks:
988
+ - patterns:
989
+ - pattern-either:
990
+ - pattern: $STMT.executeQuery("..." + $SINK + "...")
991
+ - pattern: $STMT.executeQuery("..." + $SINK)
992
+ - pattern: $STMT.executeUpdate("..." + $SINK + "...")
993
+ - pattern: $STMT.execute("..." + $SINK + "...")
994
+ pattern-sanitizers:
995
+ - patterns:
996
+ - pattern: Integer.parseInt(...)
997
+ - patterns:
998
+ - pattern: Long.parseLong(...)
999
+ - id: narvy.java.tls.weak-sslcontext-protocol.weak-sslcontext-protocol
1000
+ message: '`SSLContext.getInstance(...)` is initialised with a deprecated/broken protocol name ("SSL", "SSLv2", "SSLv3",
1001
+ "SSLv2Hello", or the bare "TLS" alias, which on some JVMs still negotiates down to TLS 1.0). SSLv2/v3 have known practical
1002
+ breaks (POODLE, DROWN); TLS 1.0/1.1 are formally deprecated (CWE-326). Request `"TLSv1.3"` (or `"TLSv1.2"` at minimum)
1003
+ explicitly.'
1004
+ severity: WARNING
1005
+ languages:
1006
+ - java
1007
+ metadata:
1008
+ category: security
1009
+ cwe:
1010
+ - 'CWE-326: Inadequate Encryption Strength'
1011
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1012
+ owasp:
1013
+ - A02:2021 - Cryptographic Failures
1014
+ subcategory:
1015
+ - vuln
1016
+ likelihood: LOW
1017
+ impact: MEDIUM
1018
+ confidence: MEDIUM
1019
+ technology:
1020
+ - java
1021
+ patterns:
1022
+ - pattern-either:
1023
+ - pattern: SSLContext.getInstance("SSL")
1024
+ - pattern: SSLContext.getInstance("SSLv2")
1025
+ - pattern: SSLContext.getInstance("SSLv3")
1026
+ - pattern: SSLContext.getInstance("SSLv2Hello")
1027
+ - pattern: SSLContext.getInstance("TLS")
1028
+ - id: narvy.java.tls.trust-all-managers.trust-all-managers
1029
+ message: A custom `X509TrustManager` implements `checkServerTrusted`/ `checkClientTrusted` as a no-op (empty body, or a
1030
+ body that never throws). Installing it into an `SSLContext` disables certificate validation entirely - the connection
1031
+ accepts any certificate, including one presented by a man-in-the-middle (CWE-295). Use the platform default trust manager,
1032
+ or implement real chain/hostname validation if a custom trust store is genuinely required.
1033
+ severity: ERROR
1034
+ languages:
1035
+ - java
1036
+ metadata:
1037
+ category: security
1038
+ cwe:
1039
+ - 'CWE-295: Improper Certificate Validation'
1040
+ owasp:
1041
+ - A02:2021 - Cryptographic Failures
1042
+ subcategory:
1043
+ - vuln
1044
+ likelihood: LOW
1045
+ impact: HIGH
1046
+ confidence: MEDIUM
1047
+ technology:
1048
+ - java
1049
+ patterns:
1050
+ - pattern-either:
1051
+ - pattern: "new X509TrustManager() {\n public void checkServerTrusted(...) { }\n ...\n}\n"
1052
+ - pattern: "new X509TrustManager() {\n ...\n public void checkServerTrusted(...) { }\n}\n"
1053
+ - id: narvy.java.tls.hostnameverifier-always-true.hostnameverifier-always-true
1054
+ message: A `HostnameVerifier` (or `HttpsURLConnection.setDefaultHostnameVerifier`) implementation returns `true` unconditionally
1055
+ from `verify(...)`. This disables hostname validation on the TLS handshake - the connection accepts a certificate for
1056
+ ANY hostname, not just the one being connected to, which is a man-in-the-middle enabler (CWE-295). Use the default `HostnameVerifier`,
1057
+ or implement real hostname comparison against the certificate's SAN entries.
1058
+ severity: ERROR
1059
+ languages:
1060
+ - java
1061
+ metadata:
1062
+ category: security
1063
+ cwe:
1064
+ - 'CWE-295: Improper Certificate Validation'
1065
+ owasp:
1066
+ - A02:2021 - Cryptographic Failures
1067
+ subcategory:
1068
+ - vuln
1069
+ likelihood: LOW
1070
+ impact: HIGH
1071
+ confidence: HIGH
1072
+ technology:
1073
+ - java
1074
+ patterns:
1075
+ - pattern-either:
1076
+ - pattern: "new HostnameVerifier() {\n public boolean verify(String $HOST, SSLSession $SESSION) {\n return true;\n\
1077
+ \ }\n}\n"
1078
+ - pattern: 'HostnameVerifier $VERIFIER = ($HOST, $SESSION) -> true;
1079
+
1080
+ '
1081
+ - pattern: '$X.setDefaultHostnameVerifier(($HOST, $SESSION) -> true);
1082
+
1083
+ '
1084
+ - pattern: '$X.setHostnameVerifier(($HOST, $SESSION) -> true);
1085
+
1086
+ '
1087
+ - id: narvy.java.tls.cleartext-http-url.cleartext-http-url
1088
+ message: An outbound network call is built against a literal `http://` URL instead of `https://`. Traffic carrying session
1089
+ tokens, credentials, or any sensitive payload over plaintext HTTP can be read or altered by anyone on the network path
1090
+ (CWE-319). Use `https://` unless the target is a loopback/internal address that is genuinely local-only.
1091
+ severity: WARNING
1092
+ languages:
1093
+ - java
1094
+ metadata:
1095
+ category: security
1096
+ cwe:
1097
+ - 'CWE-319: Cleartext Transmission of Sensitive Information'
1098
+ owasp:
1099
+ - A02:2021 - Cryptographic Failures
1100
+ subcategory:
1101
+ - audit
1102
+ likelihood: LOW
1103
+ impact: MEDIUM
1104
+ confidence: LOW
1105
+ technology:
1106
+ - java
1107
+ patterns:
1108
+ - pattern-either:
1109
+ - pattern: new URL("http://...")
1110
+ - pattern: new java.net.URL("http://...")
1111
+ - pattern: $CLIENT.getForObject("http://...", ...)
1112
+ - pattern: $CLIENT.postForObject("http://...", ...)
1113
+ - pattern-not: new URL("http://localhost...")
1114
+ - pattern-not: new URL("http://127.0.0.1...")
1115
+ - id: narvy.java.tls.smtp-starttls-explicitly-disabled.smtp-starttls-explicitly-disabled
1116
+ message: JavaMail's `mail.smtp.starttls.enable` (or `mail.smtp.ssl.enable`) is explicitly set to `"false"`. The SMTP session
1117
+ then authenticates and sends mail over an unencrypted connection - credentials and message content are readable to anyone
1118
+ on the network path (CWE-319). Set the property to `"true"` (and prefer implicit SSL on port 465 or STARTTLS on 587 over
1119
+ unauthenticated plaintext SMTP on 25).
1120
+ severity: WARNING
1121
+ languages:
1122
+ - java
1123
+ metadata:
1124
+ category: security
1125
+ cwe:
1126
+ - 'CWE-319: Cleartext Transmission of Sensitive Information'
1127
+ owasp:
1128
+ - A02:2021 - Cryptographic Failures
1129
+ subcategory:
1130
+ - vuln
1131
+ likelihood: LOW
1132
+ impact: MEDIUM
1133
+ confidence: HIGH
1134
+ technology:
1135
+ - java
1136
+ patterns:
1137
+ - pattern-either:
1138
+ - pattern: $PROPS.put("mail.smtp.starttls.enable", "false")
1139
+ - pattern: $PROPS.setProperty("mail.smtp.starttls.enable", "false")
1140
+ - pattern: $PROPS.put("mail.smtp.ssl.enable", "false")
1141
+ - pattern: $PROPS.setProperty("mail.smtp.ssl.enable", "false")
1142
+ - pattern-not-inside: '...
1143
+
1144
+ $PROPS.put("mail.smtp.ssl.enable", "true");
1145
+
1146
+ ...
1147
+
1148
+ '
1149
+ - pattern-not-inside: '...
1150
+
1151
+ $PROPS.setProperty("mail.smtp.ssl.enable", "true");
1152
+
1153
+ ...
1154
+
1155
+ '
1156
+ - id: narvy.java.crypto.use-of-md5.use-of-md5
1157
+ message: MD5 is cryptographically broken; practical collisions have been demonstrated for over a decade. Do not use it for
1158
+ signatures, integrity checks, password storage, or any other security control (CWE-327, CWE-328). Use SHA-256 or stronger
1159
+ for integrity, and a memory-hard KDF (Argon2id, scrypt, bcrypt) for password hashing.
1160
+ severity: WARNING
1161
+ languages:
1162
+ - java
1163
+ metadata:
1164
+ category: security
1165
+ cwe:
1166
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1167
+ - 'CWE-328: Use of Weak Hash'
1168
+ owasp:
1169
+ - A02:2021 - Cryptographic Failures
1170
+ subcategory:
1171
+ - vuln
1172
+ likelihood: MEDIUM
1173
+ impact: MEDIUM
1174
+ confidence: HIGH
1175
+ technology:
1176
+ - java
1177
+ patterns:
1178
+ - pattern-either:
1179
+ - pattern: java.security.MessageDigest.getInstance("MD5")
1180
+ - pattern: MessageDigest.getInstance("MD5")
1181
+ - pattern: java.security.MessageDigest.getInstance("MD2")
1182
+ - pattern: MessageDigest.getInstance("MD2")
1183
+ - pattern: org.apache.commons.codec.digest.DigestUtils.md5Hex(...)
1184
+ - pattern: DigestUtils.md5Hex(...)
1185
+ - pattern: org.apache.commons.codec.digest.DigestUtils.md5(...)
1186
+ - pattern: DigestUtils.md5(...)
1187
+ - pattern: com.google.common.hash.Hashing.md5()
1188
+ - pattern: Hashing.md5()
1189
+ - id: narvy.java.crypto.use-of-sha1.use-of-sha1
1190
+ message: SHA-1 is deprecated for security purposes; chosen-prefix collisions are practical. Do not use it for signatures,
1191
+ certificate fingerprints, or any security-relevant integrity check (CWE-327, CWE-328). Use SHA-256 or stronger.
1192
+ severity: WARNING
1193
+ languages:
1194
+ - java
1195
+ metadata:
1196
+ category: security
1197
+ cwe:
1198
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1199
+ - 'CWE-328: Use of Weak Hash'
1200
+ owasp:
1201
+ - A02:2021 - Cryptographic Failures
1202
+ subcategory:
1203
+ - vuln
1204
+ likelihood: MEDIUM
1205
+ impact: MEDIUM
1206
+ confidence: HIGH
1207
+ technology:
1208
+ - java
1209
+ patterns:
1210
+ - pattern-either:
1211
+ - pattern: java.security.MessageDigest.getInstance("SHA-1")
1212
+ - pattern: MessageDigest.getInstance("SHA-1")
1213
+ - pattern: java.security.MessageDigest.getInstance("SHA1")
1214
+ - pattern: MessageDigest.getInstance("SHA1")
1215
+ - pattern: org.apache.commons.codec.digest.DigestUtils.sha1Hex(...)
1216
+ - pattern: DigestUtils.sha1Hex(...)
1217
+ - pattern: org.apache.commons.codec.digest.DigestUtils.sha1(...)
1218
+ - pattern: DigestUtils.sha1(...)
1219
+ - pattern: com.google.common.hash.Hashing.sha1()
1220
+ - pattern: Hashing.sha1()
1221
+ - id: narvy.java.crypto.weak-symmetric-cipher.weak-symmetric-cipher
1222
+ message: 'DES / 3DES(DESede) / RC2 / RC4 are broken or insufficient for modern use: DES''s 56-bit key is brute-forceable
1223
+ in hours, RC2/RC4 have known keystream biases, and 3DES''s 64-bit block size is vulnerable to birthday attacks (Sweet32)
1224
+ on any connection that moves enough data (CWE-327). Use AES-256 in GCM mode instead.'
1225
+ severity: WARNING
1226
+ languages:
1227
+ - java
1228
+ metadata:
1229
+ category: security
1230
+ cwe:
1231
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1232
+ - 'CWE-326: Inadequate Encryption Strength'
1233
+ owasp:
1234
+ - A02:2021 - Cryptographic Failures
1235
+ subcategory:
1236
+ - vuln
1237
+ likelihood: LOW
1238
+ impact: HIGH
1239
+ confidence: HIGH
1240
+ technology:
1241
+ - java
1242
+ patterns:
1243
+ - pattern-either:
1244
+ - pattern: Cipher.getInstance("DES")
1245
+ - pattern: Cipher.getInstance("DES/...")
1246
+ - pattern: Cipher.getInstance("DESede")
1247
+ - pattern: Cipher.getInstance("DESede/...")
1248
+ - pattern: Cipher.getInstance("TripleDES")
1249
+ - pattern: Cipher.getInstance("TripleDES/...")
1250
+ - pattern: Cipher.getInstance("RC2")
1251
+ - pattern: Cipher.getInstance("RC2/...")
1252
+ - pattern: Cipher.getInstance("RC4")
1253
+ - pattern: Cipher.getInstance("RC4/...")
1254
+ - pattern: Cipher.getInstance("ARCFOUR")
1255
+ - pattern: Cipher.getInstance("ARCFOUR/...")
1256
+ - pattern: KeyGenerator.getInstance("DES")
1257
+ - pattern: KeyGenerator.getInstance("DESede")
1258
+ - pattern: KeyGenerator.getInstance("RC4")
1259
+ - id: narvy.java.crypto.blowfish-weak-keysize.blowfish-weak-keysize
1260
+ message: Blowfish is instantiated with a key generator that has not been sized up from its 32-bit default in the default
1261
+ JCE provider. A short Blowfish key is brute-forceable (CWE-326). If Blowfish must be kept for legacy interop, call `init(256)`
1262
+ on the KeyGenerator; otherwise migrate to AES-256-GCM.
1263
+ severity: WARNING
1264
+ languages:
1265
+ - java
1266
+ metadata:
1267
+ category: security
1268
+ cwe:
1269
+ - 'CWE-326: Inadequate Encryption Strength'
1270
+ owasp:
1271
+ - A02:2021 - Cryptographic Failures
1272
+ subcategory:
1273
+ - audit
1274
+ likelihood: LOW
1275
+ impact: MEDIUM
1276
+ confidence: MEDIUM
1277
+ technology:
1278
+ - java
1279
+ patterns:
1280
+ - pattern-either:
1281
+ - pattern: KeyGenerator.getInstance("Blowfish")
1282
+ - pattern: Cipher.getInstance("Blowfish")
1283
+ - pattern: Cipher.getInstance("Blowfish/...")
1284
+ - id: narvy.java.crypto.ecb-cipher.ecb-cipher
1285
+ message: A symmetric cipher is used in ECB mode (explicitly, or implicitly via a bare algorithm name such as `Cipher.getInstance("AES")`,
1286
+ which most JCE providers default to `AES/ECB/PKCS5Padding`). ECB encrypts each block independently, so identical plaintext
1287
+ blocks produce identical ciphertext blocks; patterns in the plaintext (including images) leak through unencrypted (CWE-327).
1288
+ Use `AES/GCM/NoPadding` with a unique 12-byte nonce per encryption.
1289
+ severity: WARNING
1290
+ languages:
1291
+ - java
1292
+ metadata:
1293
+ category: security
1294
+ cwe:
1295
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1296
+ owasp:
1297
+ - A02:2021 - Cryptographic Failures
1298
+ subcategory:
1299
+ - vuln
1300
+ likelihood: MEDIUM
1301
+ impact: HIGH
1302
+ confidence: MEDIUM
1303
+ technology:
1304
+ - java
1305
+ patterns:
1306
+ - pattern-either:
1307
+ - pattern: Cipher.getInstance("AES/ECB/...")
1308
+ - pattern: Cipher.getInstance("AES")
1309
+ - id: narvy.java.crypto.static-iv.static-iv
1310
+ message: An `IvParameterSpec` (or GCM nonce) is built from a fixed byte array (a string literal, a `new byte[N]` zero-initialised
1311
+ array, or a hardcoded literal array) instead of a fresh random value per encryption. Reusing an IV/nonce with the same
1312
+ key breaks CBC's semantic security and is catastrophic for GCM (full plaintext/key recovery on nonce reuse) (CWE-329).
1313
+ Generate a new IV/nonce with `SecureRandom` for every encryption operation.
1314
+ severity: ERROR
1315
+ languages:
1316
+ - java
1317
+ metadata:
1318
+ category: security
1319
+ cwe:
1320
+ - 'CWE-329: Generation of Predictable IV with CBC Mode'
1321
+ - 'CWE-330: Use of Insufficiently Random Values'
1322
+ owasp:
1323
+ - A02:2021 - Cryptographic Failures
1324
+ subcategory:
1325
+ - vuln
1326
+ likelihood: LOW
1327
+ impact: HIGH
1328
+ confidence: MEDIUM
1329
+ technology:
1330
+ - java
1331
+ patterns:
1332
+ - pattern-either:
1333
+ - pattern: new IvParameterSpec("...".getBytes(...))
1334
+ - pattern: new IvParameterSpec(new byte[...])
1335
+ - pattern: new GCMParameterSpec($TAGLEN, "...".getBytes(...))
1336
+ - id: narvy.java.crypto.null-cipher.null-cipher
1337
+ message: '`javax.crypto.NullCipher` performs no encryption at all; every byte passes through unchanged. It exists purely
1338
+ for testing pipelines that expect a `Cipher` object. Shipping it in production code paths that handle real data is equivalent
1339
+ to storing/transmitting plaintext (CWE-327).'
1340
+ severity: ERROR
1341
+ languages:
1342
+ - java
1343
+ metadata:
1344
+ category: security
1345
+ cwe:
1346
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
1347
+ owasp:
1348
+ - A02:2021 - Cryptographic Failures
1349
+ subcategory:
1350
+ - vuln
1351
+ likelihood: LOW
1352
+ impact: HIGH
1353
+ confidence: HIGH
1354
+ technology:
1355
+ - java
1356
+ patterns:
1357
+ - pattern-either:
1358
+ - pattern: new NullCipher()
1359
+ - pattern: new javax.crypto.NullCipher()
1360
+ - id: narvy.java.crypto.weak-rsa-keysize.weak-rsa-keysize
1361
+ message: An RSA `KeyPairGenerator` is initialised with a key size below 2048 bits. NIST deprecated 1024-bit RSA in 2013;
1362
+ keys that small are within reach of well-resourced attackers and are rejected by most modern CA/TLS policies (CWE-326).
1363
+ Initialise with 2048 bits minimum (3072+ for long-lived keys).
1364
+ severity: WARNING
1365
+ languages:
1366
+ - java
1367
+ metadata:
1368
+ category: security
1369
+ cwe:
1370
+ - 'CWE-326: Inadequate Encryption Strength'
1371
+ owasp:
1372
+ - A02:2021 - Cryptographic Failures
1373
+ subcategory:
1374
+ - vuln
1375
+ likelihood: LOW
1376
+ impact: HIGH
1377
+ confidence: HIGH
1378
+ technology:
1379
+ - java
1380
+ patterns:
1381
+ - pattern-either:
1382
+ - pattern: $KPG.initialize(512, ...)
1383
+ - pattern: $KPG.initialize(512)
1384
+ - pattern: $KPG.initialize(768, ...)
1385
+ - pattern: $KPG.initialize(768)
1386
+ - pattern: $KPG.initialize(1024, ...)
1387
+ - pattern: $KPG.initialize(1024)
1388
+ - pattern-inside: '$KPG = KeyPairGenerator.getInstance("RSA");
1389
+
1390
+ ...
1391
+
1392
+ '
1393
+ - id: narvy.java.crypto.rsa-ecb-nopadding-cipher
1394
+ message: 'RSA is used with `NoPadding` (raw textbook RSA) instead of OAEP. Textbook RSA is deterministic and malleable:
1395
+ identical plaintexts always produce identical ciphertexts, and an attacker who can submit chosen ciphertexts to a decryption
1396
+ oracle can recover the plaintext (Bleichenbacher-style attacks) (CWE-780). Use `RSA/ECB/OAEPWithSHA-256AndMGF1Padding`.'
1397
+ severity: ERROR
1398
+ languages:
1399
+ - java
1400
+ metadata:
1401
+ category: security
1402
+ cwe:
1403
+ - 'CWE-780: Use of RSA Algorithm without OAEP'
1404
+ owasp:
1405
+ - A02:2021 - Cryptographic Failures
1406
+ subcategory:
1407
+ - vuln
1408
+ likelihood: LOW
1409
+ impact: HIGH
1410
+ confidence: HIGH
1411
+ technology:
1412
+ - java
1413
+ patterns:
1414
+ - pattern-either:
1415
+ - pattern: Cipher.getInstance("RSA/ECB/NoPadding")
1416
+ - pattern: Cipher.getInstance("RSA/None/NoPadding")
1417
+ - pattern: Cipher.getInstance("RSA/NONE/NoPadding")
1418
+ - id: narvy.java.crypto.rsa-pkcs1-padding.rsa-pkcs1-padding
1419
+ message: RSA is used with legacy PKCS#1 v1.5 padding. PKCS#1v1.5 is vulnerable to Bleichenbacher-style padding-oracle attacks
1420
+ when the same key decrypts attacker-supplied ciphertexts (CWE-780). Prefer `RSA/ECB/OAEPWithSHA-256AndMGF1Padding` for
1421
+ new code; if PKCS#1v1.5 is required for interop, ensure decryption errors never leak padding validity to the caller.
1422
+ severity: WARNING
1423
+ languages:
1424
+ - java
1425
+ metadata:
1426
+ category: security
1427
+ cwe:
1428
+ - 'CWE-780: Use of RSA Algorithm without OAEP'
1429
+ owasp:
1430
+ - A02:2021 - Cryptographic Failures
1431
+ subcategory:
1432
+ - audit
1433
+ likelihood: LOW
1434
+ impact: MEDIUM
1435
+ confidence: LOW
1436
+ technology:
1437
+ - java
1438
+ patterns:
1439
+ - pattern: Cipher.getInstance("RSA/ECB/PKCS1Padding")
1440
+ - id: narvy.java.crypto.insecure-random.insecure-random
1441
+ message: '`java.util.Random` / `Math.random()` / `ThreadLocalRandom` are linear-congruential or xorshift PRNGs whose output
1442
+ is predictable once a handful of samples are observed. Used to seed a token, password reset code, session identifier,
1443
+ or any other security-relevant value, an attacker can reconstruct past or future outputs (CWE-330, CWE-338). Use `java.security.SecureRandom`
1444
+ for anything that must be unpredictable.'
1445
+ severity: WARNING
1446
+ languages:
1447
+ - java
1448
+ metadata:
1449
+ category: security
1450
+ cwe:
1451
+ - 'CWE-330: Use of Insufficiently Random Values'
1452
+ - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)'
1453
+ owasp:
1454
+ - A02:2021 - Cryptographic Failures
1455
+ subcategory:
1456
+ - audit
1457
+ likelihood: MEDIUM
1458
+ impact: MEDIUM
1459
+ confidence: MEDIUM
1460
+ technology:
1461
+ - java
1462
+ patterns:
1463
+ - pattern-either:
1464
+ - pattern: new java.util.Random(...)
1465
+ - pattern: new Random(...)
1466
+ - pattern: Math.random()
1467
+ - pattern: ThreadLocalRandom.current()
1468
+ - pattern-not: new java.security.SecureRandom(...)
1469
+ - pattern-not: new SecureRandom(...)
1470
+ - id: narvy.java.xss.servlet-writer-tainted-request-param.servlet-writer-tainted-request-param
1471
+ message: A value read from the HTTP request (`getParameter`, `getHeader`, `getQueryString`) is written to `HttpServletResponse.getWriter()`
1472
+ (or `getOutputStream()`) without HTML-escaping. The value is reflected into the response body verbatim; an attacker who
1473
+ controls it can inject `<script>` or event-handler markup (CWE-79). Escape with an HTML encoder (`org.owasp.encoder.Encode.forHtml(...)`)
1474
+ before writing, or render through a templating engine that auto-escapes.
1475
+ severity: WARNING
1476
+ languages:
1477
+ - java
1478
+ metadata:
1479
+ category: security
1480
+ cwe:
1481
+ - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site Scripting'')'
1482
+ owasp:
1483
+ - A03:2021 - Injection
1484
+ subcategory:
1485
+ - vuln
1486
+ likelihood: MEDIUM
1487
+ impact: MEDIUM
1488
+ confidence: MEDIUM
1489
+ technology:
1490
+ - java
1491
+ mode: taint
1492
+ pattern-sources:
1493
+ - patterns:
1494
+ - pattern-either:
1495
+ - pattern: $REQ.getParameter(...)
1496
+ - pattern: $REQ.getHeader(...)
1497
+ - pattern: $REQ.getQueryString()
1498
+ pattern-sinks:
1499
+ - patterns:
1500
+ - pattern-either:
1501
+ - pattern: $RESP.getWriter().write($SINK)
1502
+ - pattern: $RESP.getWriter().print($SINK)
1503
+ - pattern: $RESP.getWriter().println($SINK)
1504
+ - pattern: $RESP.getOutputStream().print($SINK)
1505
+ - pattern: $W.write($SINK)
1506
+ - pattern: $W.print($SINK)
1507
+ pattern-sanitizers:
1508
+ - patterns:
1509
+ - pattern: org.owasp.encoder.Encode.forHtml(...)
1510
+ - patterns:
1511
+ - pattern: Encode.forHtml(...)
1512
+ - patterns:
1513
+ - pattern: StringEscapeUtils.escapeHtml4(...)
1514
+ - patterns:
1515
+ - pattern: HtmlUtils.htmlEscape(...)
1516
+ - patterns:
1517
+ - pattern: Integer.parseInt(...)
1518
+ - id: narvy.java.xss.spring-responsebody-tainted-string.spring-responsebody-tainted-string
1519
+ message: A `@RestController`/`@ResponseBody` handler method returns a `String` built directly from a `@RequestParam`/`@PathVariable`
1520
+ value with no HTML-escaping. When the response `Content-Type` is (or can be coerced to) `text/html`, this is a reflected-XSS
1521
+ sink (CWE-79). Return a typed DTO/JSON object instead of a raw HTML string, or escape the value explicitly before concatenating
1522
+ it into markup.
1523
+ severity: WARNING
1524
+ languages:
1525
+ - java
1526
+ metadata:
1527
+ category: security
1528
+ cwe:
1529
+ - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site Scripting'')'
1530
+ owasp:
1531
+ - A03:2021 - Injection
1532
+ subcategory:
1533
+ - audit
1534
+ likelihood: LOW
1535
+ impact: MEDIUM
1536
+ confidence: LOW
1537
+ technology:
1538
+ - java
1539
+ - spring
1540
+ patterns:
1541
+ - pattern-either:
1542
+ - pattern: "@GetMapping(...)\npublic String $HANDLER(..., @RequestParam $T $PARAM, ...) {\n ...\n return \"...\" + $PARAM\
1543
+ \ + \"...\";\n}\n"
1544
+ - pattern: "@PostMapping(...)\npublic String $HANDLER(..., @RequestParam $T $PARAM, ...) {\n ...\n return \"...\" +\
1545
+ \ $PARAM + \"...\";\n}\n"
1546
+ - pattern-not-inside: '@Controller
1547
+
1548
+ class $CLASS { ... }
1549
+
1550
+ '
1551
+ - id: narvy.java.xss.modelandview-tainted-attribute.modelandview-tainted-attribute
1552
+ message: A request parameter is added to a `ModelAndView`/`Model` attribute and the view is a `text/*` or a hand-built HTML
1553
+ string view (not a `Thymeleaf`/`JSP` template that auto-escapes with `${...}`). If the rendering layer does not HTML-escape
1554
+ model attributes, this is a reflected-XSS sink (CWE-79). Confirm the view technology escapes by default, or escape the
1555
+ value before adding it to the model.
1556
+ severity: WARNING
1557
+ languages:
1558
+ - java
1559
+ metadata:
1560
+ category: security
1561
+ cwe:
1562
+ - 'CWE-79: Improper Neutralization of Input During Web Page Generation (''Cross-site Scripting'')'
1563
+ owasp:
1564
+ - A03:2021 - Injection
1565
+ subcategory:
1566
+ - audit
1567
+ likelihood: LOW
1568
+ impact: MEDIUM
1569
+ confidence: LOW
1570
+ technology:
1571
+ - java
1572
+ - spring
1573
+ patterns:
1574
+ - pattern-either:
1575
+ - pattern: $MODEL.addAttribute($KEY, $REQ.getParameter(...))
1576
+ - pattern: $MAV.addObject($KEY, $REQ.getParameter(...))