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,413 @@
1
+ # Kotlin security rules, authored by Narvy.
2
+ # String-template SQL and command injection, Ktor CORS, weak crypto.
3
+
4
+ rules:
5
+ - id: narvy.kotlin.auth.ldap-unauthenticated-bind
6
+ message: An LDAP `InitialDirContext` is opened with `SECURITY_AUTHENTICATION` set to `"none"`, i.e. an anonymous bind. Anonymous
7
+ binds let any caller run LDAP queries against the directory without proving identity, which typically over-exposes directory
8
+ contents and defeats access controls built on top of the bind (CWE-287). Bind with real credentials (simple or SASL) unless
9
+ anonymous read access to this directory is a deliberate, documented design choice.
10
+ severity: WARNING
11
+ languages:
12
+ - kotlin
13
+ metadata:
14
+ category: security
15
+ cwe:
16
+ - 'CWE-287: Improper Authentication'
17
+ owasp:
18
+ - A07:2021 - Identification and Authentication Failures
19
+ subcategory:
20
+ - vuln
21
+ likelihood: LOW
22
+ impact: MEDIUM
23
+ confidence: MEDIUM
24
+ technology:
25
+ - kotlin
26
+ patterns:
27
+ - pattern: '$ENV.put(Context.SECURITY_AUTHENTICATION, "none")
28
+
29
+ ...
30
+
31
+ $DCTX = InitialDirContext($ENV, ...)
32
+
33
+ '
34
+ - id: narvy.kotlin.secrets.gradle-fallback-password.gradle-fallback-password
35
+ message: 'A Gradle Kotlin DSL build script reads a signing/repository password from the environment with a hardcoded literal
36
+ as the Elvis-operator fallback (`env["..."] ?: "literal"`). Build scripts are committed to source control, so this literal
37
+ ships to every clone of the repository; if the real environment variable is ever unset, the build silently signs or authenticates
38
+ with the leaked fallback (CWE-798). Fail the build instead of falling back: `env["SIGNING_PASSWORD"] ?: error("SIGNING_PASSWORD
39
+ not set")`.'
40
+ severity: WARNING
41
+ languages:
42
+ - kotlin
43
+ metadata:
44
+ category: security
45
+ cwe:
46
+ - 'CWE-798: Use of Hard-coded Credentials'
47
+ owasp:
48
+ - A07:2021 - Identification and Authentication Failures
49
+ subcategory:
50
+ - vuln
51
+ likelihood: LOW
52
+ impact: HIGH
53
+ confidence: MEDIUM
54
+ technology:
55
+ - kotlin
56
+ options:
57
+ symbolic_propagation: true
58
+ patterns:
59
+ - pattern: '$PASS = System.getenv($NAME) ?: $VALUE'
60
+ - metavariable-regex:
61
+ metavariable: $PASS
62
+ regex: (?i).*(password|passwd|secret|signingkey|apikey|token).*
63
+ - metavariable-regex:
64
+ metavariable: $VALUE
65
+ regex: ^"[A-Za-z0-9/+=_-]{4,}"$
66
+ paths:
67
+ include:
68
+ - '*build.gradle.kts'
69
+ - '*settings.gradle.kts'
70
+ - id: narvy.kotlin.auth.csrf-disabled.csrf-disabled
71
+ message: Spring Security's CSRF protection is explicitly disabled (`http.csrf { it.disable() }`). Without CSRF tokens, any
72
+ authenticated session can be driven by a malicious page to perform state-changing requests the victim never intended (CWE-352).
73
+ Disable CSRF only for endpoints that are genuinely stateless/token-authenticated (pure REST APIs using bearer tokens,
74
+ not cookies), and scope the exemption with `ignoringRequestMatchers(...)` rather than disabling it globally.
75
+ severity: WARNING
76
+ languages:
77
+ - kotlin
78
+ metadata:
79
+ category: security
80
+ cwe:
81
+ - 'CWE-352: Cross-Site Request Forgery (CSRF)'
82
+ owasp:
83
+ - A01:2021 - Broken Access Control
84
+ subcategory:
85
+ - audit
86
+ likelihood: LOW
87
+ impact: MEDIUM
88
+ confidence: MEDIUM
89
+ technology:
90
+ - kotlin
91
+ - spring
92
+ patterns:
93
+ - pattern: $HTTP.csrf { it.disable() }
94
+ - id: narvy.kotlin.cmdi.command-string-template.command-string-template
95
+ message: '`Runtime.getRuntime().exec(...)` is called with a single command string built via Kotlin string-template interpolation
96
+ (`"ping -c 1 $host"`). The JVM tokenises that single-string form itself, so an interpolated value containing spaces or
97
+ shell metacharacters changes how many arguments the process actually receives - a command injection vector (CWE-78). Use
98
+ the `exec(Array<String>)` / `ProcessBuilder(listOf(...))` overload with each argument as a separate element instead of
99
+ building one interpolated string.'
100
+ severity: ERROR
101
+ languages:
102
+ - kotlin
103
+ metadata:
104
+ category: security
105
+ cwe:
106
+ - 'CWE-78: Improper Neutralization of Special Elements used in an OS Command (''OS Command Injection'')'
107
+ owasp:
108
+ - A03:2021 - Injection
109
+ subcategory:
110
+ - vuln
111
+ likelihood: HIGH
112
+ impact: HIGH
113
+ confidence: MEDIUM
114
+ technology:
115
+ - kotlin
116
+ patterns:
117
+ - pattern: Runtime.getRuntime().exec("...${$X}...")
118
+ - id: narvy.kotlin.cors.install-cors-anyhost.install-cors-anyhost
119
+ message: A Ktor `install(CORS)` block calls `anyHost()` while also allowing credentials (`allowCredentials = true`). Reflecting
120
+ every Origin while also permitting cookies/Authorization headers on cross-origin requests means any website can make authenticated
121
+ requests on behalf of a logged in user and read the response (CWE-942). Restrict allowed hosts with `allowHost("app.example.com",
122
+ schemes = listOf("https"))` when `allowCredentials` is enabled.
123
+ severity: ERROR
124
+ languages:
125
+ - kotlin
126
+ metadata:
127
+ category: security
128
+ cwe:
129
+ - 'CWE-942: Permissive Cross-domain Policy with Untrusted Domains'
130
+ owasp:
131
+ - A05:2021 - Security Misconfiguration
132
+ subcategory:
133
+ - vuln
134
+ likelihood: MEDIUM
135
+ impact: HIGH
136
+ confidence: MEDIUM
137
+ technology:
138
+ - kotlin
139
+ - ktor
140
+ patterns:
141
+ - pattern: "install(CORS) {\n ...\n anyHost()\n ...\n allowCredentials = true\n ...\n}\n"
142
+ - id: narvy.kotlin.crypto.use-of-md5.use-of-md5
143
+ message: MD5 is cryptographically broken; practical collisions have been demonstrated for over a decade. Do not use it for
144
+ signatures, integrity checks, password storage, or any other security control (CWE-327, CWE-328). Use SHA-256 or stronger
145
+ for integrity, and a memory-hard KDF (Argon2id, scrypt, bcrypt) for password hashing.
146
+ severity: WARNING
147
+ languages:
148
+ - kotlin
149
+ metadata:
150
+ category: security
151
+ cwe:
152
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
153
+ - 'CWE-328: Use of Weak Hash'
154
+ owasp:
155
+ - A02:2021 - Cryptographic Failures
156
+ subcategory:
157
+ - vuln
158
+ likelihood: MEDIUM
159
+ impact: MEDIUM
160
+ confidence: HIGH
161
+ technology:
162
+ - kotlin
163
+ patterns:
164
+ - pattern-either:
165
+ - pattern: MessageDigest.getInstance("MD5")
166
+ - pattern: java.security.MessageDigest.getInstance("MD5")
167
+ - pattern: DigestUtils.getMd5Digest()
168
+ - pattern: DigestUtils.md5Hex(...)
169
+ - id: narvy.kotlin.crypto.use-of-sha1.use-of-sha1
170
+ message: SHA-1 is deprecated for security purposes; chosen-prefix collisions are practical. Do not use it for signatures,
171
+ certificate fingerprints, or any security-relevant integrity check (CWE-327, CWE-328). Use SHA-256 or stronger.
172
+ severity: WARNING
173
+ languages:
174
+ - kotlin
175
+ metadata:
176
+ category: security
177
+ cwe:
178
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
179
+ - 'CWE-328: Use of Weak Hash'
180
+ owasp:
181
+ - A02:2021 - Cryptographic Failures
182
+ subcategory:
183
+ - vuln
184
+ likelihood: MEDIUM
185
+ impact: MEDIUM
186
+ confidence: HIGH
187
+ technology:
188
+ - kotlin
189
+ patterns:
190
+ - pattern-either:
191
+ - pattern: MessageDigest.getInstance("SHA-1")
192
+ - pattern: MessageDigest.getInstance("SHA1")
193
+ - pattern: java.security.MessageDigest.getInstance("SHA-1")
194
+ - pattern: DigestUtils.getSha1Digest()
195
+ - pattern: DigestUtils.sha1Hex(...)
196
+ - id: narvy.kotlin.crypto.ecb-cipher.ecb-cipher
197
+ message: A symmetric cipher is used in ECB mode (explicitly, or implicitly via a bare algorithm name such as `Cipher.getInstance("AES")`,
198
+ which most JCE providers default to `AES/ECB/PKCS5Padding`). ECB encrypts each block independently, so identical plaintext
199
+ blocks produce identical ciphertext blocks; patterns in the plaintext leak through unencrypted (CWE-327). Use `AES/GCM/NoPadding`
200
+ with a unique 12-byte nonce per encryption.
201
+ severity: WARNING
202
+ languages:
203
+ - kotlin
204
+ metadata:
205
+ category: security
206
+ cwe:
207
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
208
+ owasp:
209
+ - A02:2021 - Cryptographic Failures
210
+ subcategory:
211
+ - vuln
212
+ likelihood: MEDIUM
213
+ impact: HIGH
214
+ confidence: MEDIUM
215
+ technology:
216
+ - kotlin
217
+ patterns:
218
+ - pattern-either:
219
+ - pattern: Cipher.getInstance("AES/ECB/...")
220
+ - pattern: Cipher.getInstance("AES")
221
+ - id: narvy.kotlin.crypto.null-cipher.null-cipher
222
+ message: '`javax.crypto.NullCipher` performs no encryption at all; every byte passes through unchanged. It exists purely
223
+ for testing pipelines that expect a `Cipher` object. Shipping it in a production code path that handles real data is equivalent
224
+ to storing/transmitting plaintext (CWE-327).'
225
+ severity: ERROR
226
+ languages:
227
+ - kotlin
228
+ metadata:
229
+ category: security
230
+ cwe:
231
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
232
+ owasp:
233
+ - A02:2021 - Cryptographic Failures
234
+ subcategory:
235
+ - vuln
236
+ likelihood: LOW
237
+ impact: HIGH
238
+ confidence: HIGH
239
+ technology:
240
+ - kotlin
241
+ patterns:
242
+ - pattern-either:
243
+ - pattern: NullCipher()
244
+ - pattern: javax.crypto.NullCipher()
245
+ - id: narvy.kotlin.crypto.weak-symmetric-cipher.weak-symmetric-cipher
246
+ message: 'DES / 3DES(DESede) / RC2 / RC4 are broken or insufficient for modern use: DES''s 56-bit key is brute-forceable
247
+ in hours, RC2/RC4 have known keystream biases, and 3DES''s 64-bit block size is vulnerable to birthday attacks (Sweet32)
248
+ (CWE-327). Use AES-256 in GCM mode instead.'
249
+ severity: WARNING
250
+ languages:
251
+ - kotlin
252
+ metadata:
253
+ category: security
254
+ cwe:
255
+ - 'CWE-327: Use of a Broken or Risky Cryptographic Algorithm'
256
+ - 'CWE-326: Inadequate Encryption Strength'
257
+ owasp:
258
+ - A02:2021 - Cryptographic Failures
259
+ subcategory:
260
+ - vuln
261
+ likelihood: LOW
262
+ impact: HIGH
263
+ confidence: HIGH
264
+ technology:
265
+ - kotlin
266
+ patterns:
267
+ - pattern-either:
268
+ - pattern: Cipher.getInstance("DES")
269
+ - pattern: Cipher.getInstance("DESede")
270
+ - pattern: Cipher.getInstance("DESede/...")
271
+ - pattern: Cipher.getInstance("RC2")
272
+ - pattern: Cipher.getInstance("RC4")
273
+ - pattern: KeyGenerator.getInstance("DES")
274
+ - pattern: KeyGenerator.getInstance("DESede")
275
+ - id: narvy.kotlin.crypto.rsa-ecb-nopadding-cipher
276
+ message: RSA is used with `NoPadding` (raw textbook RSA) instead of OAEP. Textbook RSA is deterministic and malleable, and
277
+ an attacker who can submit chosen ciphertexts to a decryption oracle can recover the plaintext (Bleichenbacher-style attacks)
278
+ (CWE-780). Use `RSA/ECB/OAEPWithSHA-256AndMGF1Padding`.
279
+ severity: ERROR
280
+ languages:
281
+ - kotlin
282
+ metadata:
283
+ category: security
284
+ cwe:
285
+ - 'CWE-780: Use of RSA Algorithm without OAEP'
286
+ owasp:
287
+ - A02:2021 - Cryptographic Failures
288
+ subcategory:
289
+ - vuln
290
+ likelihood: LOW
291
+ impact: HIGH
292
+ confidence: HIGH
293
+ technology:
294
+ - kotlin
295
+ patterns:
296
+ - pattern-either:
297
+ - pattern: Cipher.getInstance("RSA/ECB/NoPadding")
298
+ - pattern: Cipher.getInstance("RSA/None/NoPadding")
299
+ - id: narvy.kotlin.crypto.weak-rsa-keysize.weak-rsa-keysize
300
+ message: An RSA `KeyPairGenerator` is initialised with a key size below 2048 bits. NIST deprecated 1024-bit RSA in 2013
301
+ (CWE-326). Initialise with 2048 bits minimum (3072+ for long-lived keys).
302
+ severity: WARNING
303
+ languages:
304
+ - kotlin
305
+ metadata:
306
+ category: security
307
+ cwe:
308
+ - 'CWE-326: Inadequate Encryption Strength'
309
+ owasp:
310
+ - A02:2021 - Cryptographic Failures
311
+ subcategory:
312
+ - vuln
313
+ likelihood: LOW
314
+ impact: HIGH
315
+ confidence: HIGH
316
+ technology:
317
+ - kotlin
318
+ patterns:
319
+ - pattern-either:
320
+ - pattern: 'val $KEY = $G.getInstance("RSA")
321
+
322
+ ...
323
+
324
+ $KEY.initialize($BITS, ...)
325
+
326
+ '
327
+ - pattern: 'var $KEY = $G.getInstance("RSA")
328
+
329
+ ...
330
+
331
+ $KEY.initialize($BITS, ...)
332
+
333
+ '
334
+ - pattern: 'val $KEY = $G.getInstance("RSA")
335
+
336
+ ...
337
+
338
+ $KEY.initialize($BITS)
339
+
340
+ '
341
+ - pattern: 'var $KEY = $G.getInstance("RSA")
342
+
343
+ ...
344
+
345
+ $KEY.initialize($BITS)
346
+
347
+ '
348
+ - metavariable-comparison:
349
+ metavariable: $BITS
350
+ comparison: $BITS < 2048
351
+ - id: narvy.kotlin.crypto.insecure-random.insecure-random
352
+ message: '`kotlin.random.Random` / `java.util.Random` / `Math.random()` are predictable PRNGs once a handful of outputs
353
+ are observed. Used to seed a token, password reset code, or any other security-relevant value, an attacker can reconstruct
354
+ past or future outputs (CWE-330, CWE-338). Use `java.security.SecureRandom` for anything that must be unpredictable.'
355
+ severity: WARNING
356
+ languages:
357
+ - kotlin
358
+ metadata:
359
+ category: security
360
+ cwe:
361
+ - 'CWE-330: Use of Insufficiently Random Values'
362
+ - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)'
363
+ owasp:
364
+ - A02:2021 - Cryptographic Failures
365
+ subcategory:
366
+ - audit
367
+ likelihood: MEDIUM
368
+ impact: MEDIUM
369
+ confidence: MEDIUM
370
+ technology:
371
+ - kotlin
372
+ patterns:
373
+ - pattern-either:
374
+ - pattern: Random.nextLong()
375
+ - pattern: Random.nextInt(...)
376
+ - pattern: Random.Default.nextLong()
377
+ - pattern: Math.random()
378
+ - pattern: java.util.Random()
379
+ - pattern-not: SecureRandom()
380
+ - pattern-not: java.security.SecureRandom()
381
+ - id: narvy.kotlin.sqli.raw-sql-string-template.raw-sql-string-template
382
+ message: >-
383
+ A SQL string built with Kotlin string-template interpolation (`"SELECT
384
+ ... WHERE x = $var"` or `"${expr}"`) is passed directly to a JDBC
385
+ `Statement`/`Connection.prepareStatement` or an Exposed
386
+ `TransactionManager.exec(...)` call. Interpolation happens before the
387
+ driver ever sees the string, so a tainted value here is spliced straight
388
+ into the SQL grammar - the same risk as `+` concatenation (CWE-89). Use
389
+ `?` placeholders with bound parameters instead of interpolating the value
390
+ into the query text.
391
+ severity: ERROR
392
+ languages:
393
+ - kotlin
394
+ metadata:
395
+ category: security
396
+ cwe:
397
+ - 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command (''SQL Injection'')'
398
+ owasp:
399
+ - A03:2021 - Injection
400
+ subcategory:
401
+ - vuln
402
+ likelihood: HIGH
403
+ impact: HIGH
404
+ confidence: MEDIUM
405
+ technology:
406
+ - kotlin
407
+ patterns:
408
+ - pattern-either:
409
+ - pattern: $CONN.prepareStatement("...${$X}...")
410
+ - pattern: $STMT.executeQuery("...${$X}...")
411
+ - pattern: $STMT.executeUpdate("...${$X}...")
412
+ - pattern: $TM.current().exec("...${$X}...")
413
+ - pattern: TransactionManager.current().exec("...${$X}...")
@@ -0,0 +1,61 @@
1
+ rules:
2
+
3
+ # ASP.NET config hardening (web.config/attributes): request validation off, debug compilation on.
4
+ # Generic mode.
5
+
6
+ - id: narvy.csharp.config.request-validation-disabled.request-validation-disabled
7
+ message: >-
8
+ ASP.NET request validation is disabled (`validateRequest="false"` in
9
+ web.config, or `[ValidateInput(false)]` on a controller/action). Request
10
+ validation is the framework's built-in first line against reflected XSS
11
+ and script injection in posted values; turning it off removes that
12
+ safety net for every affected request (CWE-20, CWE-79). Leave it on and
13
+ encode output at the point of use instead of disabling validation
14
+ wholesale.
15
+ severity: WARNING
16
+ languages: [generic]
17
+ paths:
18
+ include:
19
+ - "*.config"
20
+ - "*.cs"
21
+ metadata:
22
+ category: security
23
+ cwe:
24
+ - "CWE-20: Improper Input Validation"
25
+ owasp:
26
+ - "A03:2021 - Injection"
27
+ subcategory: [audit]
28
+ likelihood: LOW
29
+ impact: MEDIUM
30
+ confidence: MEDIUM
31
+ technology: [csharp, dotnet, asp.net]
32
+ patterns:
33
+ - pattern-either:
34
+ - pattern-regex: 'validateRequest\s*=\s*"false"'
35
+ - pattern-regex: 'ValidateInput\s*\(\s*false\s*\)'
36
+
37
+ - id: narvy.csharp.config.debug-compilation-enabled.debug-compilation-enabled
38
+ message: >-
39
+ `<compilation debug="true">` is set in web.config. Debug compilation
40
+ disables request timeouts, emits verbose error pages that leak stack
41
+ traces and source paths, and produces non-optimized, larger binaries -
42
+ none of which belong in a deployed application (CWE-11, CWE-489). Set
43
+ `debug="false"` for anything past local development.
44
+ severity: WARNING
45
+ languages: [generic]
46
+ paths:
47
+ include:
48
+ - "*.config"
49
+ metadata:
50
+ category: security
51
+ cwe:
52
+ - "CWE-11: ASP.NET Misconfiguration: Creating Debug Binary"
53
+ owasp:
54
+ - "A05:2021 - Security Misconfiguration"
55
+ subcategory: [audit]
56
+ likelihood: LOW
57
+ impact: MEDIUM
58
+ confidence: HIGH
59
+ technology: [csharp, dotnet, asp.net]
60
+ patterns:
61
+ - pattern-regex: '<compilation[^>]*\bdebug\s*=\s*"true"'
@@ -0,0 +1,64 @@
1
+ rules:
2
+
3
+ # C#/.NET weak crypto: broken hashes (MD5/SHA-1) and broken/legacy ciphers (DES/3DES/RC2).
4
+
5
+ - id: narvy.csharp.crypto.weak-hash.weak-hash
6
+ message: >-
7
+ A cryptographically broken hash algorithm (MD5 or SHA-1) is instantiated.
8
+ Both have practical collision attacks and must not be used for
9
+ signatures, integrity of security-relevant data, or password hashing
10
+ (CWE-327, CWE-328). Use SHA-256 or better for integrity; for passwords
11
+ use a memory-hard KDF such as PBKDF2 (`Rfc2898DeriveBytes`), bcrypt or
12
+ Argon2.
13
+ severity: WARNING
14
+ languages: [csharp]
15
+ metadata:
16
+ category: security
17
+ cwe:
18
+ - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
19
+ - "CWE-328: Use of Weak Hash"
20
+ owasp:
21
+ - "A02:2021 - Cryptographic Failures"
22
+ subcategory: [vuln]
23
+ likelihood: MEDIUM
24
+ impact: MEDIUM
25
+ confidence: HIGH
26
+ technology: [csharp, dotnet]
27
+ patterns:
28
+ - pattern-either:
29
+ - pattern: MD5.Create(...)
30
+ - pattern: SHA1.Create(...)
31
+ - pattern: new MD5CryptoServiceProvider(...)
32
+ - pattern: new SHA1CryptoServiceProvider(...)
33
+ - pattern: new MD5Cng(...)
34
+ - pattern: new SHA1Managed(...)
35
+ - pattern: System.Security.Cryptography.MD5.Create(...)
36
+ - pattern: System.Security.Cryptography.SHA1.Create(...)
37
+
38
+ - id: narvy.csharp.crypto.weak-cipher.weak-cipher
39
+ message: >-
40
+ A broken or legacy symmetric cipher (DES, Triple-DES, or RC2) is
41
+ instantiated. DES and RC2 have inadequate key sizes and Triple-DES is
42
+ deprecated (SWEET32 birthday attack on its 64-bit block) (CWE-327).
43
+ Use AES (`Aes.Create()`) with an authenticated mode such as AES-GCM.
44
+ severity: WARNING
45
+ languages: [csharp]
46
+ metadata:
47
+ category: security
48
+ cwe:
49
+ - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
50
+ owasp:
51
+ - "A02:2021 - Cryptographic Failures"
52
+ subcategory: [vuln]
53
+ likelihood: MEDIUM
54
+ impact: MEDIUM
55
+ confidence: HIGH
56
+ technology: [csharp, dotnet]
57
+ patterns:
58
+ - pattern-either:
59
+ - pattern: new DESCryptoServiceProvider(...)
60
+ - pattern: new TripleDESCryptoServiceProvider(...)
61
+ - pattern: new RC2CryptoServiceProvider(...)
62
+ - pattern: DES.Create(...)
63
+ - pattern: TripleDES.Create(...)
64
+ - pattern: RC2.Create(...)
@@ -0,0 +1,59 @@
1
+ rules:
2
+
3
+ # C#/.NET unsafe deserialization: BinaryFormatter and Json.NET polymorphic TypeNameHandling.
4
+
5
+ - id: narvy.csharp.deserialization.binary-formatter.binary-formatter
6
+ message: >-
7
+ `BinaryFormatter` is used. It deserializes the concrete .NET types named
8
+ in the payload, so on any attacker-influenced data it is a
9
+ remote-code-execution gadget - Microsoft has deprecated it and made it
10
+ throw by default from .NET 5+ precisely because it cannot be made safe
11
+ (CWE-502). Replace it with a contract-based serializer that does not
12
+ embed types, such as `System.Text.Json` or `DataContractSerializer` over
13
+ a known type.
14
+ severity: ERROR
15
+ languages: [csharp]
16
+ metadata:
17
+ category: security
18
+ cwe:
19
+ - "CWE-502: Deserialization of Untrusted Data"
20
+ owasp:
21
+ - "A08:2021 - Software and Data Integrity Failures"
22
+ subcategory: [vuln]
23
+ likelihood: MEDIUM
24
+ impact: HIGH
25
+ confidence: HIGH
26
+ technology: [csharp, dotnet]
27
+ patterns:
28
+ - pattern-either:
29
+ - pattern: new BinaryFormatter(...)
30
+ - pattern: new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(...)
31
+
32
+ - id: narvy.csharp.deserialization.json-net-typenamehandling.json-net-typenamehandling
33
+ message: >-
34
+ Json.NET (`Newtonsoft.Json`) is configured with a permissive
35
+ `TypeNameHandling` (`All`, `Auto`, `Objects`, or `Arrays`). That makes
36
+ the serializer honour a `$type` field in the JSON and instantiate the
37
+ named type, which an attacker can point at a gadget class to achieve
38
+ remote code execution (CWE-502). Use `TypeNameHandling.None`, or, if
39
+ polymorphism is genuinely required, pin a strict `SerializationBinder`
40
+ that allow-lists the expected types.
41
+ severity: ERROR
42
+ languages: [csharp]
43
+ metadata:
44
+ category: security
45
+ cwe:
46
+ - "CWE-502: Deserialization of Untrusted Data"
47
+ owasp:
48
+ - "A08:2021 - Software and Data Integrity Failures"
49
+ subcategory: [vuln]
50
+ likelihood: MEDIUM
51
+ impact: HIGH
52
+ confidence: MEDIUM
53
+ technology: [csharp, dotnet, newtonsoft]
54
+ patterns:
55
+ - pattern-either:
56
+ - pattern: TypeNameHandling.All
57
+ - pattern: TypeNameHandling.Auto
58
+ - pattern: TypeNameHandling.Objects
59
+ - pattern: TypeNameHandling.Arrays