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,291 @@
1
+ rules:
2
+
3
+ # Java/Spring hardening: CSRF disabled, SpEL injection, permissive CORS.
4
+
5
+ - id: narvy.java.spring.csrf-disabled.csrf-disabled
6
+ message: >-
7
+ CSRF protection is explicitly turned off on this
8
+ `HttpSecurity`/`ServerHttpSecurity` chain. Once disabled, any
9
+ state-changing endpoint reachable with a browser-sent cookie can be
10
+ triggered from a page the victim did not intend to submit (CWE-352).
11
+ This is a deliberate choice for pure token-authenticated APIs (no
12
+ cookie-based session, `Authorization: Bearer` on every call) - if that
13
+ is this service, leave a comment explaining why; if any endpoint still
14
+ relies on a session cookie, re-enable CSRF or scope the disable to the
15
+ stateless endpoints only.
16
+ severity: WARNING
17
+ languages: [java]
18
+ metadata:
19
+ category: security
20
+ cwe:
21
+ - "CWE-352: Cross-Site Request Forgery (CSRF)"
22
+ owasp:
23
+ - "A01:2021 - Broken Access Control"
24
+ subcategory: [audit]
25
+ likelihood: LOW
26
+ impact: MEDIUM
27
+ confidence: MEDIUM
28
+ technology: [java, spring]
29
+ patterns:
30
+ - pattern-either:
31
+ - pattern: $HTTP.csrf().disable()
32
+ - pattern: $HTTP.csrf($CSRF -> $CSRF.disable())
33
+ - pattern: $HTTP.csrf(AbstractHttpConfigurer::disable)
34
+ - pattern: $HTTP.csrf(CsrfConfigurer::disable)
35
+ - pattern: $HTTP.csrf(ServerHttpSecurity.CsrfSpec::disable)
36
+ - pattern: $HTTP.csrf(CsrfSpec::disable)
37
+
38
+ - id: narvy.java.spring.spel-injection.tainted-request-parseexpression
39
+ message: >-
40
+ A Spring Expression Language (SpEL) parser evaluates an expression
41
+ string built from an HTTP request parameter, header, or a
42
+ `@RequestParam`/`@PathVariable` handler argument. SpEL is a full
43
+ expression language with reflection and static-method invocation
44
+ (`T(java.lang.Runtime).getRuntime().exec(...)` is valid SpEL) - letting
45
+ the request choose any part of the evaluated expression is remote code
46
+ execution, not just information disclosure (CWE-94). Never evaluate
47
+ request-derived text as SpEL; if the request must select between a
48
+ handful of computations, look them up in a fixed map instead.
49
+ severity: ERROR
50
+ languages: [java]
51
+ metadata:
52
+ category: security
53
+ cwe:
54
+ - "CWE-94: Improper Control of Generation of Code ('Code Injection')"
55
+ owasp:
56
+ - "A03:2021 - Injection"
57
+ subcategory: [vuln]
58
+ likelihood: MEDIUM
59
+ impact: HIGH
60
+ confidence: HIGH
61
+ technology: [java, spring]
62
+ mode: taint
63
+ pattern-sources:
64
+ - patterns:
65
+ - pattern-either:
66
+ - pattern: $REQ.getParameter(...)
67
+ - pattern: $REQ.getHeader(...)
68
+ - patterns:
69
+ - pattern-inside: |
70
+ $RET $METHOD(..., @RequestParam $T $PARAM, ...) {
71
+ ...
72
+ }
73
+ - pattern: $PARAM
74
+ - patterns:
75
+ - pattern-inside: |
76
+ $RET $METHOD(..., @RequestParam(...) $T $PARAM, ...) {
77
+ ...
78
+ }
79
+ - pattern: $PARAM
80
+ - patterns:
81
+ - pattern-inside: |
82
+ $RET $METHOD(..., @PathVariable $T $PARAM, ...) {
83
+ ...
84
+ }
85
+ - pattern: $PARAM
86
+ - patterns:
87
+ - pattern-inside: |
88
+ $RET $METHOD(..., @PathVariable(...) $T $PARAM, ...) {
89
+ ...
90
+ }
91
+ - pattern: $PARAM
92
+ pattern-sinks:
93
+ - patterns:
94
+ - pattern: $PARSER.parseExpression($SINK)
95
+
96
+ - id: narvy.java.spring.spel-injection.dynamic-expression-parsed
97
+ message: >-
98
+ A SpEL `ExpressionParser`/`SpelExpressionParser` evaluates a string
99
+ that is not a fixed literal in this call (it comes from a getter, a
100
+ method argument, a loop variable, or a field). SpEL grants full
101
+ reflection and static-method invocation once evaluated, so parsing
102
+ anything other than a compile-time-fixed expression is a code-injection
103
+ risk the moment that string can be influenced by a stored record, a
104
+ config value an admin (not a developer) can edit, or an upstream call
105
+ (CWE-94). Confirm the expression text is fully outside user/operator
106
+ reach, or stop building it dynamically.
107
+ severity: WARNING
108
+ languages: [java]
109
+ metadata:
110
+ category: security
111
+ cwe:
112
+ - "CWE-94: Improper Control of Generation of Code ('Code Injection')"
113
+ owasp:
114
+ - "A03:2021 - Injection"
115
+ subcategory: [audit]
116
+ likelihood: LOW
117
+ impact: HIGH
118
+ confidence: LOW
119
+ technology: [java, spring]
120
+ patterns:
121
+ - pattern-inside: |
122
+ ...
123
+ $PARSERTYPE $PARSER = ...;
124
+ ...
125
+ - metavariable-regex:
126
+ metavariable: $PARSERTYPE
127
+ regex: ^(SpelExpressionParser|ExpressionParser|TemplateAwareExpressionParser)$
128
+ - pattern: $PARSER.parseExpression($EXPR)
129
+ - pattern-not: $PARSER.parseExpression("...")
130
+ - pattern-not-inside: |
131
+ String $EXPR = "...";
132
+ ...
133
+
134
+ - id: narvy.java.spring.spel-injection.dangerous-type-reference
135
+ message: >-
136
+ A hardcoded SpEL expression (parsed directly, or supplied via
137
+ `@Value(...)`) references `java.lang.Runtime` or
138
+ `java.lang.ProcessBuilder` through SpEL's `T(...)` type-reference
139
+ syntax. That is a working remote-code-execution gadget the moment this
140
+ expression string becomes reachable from outside the codebase - a
141
+ config value an operator can edit, a template an admin user can save,
142
+ or debug/test code left behind (CWE-94). Remove the type reference; if
143
+ process execution is genuinely needed, call `ProcessBuilder` directly
144
+ from Java code, not through an evaluated expression string.
145
+ severity: ERROR
146
+ languages: [java]
147
+ metadata:
148
+ category: security
149
+ cwe:
150
+ - "CWE-94: Improper Control of Generation of Code ('Code Injection')"
151
+ owasp:
152
+ - "A03:2021 - Injection"
153
+ subcategory: [vuln]
154
+ likelihood: LOW
155
+ impact: HIGH
156
+ confidence: HIGH
157
+ technology: [java, spring]
158
+ patterns:
159
+ - pattern-either:
160
+ - pattern: $PARSER.parseExpression($S)
161
+ - pattern: '@Value($S)'
162
+ - metavariable-regex:
163
+ metavariable: $S
164
+ regex: .*T\(\s*(java\.lang\.)?(Runtime|ProcessBuilder)\s*\).*
165
+
166
+ - id: narvy.java.spring.permissive-cors.crossorigin-wildcard-annotation
167
+ message: >-
168
+ `@CrossOrigin` allows every origin (`"*"`, or no `origins` value at
169
+ all, which also defaults to allow-all). Any website can now make
170
+ cross-origin requests to this endpoint from a victim's browser and read
171
+ the response, defeating the same-origin policy that protects
172
+ session-cookie-authenticated users from other sites reading their data
173
+ (CWE-942). Name the exact origins that need access instead of `"*"`.
174
+ severity: WARNING
175
+ languages: [java]
176
+ metadata:
177
+ category: security
178
+ cwe:
179
+ - "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
180
+ owasp:
181
+ - "A05:2021 - Security Misconfiguration"
182
+ subcategory: [audit]
183
+ likelihood: LOW
184
+ impact: MEDIUM
185
+ confidence: MEDIUM
186
+ technology: [java, spring]
187
+ patterns:
188
+ - pattern-either:
189
+ - pattern: '@CrossOrigin(origins = "*")'
190
+ - pattern: '@CrossOrigin(origins = {"*"})'
191
+ - pattern: '@CrossOrigin("*")'
192
+
193
+ - id: narvy.java.spring.permissive-cors.corsconfiguration-wildcard
194
+ message: >-
195
+ A `CorsConfiguration` allows every origin (`"*"`, or the equivalent
196
+ `addAllowedOriginPattern("*")`/wildcard `CorsConfigurationSource`).
197
+ Any website can now make cross-origin requests to this application
198
+ from a victim's browser (CWE-942). Build the allowed-origins list from
199
+ a fixed set of known-good hosts instead of a wildcard.
200
+ severity: WARNING
201
+ languages: [java]
202
+ metadata:
203
+ category: security
204
+ cwe:
205
+ - "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
206
+ owasp:
207
+ - "A05:2021 - Security Misconfiguration"
208
+ subcategory: [audit]
209
+ likelihood: LOW
210
+ impact: MEDIUM
211
+ confidence: MEDIUM
212
+ technology: [java, spring]
213
+ patterns:
214
+ - pattern-either:
215
+ - pattern: $CFG.setAllowedOrigins(java.util.List.of("*"))
216
+ - pattern: $CFG.setAllowedOrigins(java.util.Arrays.asList("*"))
217
+ - pattern: $CFG.setAllowedOrigins(java.util.Collections.singletonList("*"))
218
+ - pattern: $CFG.addAllowedOrigin("*")
219
+ - pattern: $CFG.setAllowedOriginPatterns(java.util.List.of("*"))
220
+ - pattern: $CFG.addAllowedOriginPattern("*")
221
+
222
+ - id: narvy.java.spring.permissive-cors.corsconfiguration-wildcard-with-credentials
223
+ message: >-
224
+ This `CorsConfiguration` allows every origin AND allows credentials
225
+ (`setAllowCredentials(true)`). Combined, a malicious page on any site
226
+ can send the victim's session cookie/basic-auth header cross-origin and
227
+ read the authenticated response - the exact attack CORS's
228
+ credentialed-request checks exist to block (CWE-942). Most browsers
229
+ reject a literal `"*"` alongside `allowCredentials(true)` today, but a
230
+ reflected-origin implementation (echoing whatever `Origin` header the
231
+ caller sent) has the identical effect and does pass browser checks - if
232
+ this configuration reflects the request origin rather than using a
233
+ fixed allow-list, treat this as exploitable now.
234
+ severity: ERROR
235
+ languages: [java]
236
+ metadata:
237
+ category: security
238
+ cwe:
239
+ - "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
240
+ owasp:
241
+ - "A05:2021 - Security Misconfiguration"
242
+ subcategory: [vuln]
243
+ likelihood: MEDIUM
244
+ impact: HIGH
245
+ confidence: MEDIUM
246
+ technology: [java, spring]
247
+ patterns:
248
+ - pattern-inside: |
249
+ $CFGTYPE $CFG = ...;
250
+ ...
251
+ $CFG.setAllowCredentials(true);
252
+ ...
253
+ - pattern-either:
254
+ - pattern: $CFG.setAllowedOrigins(java.util.List.of("*"))
255
+ - pattern: $CFG.setAllowedOrigins(java.util.Arrays.asList("*"))
256
+ - pattern: $CFG.addAllowedOrigin("*")
257
+ - pattern: $CFG.setAllowedOriginPatterns(java.util.List.of("*"))
258
+ - pattern: $CFG.addAllowedOriginPattern("*")
259
+
260
+ - id: narvy.java.spring.permissive-cors.addcorsmapping-wildcard
261
+ message: >-
262
+ A `WebMvcConfigurer.addCorsMapping` registration allows every origin
263
+ (`"*"`, or omits `.allowedOrigins(...)` entirely, which also defaults
264
+ to allow-all). Any website can now make cross-origin requests to the
265
+ mapped paths from a victim's browser (CWE-942). Name the exact origins
266
+ that need access instead of `"*"`.
267
+ severity: WARNING
268
+ languages: [java]
269
+ metadata:
270
+ category: security
271
+ cwe:
272
+ - "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
273
+ owasp:
274
+ - "A05:2021 - Security Misconfiguration"
275
+ subcategory: [audit]
276
+ likelihood: LOW
277
+ impact: MEDIUM
278
+ confidence: MEDIUM
279
+ technology: [java, spring]
280
+ patterns:
281
+ - pattern-inside: |
282
+ class $CLASS implements WebMvcConfigurer {
283
+ ...
284
+ public void addCorsMappings(CorsRegistry $REGISTRY) {
285
+ ...
286
+ }
287
+ ...
288
+ }
289
+ - pattern-either:
290
+ - pattern: $REGISTRY.addMapping(...).allowedOrigins("*")
291
+ - pattern: $MAPPING.allowedOrigins("*")
@@ -0,0 +1,235 @@
1
+ rules:
2
+
3
+ # Java SQL injection: JDBC, JPA/Hibernate, Spring JdbcTemplate, MyBatis.
4
+
5
+ - id: narvy.java.sqli.jdbc-statement-concat.jdbc-statement-concat
6
+ message: >-
7
+ A plain JDBC `Statement` executes a query string built with `+`
8
+ concatenation. `Statement` never parameterises, so any tainted value
9
+ reaching the concatenation is a direct SQL injection (CWE-89). Switch to
10
+ `PreparedStatement` with `?` placeholders and `setString`/`setInt`/etc.
11
+ severity: ERROR
12
+ languages: [java]
13
+ metadata:
14
+ category: security
15
+ cwe:
16
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
17
+ owasp:
18
+ - "A03:2021 - Injection"
19
+ subcategory: [vuln]
20
+ likelihood: HIGH
21
+ impact: HIGH
22
+ confidence: MEDIUM
23
+ technology: [java]
24
+ patterns:
25
+ - pattern-either:
26
+ - pattern: $STMT.executeQuery($A + $B)
27
+ - pattern: $STMT.executeUpdate($A + $B)
28
+ - pattern: $STMT.execute($A + $B)
29
+ - pattern-not: $STMT.executeQuery("..." + "...")
30
+ - pattern-not: $STMT.executeUpdate("..." + "...")
31
+ - pattern-not: $STMT.execute("..." + "...")
32
+
33
+ - id: narvy.java.sqli.jdbc-connection-createquery-concat.jdbc-connection-createquery-concat
34
+ message: >-
35
+ `Connection.prepareStatement(...)` is called with a SQL string built by
36
+ `+` concatenation. Building the query text via concatenation defeats the
37
+ protection `PreparedStatement` exists to provide, because the tainted
38
+ value is already part of the parsed SQL grammar by the time the driver
39
+ sees it (CWE-89). Keep the query text a fixed literal and bind values
40
+ with `?` + `setString`/`setInt`.
41
+ severity: ERROR
42
+ languages: [java]
43
+ metadata:
44
+ category: security
45
+ cwe:
46
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
47
+ owasp:
48
+ - "A03:2021 - Injection"
49
+ subcategory: [vuln]
50
+ likelihood: HIGH
51
+ impact: HIGH
52
+ confidence: MEDIUM
53
+ technology: [java]
54
+ patterns:
55
+ - pattern-either:
56
+ - pattern: $CONN.prepareStatement($A + $B)
57
+ - pattern: $CONN.prepareStatement($A + $B, ...)
58
+ - pattern-not: $CONN.prepareStatement("..." + "...")
59
+ - pattern-not: $CONN.prepareStatement("..." + "...", ...)
60
+
61
+ - id: narvy.java.sqli.jpa-createquery-concat.jpa-createquery-concat
62
+ message: >-
63
+ A JPA/Hibernate `EntityManager.createQuery(...)` or
64
+ `createNativeQuery(...)` builds JPQL/SQL by string concatenation. Even
65
+ JPQL is subject to injection when the WHERE clause, ORDER BY column, or
66
+ table name is built from tainted data this way (CWE-89). Use a named or
67
+ positional parameter (`:status`, `?1`) and `setParameter(...)` instead
68
+ of splicing the value into the query text.
69
+ severity: ERROR
70
+ languages: [java]
71
+ metadata:
72
+ category: security
73
+ cwe:
74
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
75
+ owasp:
76
+ - "A03:2021 - Injection"
77
+ subcategory: [vuln]
78
+ likelihood: HIGH
79
+ impact: HIGH
80
+ confidence: MEDIUM
81
+ technology: [java]
82
+ patterns:
83
+ - pattern-either:
84
+ - pattern: $EM.createQuery($A + $B)
85
+ - pattern: $EM.createNativeQuery($A + $B)
86
+ - pattern: $EM.createNativeQuery($A + $B, ...)
87
+ - pattern-not: $EM.createQuery("..." + "...")
88
+ - pattern-not: $EM.createNativeQuery("..." + "...")
89
+ - pattern-not: $EM.createNativeQuery("..." + "...", ...)
90
+
91
+ # Covers the variable-indirection shape (concatenation moved to a local) that the inline rule above misses.
92
+ - id: narvy.java.sqli.jpa-createquery-concat-var.jpa-createquery-concat-var
93
+ message: >-
94
+ The query string handed to `createQuery`/`createNativeQuery` was built
95
+ by string concatenation a few lines earlier and assigned to a local
96
+ variable. Moving the concatenation into a variable does not change
97
+ what reaches the database (CWE-89). Bind the value with
98
+ `setParameter(...)` instead.
99
+ severity: ERROR
100
+ languages: [java]
101
+ metadata:
102
+ category: security
103
+ cwe:
104
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
105
+ owasp:
106
+ - "A03:2021 - Injection"
107
+ subcategory: [vuln]
108
+ likelihood: HIGH
109
+ impact: HIGH
110
+ confidence: MEDIUM
111
+ technology: [java]
112
+ patterns:
113
+ - pattern-either:
114
+ - pattern: |
115
+ String $Q = $A + $B;
116
+ ...
117
+ $EM.createQuery($Q, ...);
118
+ - pattern: |
119
+ String $Q = $A + $B;
120
+ ...
121
+ $EM.createNativeQuery($Q, ...);
122
+ - pattern-not: |
123
+ String $Q = "..." + "...";
124
+ ...
125
+ $EM.createQuery($Q, ...);
126
+ - pattern-not: |
127
+ String $Q = "..." + "...";
128
+ ...
129
+ $EM.createNativeQuery($Q, ...);
130
+
131
+ - id: narvy.java.sqli.jpa-createquery-sprintf-var.jpa-createquery-sprintf-var
132
+ message: >-
133
+ A JPQL/native query string assembled with `String.format(...)` is passed
134
+ to `createQuery`/`createNativeQuery`. `String.format` does not escape
135
+ SQL metacharacters - a tainted format argument is a SQL injection the
136
+ same as direct concatenation would be (CWE-89). Use a bind parameter
137
+ instead of formatting the value into the query text.
138
+ severity: ERROR
139
+ languages: [java]
140
+ metadata:
141
+ category: security
142
+ cwe:
143
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
144
+ owasp:
145
+ - "A03:2021 - Injection"
146
+ subcategory: [vuln]
147
+ likelihood: MEDIUM
148
+ impact: HIGH
149
+ confidence: HIGH
150
+ technology: [java]
151
+ patterns:
152
+ - pattern-either:
153
+ - pattern: |
154
+ $Q = String.format($FMT, ...);
155
+ ...
156
+ $EM.createQuery($Q);
157
+ - pattern: |
158
+ $Q = String.format($FMT, ...);
159
+ ...
160
+ $EM.createNativeQuery($Q);
161
+
162
+ - id: narvy.java.sqli.jdbctemplate-concat.jdbctemplate-concat
163
+ message: >-
164
+ Spring `JdbcTemplate` is called with a SQL string built by `+`
165
+ concatenation instead of the `?` placeholder + args form. `JdbcTemplate`
166
+ only protects arguments passed through its own varargs binder; splicing
167
+ a value into the SQL text bypasses that entirely (CWE-89). Use
168
+ `jdbcTemplate.query("... WHERE id = ?", rowMapper, id)`.
169
+ severity: ERROR
170
+ languages: [java]
171
+ metadata:
172
+ category: security
173
+ cwe:
174
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
175
+ owasp:
176
+ - "A03:2021 - Injection"
177
+ subcategory: [vuln]
178
+ likelihood: HIGH
179
+ impact: HIGH
180
+ confidence: MEDIUM
181
+ technology: [java, spring]
182
+ patterns:
183
+ - pattern-either:
184
+ - pattern: $JT.query($A + $B, ...)
185
+ - pattern: $JT.queryForObject($A + $B, ...)
186
+ - pattern: $JT.queryForList($A + $B, ...)
187
+ - pattern: $JT.update($A + $B, ...)
188
+ - pattern: $JT.execute($A + $B)
189
+ - pattern-not: $JT.query("..." + "...", ...)
190
+ - pattern-not: $JT.queryForObject("..." + "...", ...)
191
+ - pattern-not: $JT.queryForList("..." + "...", ...)
192
+ - pattern-not: $JT.update("..." + "...", ...)
193
+ - pattern-not: $JT.execute("..." + "...")
194
+
195
+ - id: narvy.java.sqli.tainted-request-param-to-statement.tainted-request-param-to-statement
196
+ message: >-
197
+ A value read directly from the HTTP request (`getParameter`,
198
+ `getHeader`, `getQueryString`) reaches a `Statement`/`PreparedStatement`
199
+ SQL sink through a local variable, with no bind-parameter API in the
200
+ call. Even when the sink call itself is a `PreparedStatement`, if the
201
+ tainted value ends up as part of the SQL text (versus a bound `?`
202
+ argument) it is a SQL injection (CWE-89). Bind the value with
203
+ `setString`/`setInt`/etc; never build the SQL string from request data.
204
+ severity: WARNING
205
+ languages: [java]
206
+ metadata:
207
+ category: security
208
+ cwe:
209
+ - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
210
+ owasp:
211
+ - "A03:2021 - Injection"
212
+ subcategory: [vuln]
213
+ likelihood: MEDIUM
214
+ impact: HIGH
215
+ confidence: MEDIUM
216
+ technology: [java]
217
+ mode: taint
218
+ pattern-sources:
219
+ - patterns:
220
+ - pattern-either:
221
+ - pattern: $REQ.getParameter(...)
222
+ - pattern: $REQ.getHeader(...)
223
+ - pattern: $REQ.getQueryString()
224
+ pattern-sinks:
225
+ - patterns:
226
+ - pattern-either:
227
+ - pattern: $STMT.executeQuery("..." + $SINK + "...")
228
+ - pattern: $STMT.executeQuery("..." + $SINK)
229
+ - pattern: $STMT.executeUpdate("..." + $SINK + "...")
230
+ - pattern: $STMT.execute("..." + $SINK + "...")
231
+ pattern-sanitizers:
232
+ - patterns:
233
+ - pattern: Integer.parseInt(...)
234
+ - patterns:
235
+ - pattern: Long.parseLong(...)