You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(rules): improve precision of 4 high-FP dotnet opengrep rules (#63)
* fix(rules): improve precision of 4 high-FP dotnet opengrep rules
Addresses customer SAST evaluation feedback where 4 rules produced 150/170
false positives (88% of all FPs), inflating the reported FP rate to 91%.
Rules fixed:
- dotnet-xss-response-write: Convert to taint mode. Previously matched any
.Write() call including Serilog ITextFormatter log sinks. Now requires
data flow from user input sources to Response.Write sinks.
- dotnet-hardcoded-credentials: Add value inspection and credential API
patterns. Previously matched on variable names alone, flagging config
key paths like "UseCaptchaOnResetPassword".
- dotnet-crypto-failures: Target actual weak algorithms (3DES, DES, RC2,
RijndaelManaged) instead of Encoding.UTF8.GetBytes() which flagged the
recommended SHA256.HashData(Encoding.UTF8.GetBytes(...)) pattern.
- dotnet-path-traversal: Convert to taint mode. Previously matched all
Path.Combine() calls including those using framework-provided paths
like _env.WebRootPath.
Validated with opengrep v1.19.0 against NIST Juliet C# test suite:
xss-response-write: Prec 41.6% -> 100%, Recall 47.8% -> 24.3%
hardcoded-credentials: Prec 0.0% -> 100%, Recall 0.0% -> 3.6%
crypto-failures: Prec 36.7% -> 100%, Recall 51.4% -> 50.0%
path-traversal: Prec 0.0% -> 100%, Recall 0.0% -> 45.2%
* fix(rules): add ASP.NET Core taint sources and System.IO sinks to dotnet rules
Add controller parameter binding sources ([FromQuery], [FromBody],
[FromRoute], [FromForm]) and IFormFile.FileName to path-traversal
and XSS taint rules. Add Response.WriteAsync and Html.Raw as XSS
sinks. Add fully-qualified System.IO.File.* sink variants for
ASP.NET Core code that uses explicit namespace qualification.
E2E tested against two vulnerable .NET repos: 7 true positives
found, zero false positives.
* fix(rules): address review feedback on dotnet rule precision
- Remove Path.GetFullPath() as path-traversal sanitizer (normalizes but
does not prevent traversal on its own)
- Broaden hardcoded-credentials variable regex to cover idiomatic C#
naming: apiKey, connectionString, privateKey, accessKey, authToken
- Remove overly broad Base64 encoding pattern from crypto-failures
(benign encoding/transport use generates noise)
* fix(rules): correct path-traversal StartsWith sanitizer in dotnet rule
The $X.StartsWith($BASE) sanitizer was matching the boolean expression
instead of marking the checked path variable as sanitized, so correctly
validated paths were still flagged as tainted.
Use focus-metavariable + by-side-effect so the sanitizer applies to $X
itself. Verified with a synthetic test case: scans of an unsanitized
File.ReadAllText still fire, but the same call guarded by
full.StartsWith("/var/data/") no longer does. Juliet CWE-23/36 results
unchanged at 432 findings (Juliet test cases do not exercise StartsWith
validation). opengrep --validate and pytest pass.
# Hardcoded credentials - matches both variable-name patterns AND credential API usage
145
145
- id: dotnet-hardcoded-credentials
146
146
message: "Hard-coded credentials detected. Embedding secrets in source code makes them easily discoverable and impossible to rotate. Use environment variables or a secrets manager instead."
# Pattern 2: Credential APIs called with hardcoded string literals
171
+
- pattern: new NetworkCredential($USER, "...", ...)
172
+
- pattern: new NetworkCredential("...", "...", ...)
173
+
- pattern: new SqlConnection("...");
174
+
- pattern: new PasswordDeriveBytes("...", ...)
161
175
metadata:
162
176
category: security
163
177
cwe: CWE-798
@@ -223,35 +237,183 @@ rules:
223
237
owasp: "A07:2021"
224
238
fix: "Never return true from ServerCertificateCustomValidationCallback. Use the default certificate validation from ServicePointManager."
225
239
226
-
# XSS vulnerabilities
240
+
# XSS vulnerabilities - taint mode for accurate user-input tracking
227
241
- id: dotnet-xss-response-write
228
242
message: "Cross-site scripting (XSS) vulnerability detected. User input is rendered in HTML output without proper escaping, allowing attackers to inject malicious scripts. Sanitize or escape all user input before rendering."
# HttpResponse parameter pattern (Juliet, ASP.NET handlers)
310
+
- pattern: $RESP.Write(...)
311
+
- pattern: $RESP.WriteAsync(...)
312
+
# Razor unencoded output
313
+
- pattern: Html.Raw(...)
314
+
pattern-sanitizers:
315
+
- pattern-either:
316
+
- pattern: HttpUtility.HtmlEncode(...)
317
+
- pattern: HtmlEncoder.Default.Encode(...)
318
+
- pattern: WebUtility.HtmlEncode(...)
319
+
- pattern: Server.HtmlEncode(...)
320
+
- pattern: AntiXssEncoder.HtmlEncode(...)
235
321
metadata:
236
322
category: security
237
323
cwe: CWE-79
238
-
confidence: medium
324
+
confidence: high
239
325
subcategory: xss
240
326
vulnerability_class: "Cross-Site Scripting (XSS)"
241
327
owasp: "A03:2021"
242
328
fix: "Use Razor auto-encoding or HtmlEncoder.Default.Encode(). Never use Html.Raw() with user input. Validate input on both client and server."
243
329
244
-
# Path traversal
330
+
# Path traversal - taint mode for accurate user-input tracking
245
331
- id: dotnet-path-traversal
246
332
message: "Path traversal vulnerability detected. User input is used in file paths without validation, allowing attackers to access files outside the intended directory. Validate and canonicalize paths before use."
# Fully-qualified System.IO variants (common in ASP.NET Core)
396
+
- pattern: System.IO.File.ReadAllText(...)
397
+
- pattern: System.IO.File.ReadAllBytes(...)
398
+
- pattern: System.IO.File.WriteAllText(...)
399
+
- pattern: System.IO.File.WriteAllBytes(...)
400
+
- pattern: System.IO.File.Exists(...)
401
+
- pattern: System.IO.File.Open(...)
402
+
- pattern: System.IO.File.Delete(...)
403
+
- pattern: new FileStream(...)
404
+
- pattern: new StreamReader(...)
405
+
- pattern: new StreamWriter(...)
406
+
- pattern: Directory.GetFiles(...)
407
+
- pattern: Directory.EnumerateFiles(...)
408
+
pattern-sanitizers:
409
+
- pattern: Path.GetFileName(...)
410
+
# Treat the checked path variable as sanitized after a base-path validation.
411
+
# focus-metavariable + by-side-effect cleans $X itself, not just the
412
+
# StartsWith(...) boolean expression.
413
+
- patterns:
414
+
- pattern: $X.StartsWith($BASE)
415
+
- focus-metavariable: $X
416
+
by-side-effect: true
255
417
metadata:
256
418
category: security
257
419
cwe: CWE-22
@@ -623,23 +785,32 @@ rules:
623
785
vulnerability_class: "Access Control Violation"
624
786
fix: "Review authorization logic for bypass conditions. Use policy-based authorization with IAuthorizationHandler. Test authorization with different user roles."
625
787
626
-
# A02: Cryptographic Failures
788
+
# A02: Cryptographic Failures - targets actual weak algorithm usage
627
789
- id: dotnet-crypto-failures
628
790
message: "Weak cryptographic algorithm detected. Using broken or outdated algorithms may allow attackers to decrypt data or forge signatures. Use modern algorithms like AES-256, SHA-256, or Ed25519."
# Using raw password bytes directly as crypto key (no KDF)
634
804
- pattern: new RijndaelManaged() { Key = Encoding.UTF8.GetBytes($KEY) }
805
+
- pattern: new AesCryptoServiceProvider() { Key = Encoding.UTF8.GetBytes($KEY) }
635
806
metadata:
636
807
category: security
637
808
owasp: A02
638
809
cwe: CWE-327
639
-
confidence: medium
810
+
confidence: high
640
811
subcategory: crypto
641
812
vulnerability_class: "Cryptographic Weakness"
642
-
fix: "Use SHA256.Create() instead of MD5/SHA1. Use Aes.Create() with CipherMode.CBC or AesGcm for encryption."
813
+
fix: "Use Aes.Create() instead of 3DES/DES/RC2. Use Rfc2898DeriveBytes or HKDF for key derivation from passwords. Never use raw Encoding.GetBytes() as a crypto key."
0 commit comments