diff --git a/docs/VULNERABILITY_CATALOG.md b/docs/VULNERABILITY_CATALOG.md
index 5763d34..3b48698 100644
--- a/docs/VULNERABILITY_CATALOG.md
+++ b/docs/VULNERABILITY_CATALOG.md
@@ -7,12 +7,12 @@ from each file's header comment, so this page cannot drift from the source.
## Totals
-- **Test cases:** 62
-- **Expected detections:** 62
-- **`VULNERABLE:` markers:** 123 (individual lines a scanner should flag)
-- **`SAFE:` markers:** 73 (lines a scanner must not flag — the false-positive control group)
+- **Test cases:** 136
+- **Expected detections:** 136
+- **`VULNERABLE:` markers:** 209 (individual lines a scanner should flag)
+- **`SAFE:` markers:** 140 (lines a scanner must not flag — the false-positive control group)
- **Languages:** 8 — dotenv, go, java, javascript, json, python, ruby, text
-- **CWE categories:** 46 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-95, CWE-113, CWE-117, CWE-190, CWE-201, CWE-209, CWE-256, CWE-295, CWE-321, CWE-327, CWE-330, CWE-338, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-489, CWE-502, CWE-506, CWE-532, CWE-601, CWE-611, CWE-614, CWE-639, CWE-643, CWE-681, CWE-759, CWE-798, CWE-862, CWE-915, CWE-918, CWE-942, CWE-943, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357
+- **CWE categories:** 75 — CWE-20, CWE-22, CWE-23, CWE-77, CWE-78, CWE-79, CWE-89, CWE-90, CWE-95, CWE-113, CWE-117, CWE-190, CWE-200, CWE-201, CWE-209, CWE-256, CWE-281, CWE-284, CWE-285, CWE-287, CWE-295, CWE-306, CWE-307, CWE-311, CWE-312, CWE-319, CWE-321, CWE-326, CWE-327, CWE-330, CWE-338, CWE-345, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-400, CWE-426, CWE-434, CWE-444, CWE-470, CWE-476, CWE-489, CWE-494, CWE-502, CWE-506, CWE-532, CWE-601, CWE-611, CWE-614, CWE-617, CWE-626, CWE-639, CWE-643, CWE-681, CWE-693, CWE-754, CWE-759, CWE-770, CWE-787, CWE-798, CWE-835, CWE-862, CWE-912, CWE-915, CWE-918, CWE-942, CWE-943, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357
## How coverage is scored
@@ -26,17 +26,47 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
+| Authentication bypass via JWT algorithm confusion (none algorithm) | [`cwe-287-go.go`](../vulns/go/cwe-287-go.go) | CWE-287 | critical | yes | 1 vuln / 1 safe |
| OS command injection via exec.Command with a shell | [`cmd-injection-exec.go`](../vulns/go/cmd-injection-exec.go) | CWE-78 | critical | yes | 2 vuln / 1 safe |
+| CSV injection via user-controlled input written to a CSV file | [`cwe-1236-go.go`](../vulns/go/cwe-1236-go.go) | CWE-1236 | high | yes | 1 vuln / 1 safe |
+| Sensitive data (API key) is logged in plaintext | [`cwe-312-go.go`](../vulns/go/cwe-312-go.go) | CWE-312 | high | yes | 1 vuln / 1 safe |
+| JSON data integrity check bypass via missing signature verification | [`cwe-345-go.go`](../vulns/go/cwe-345-go.go) | CWE-345 | high | yes | 1 vuln / 2 safe |
+| CWE-346 Origin validation error via missing Origin header check in WebSocket handshake | [`cwe-346-go.go`](../vulns/go/cwe-346-go.go) | CWE-346 | high | yes | 2 vuln / 3 safe |
+| CWE-681 Incorrect Conversion between Numeric Types: float64 to int truncation | [`cwe-681-go.go`](../vulns/go/cwe-681-go.go) | CWE-681 | medium | yes | 1 vuln / 1 safe |
+| Unchecked error from file operation leads to inconsistent state | [`cwe-754-go.go`](../vulns/go/cwe-754-go.go) | CWE-754 | high | yes | 2 vuln / 1 safe |
+| Insecure URL rewrite via httputil.ReverseProxy with user-controlled target | [`cwe-942-go.go`](../vulns/go/cwe-942-go.go) | CWE-942 | high | yes | 1 vuln / 1 safe |
| Integer overflow and unchecked narrowing conversion | [`integer-overflow.go`](../vulns/go/integer-overflow.go) | CWE-190 | medium | yes | 2 vuln / 3 safe |
+| Integer overflow in arithmetic operation after parsing user input | [`cwe-190-go.go`](../vulns/go/cwe-190-go.go) | CWE-190 | high | yes | 4 vuln / 1 safe |
+| Missing authorization check on file read endpoint | [`cwe-862-go.go`](../vulns/go/cwe-862-go.go) | CWE-862 | high | yes | 1 vuln / 1 safe |
+| Nil pointer dereference on a response body that may be nil | [`cwe-476-go.go`](../vulns/go/cwe-476-go.go) | CWE-476 | high | yes | 2 vuln / 1 safe |
+| Open redirect via http.Redirect with user-controlled URL | [`cwe-601-go.go`](../vulns/go/cwe-601-go.go) | CWE-601 | medium | yes | 1 vuln / 1 safe |
+| Session fixation via predictable session ID in Set-Cookie | [`cwe-384-go.go`](../vulns/go/cwe-384-go.go) | CWE-384 | high | yes | 1 vuln / 1 safe |
| SQL injection via fmt.Sprintf | [`sqli-fmt-sprintf.go`](../vulns/go/sqli-fmt-sprintf.go) | CWE-89 | critical | yes | 2 vuln / 1 safe |
| Server-side request forgery via http.Get on a user-supplied URL | [`ssrf-http-get.go`](../vulns/go/ssrf-http-get.go) | CWE-918 | high | yes | 2 vuln / 2 safe |
+| Full stack trace leaked to client on unhandled error | [`stack-trace-exposed.go`](../vulns/go/stack-trace-exposed.go) | CWE-200 | medium | yes | 1 vuln / 0 safe |
+| TLS certificate verification disabled via InsecureSkipVerify | [`cwe-295-go.go`](../vulns/go/cwe-295-go.go) | CWE-295 | high | yes | 1 vuln / 1 safe |
## Java
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
+| Cleartext transmission of sensitive data over unencrypted channel | [`cwe-319-java.java`](../vulns/java/cwe-319-java.java) | CWE-319 | high | yes | 1 vuln / 1 safe |
| Insecure deserialisation via ObjectInputStream | [`deserialization-object-input-stream.java`](../vulns/java/deserialization-object-input-stream.java) | CWE-502 | critical | yes | 2 vuln / 2 safe |
+| Hardcoded database credentials in JDBC connection string | [`cwe-798-java.java`](../vulns/java/cwe-798-java.java) | CWE-798 | critical | yes | 1 vuln / 0 safe |
+| Hidden administrative backdoor endpoint behind an innocuous path | [`hidden-backdoor-endpoint.java`](../vulns/java/hidden-backdoor-endpoint.java) | CWE-912 | critical | yes | 1 vuln / 0 safe |
+| Insecure random UUID generation using java.util.Random for session identifiers | [`cwe-338-java.java`](../vulns/java/cwe-338-java.java) | CWE-338 | high | yes | 1 vuln / 0 safe |
+| Log injection via unsanitized user input in HTTP response logging | [`cwe-117-java.java`](../vulns/java/cwe-117-java.java) | CWE-117 | high | yes | 1 vuln / 0 safe |
+| Missing encryption of sensitive data in transit | [`cwe-311-java.java`](../vulns/java/cwe-311-java.java) | CWE-311 | high | yes | 1 vuln / 1 safe |
+| Plaintext password storage in HTTP Basic Authentication credentials | [`cwe-256-java.java`](../vulns/java/cwe-256-java.java) | CWE-256 | high | yes | 1 vuln / 0 safe |
+| Protection mechanism failure - missing authentication on sensitive endpoint | [`cwe-693-java.java`](../vulns/java/cwe-693-java.java) | CWE-693 | high | yes | 1 vuln / 0 safe |
+| Sensitive credit card data logged in plain text | [`cwe-532-java.java`](../vulns/java/cwe-532-java.java) | CWE-532 | high | yes | 1 vuln / 0 safe |
| SQL injection via Statement string concatenation | [`sqli-statement-concat.java`](../vulns/java/sqli-statement-concat.java) | CWE-89 | critical | yes | 2 vuln / 1 safe |
+| Server-Side Request Forgery via user-controlled URL in HttpURLConnection | [`cwe-918-java.java`](../vulns/java/cwe-918-java.java) | CWE-918 | high | yes | 1 vuln / 0 safe |
+| Insecure temporary file creation with predictable name and no atomic operation | [`cwe-377-java.java`](../vulns/java/cwe-377-java.java) | CWE-377 | high | yes | 1 vuln / 0 safe |
+| Unbounded accumulation of request bodies into memory | [`unbounded-request-collection.java`](../vulns/java/unbounded-request-collection.java) | CWE-400 | medium | yes | 1 vuln / 0 safe |
+| Unsafe reflection with user-controlled class name leading to arbitrary class instantiation | [`cwe-1357-java.java`](../vulns/java/cwe-1357-java.java) | CWE-1357 | high | yes | 1 vuln / 0 safe |
+| Unsafe reflection-based method invocation with user-controlled class name | [`cwe-470-java.java`](../vulns/java/cwe-470-java.java) | CWE-470 | high | yes | 1 vuln / 0 safe |
+| XPath injection via unsanitized user input in XML document query | [`cwe-643-java.java`](../vulns/java/cwe-643-java.java) | CWE-643 | high | yes | 1 vuln / 0 safe |
| Reflected XSS via HttpServletResponse writer | [`xss-response-writer.java`](../vulns/java/xss-response-writer.java) | CWE-79 | high | yes | 2 vuln / 2 safe |
| XXE via unconfigured DocumentBuilderFactory | [`xxe-document-builder.java`](../vulns/java/xxe-document-builder.java) | CWE-611 | high | yes | 2 vuln / 1 safe |
@@ -44,25 +74,40 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
+| Login endpoint without rate limiting or lockout | [`bruteforce-no-rate-limit.js`](../vulns/javascript/bruteforce-no-rate-limit.js) | CWE-307 | medium | yes | 2 vuln / 0 safe |
+| Unsafe buffer copy without bounds checking | [`cwe-787-javascript.js`](../vulns/javascript/cwe-787-javascript.js) | CWE-787 | high | yes | 1 vuln / 0 safe |
+| User input passed directly to eval() for arithmetic calculation | [`cwe-95-javascript.js`](../vulns/javascript/cwe-95-javascript.js) | CWE-95 | critical | yes | 1 vuln / 0 safe |
+| Command injection via unsanitized user input in exec() | [`cwe-78-javascript.js`](../vulns/javascript/cwe-78-javascript.js) | CWE-78 | critical | yes | 1 vuln / 0 safe |
+| Command injection via shelljs exec with unsanitized input | [`command-injection-shelljs.js`](../vulns/javascript/command-injection-shelljs.js) | CWE-77 | high | yes | 1 vuln / 1 safe |
| Sensitive session cookie without the Secure attribute | [`cookie-security-flags.js`](../vulns/javascript/cookie-security-flags.js) | CWE-614 | medium | yes | 1 vuln / 1 safe |
| Credentialed CORS configured with a wildcard origin | [`cors-wildcard-credentials.js`](../vulns/javascript/cors-wildcard-credentials.js) | CWE-942 | high | yes | 1 vuln / 1 safe |
| CSRF via missing anti-CSRF token on state-changing POST | [`csrf-missing-token.js`](../vulns/javascript/csrf-missing-token.js) | CWE-352 | high | yes | 3 vuln / 1 safe |
+| State-changing POST endpoint without CSRF token validation | [`cwe-352-javascript.js`](../vulns/javascript/cwe-352-javascript.js) | CWE-352 | high | yes | 1 vuln / 0 safe |
+| Error response includes full stack trace and internal path | [`cwe-201-javascript.js`](../vulns/javascript/cwe-201-javascript.js) | CWE-201 | medium | yes | 1 vuln / 0 safe |
+| Session cookie set without Secure flag over HTTP | [`cwe-614-javascript.js`](../vulns/javascript/cwe-614-javascript.js) | CWE-614 | high | yes | 1 vuln / 0 safe |
| Hardcoded cryptographic key used for application encryption | [`hardcoded-crypto-key.js`](../vulns/javascript/hardcoded-crypto-key.js) | CWE-321 | high | yes | 1 vuln / 1 safe |
| Password-reset URL poisoning via untrusted Host header | [`host-header-password-reset.js`](../vulns/javascript/host-header-password-reset.js) | CWE-346 | high | yes | 1 vuln / 1 safe |
| HTTP response splitting via unsanitized header value | [`http-header-injection.js`](../vulns/javascript/http-header-injection.js) | CWE-113 | high | yes | 1 vuln / 1 safe |
| IDOR via unscoped object lookup | [`idor-unscoped-object-lookup.js`](../vulns/javascript/idor-unscoped-object-lookup.js) | CWE-639 | high | yes | 1 vuln / 1 safe |
+| Uncontrolled loop condition leading to denial of service | [`cwe-617-javascript.js`](../vulns/javascript/cwe-617-javascript.js) | CWE-617 | high | yes | 1 vuln / 0 safe |
+| Unsafe deserialization of user-controlled JSON into a JavaScript object | [`cwe-502-javascript.js`](../vulns/javascript/cwe-502-javascript.js) | CWE-502 | high | yes | 1 vuln / 0 safe |
+| File upload endpoint checks only ownership, not shared-resource permissions | [`cwe-281-javascript.js`](../vulns/javascript/cwe-281-javascript.js) | CWE-281 | high | yes | 1 vuln / 0 safe |
| Predictable security token generated with Math.random | [`insecure-random-token.js`](../vulns/javascript/insecure-random-token.js) | CWE-330 | high | yes | 1 vuln / 1 safe |
| JWT signature validation bypass via decode-only parsing | [`jwt-decode-without-verify.js`](../vulns/javascript/jwt-decode-without-verify.js) | CWE-347 | high | yes | 1 vuln / 1 safe |
+| LDAP search filter built from user input without sanitization | [`cwe-90-javascript.js`](../vulns/javascript/cwe-90-javascript.js) | CWE-90 | high | yes | 1 vuln / 0 safe |
| Log injection via untrusted request metadata | [`log-injection.js`](../vulns/javascript/log-injection.js) | CWE-117 | medium | yes | 1 vuln / 1 safe |
| Mass assignment through Object.assign with request data | [`mass-assignment-object-assign.js`](../vulns/javascript/mass-assignment-object-assign.js) | CWE-915 | high | yes | 1 vuln / 1 safe |
| MongoDB NoSQL injection via attacker-controlled query object | [`nosql-injection-mongodb.js`](../vulns/javascript/nosql-injection-mongodb.js) | CWE-943 | high | yes | 1 vuln / 1 safe |
| Open redirect via unvalidated next parameter | [`open-redirect.js`](../vulns/javascript/open-redirect.js) | CWE-601 | medium | yes | 3 vuln / 1 safe |
| Prototype pollution via recursive merge | [`prototype-pollution.js`](../vulns/javascript/prototype-pollution.js) | CWE-1321 | high | yes | 2 vuln / 1 safe |
| OS command injection via child_process.exec | [`rce-child-process.js`](../vulns/javascript/rce-child-process.js) | CWE-78 | critical | yes | 2 vuln / 1 safe |
+| Regular expression with catastrophic backtracking on user input | [`cwe-1333-javascript.js`](../vulns/javascript/cwe-1333-javascript.js) | CWE-1333 | high | yes | 1 vuln / 0 safe |
| Session fixation when login reuses the anonymous session ID | [`session-fixation-login.js`](../vulns/javascript/session-fixation-login.js) | CWE-384 | high | yes | 1 vuln / 1 safe |
| SQL injection via string concatenation | [`sqli-raw-concat.js`](../vulns/javascript/sqli-raw-concat.js) | CWE-89 | critical | yes | 2 vuln / 1 safe |
| Server-side request forgery via user-supplied URL | [`ssrf-request-user-url.js`](../vulns/javascript/ssrf-request-user-url.js) | CWE-918 | high | yes | 2 vuln / 2 safe |
| TLS certificate validation disabled on an HTTPS agent | [`tls-reject-unauthorized-false.js`](../vulns/javascript/tls-reject-unauthorized-false.js) | CWE-295 | high | yes | 1 vuln / 1 safe |
+| File upload endpoint accepting executable content without validation | [`cwe-434-javascript.js`](../vulns/javascript/cwe-434-javascript.js) | CWE-434 | critical | yes | 1 vuln / 0 safe |
+| Using DES for symmetric encryption | [`cwe-327-javascript.js`](../vulns/javascript/cwe-327-javascript.js) | CWE-327 | high | yes | 1 vuln / 0 safe |
| Reflected XSS via innerHTML | [`xss-dom-innerHTML.js`](../vulns/javascript/xss-dom-innerHTML.js) | CWE-79 | high | yes | 2 vuln / 1 safe |
| Code injection via eval() of user input | [`xss-eval-user-input.js`](../vulns/javascript/xss-eval-user-input.js) | CWE-95 | critical | yes | 3 vuln / 1 safe |
@@ -71,9 +116,17 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
| CSV formula injection from untrusted spreadsheet cells | [`csv-formula-injection.py`](../vulns/python/csv-formula-injection.py) | CWE-1236 | medium | yes | 1 vuln / 1 safe |
+| Generator option confusion leading to unsafe bytecode generation | [`cwe-626-python.py`](../vulns/python/cwe-626-python.py) | CWE-626 | high | yes | 1 vuln / 1 safe |
+| Error message disclosure in HTTP exception response | [`cwe-209-python.py`](../vulns/python/cwe-209-python.py) | CWE-209 | medium | yes | 1 vuln / 1 safe |
+| Infinite loop from attacker-controlled loop bound | [`cwe-835-python.py`](../vulns/python/cwe-835-python.py) | CWE-835 | high | yes | 1 vuln / 1 safe |
+| Unsafe deserialization of attacker-controlled pickle data | [`cwe-915-python.py`](../vulns/python/cwe-915-python.py) | CWE-915 | critical | yes | 1 vuln / 1 safe |
+| Embedded backdoor in authentication logic | [`cwe-506-python.py`](../vulns/python/cwe-506-python.py) | CWE-506 | critical | yes | 1 vuln / 1 safe |
| Excessive user-record exposure in an API response | [`excessive-data-exposure.py`](../vulns/python/excessive-data-exposure.py) | CWE-201 | high | yes | 1 vuln / 1 safe |
| Flask debug mode enabled in application configuration | [`flask-debug-enabled.py`](../vulns/python/flask-debug-enabled.py) | CWE-489 | high | yes | 1 vuln / 1 safe |
| Hardcoded secret used to configure session signing | [`hardcoded-session-secret.py`](../vulns/python/hardcoded-session-secret.py) | CWE-798 | high | yes | 1 vuln / 1 safe |
+| HTTP response header injection via unsanitized redirect parameter | [`cwe-113-python.py`](../vulns/python/cwe-113-python.py) | CWE-113 | high | yes | 1 vuln / 1 safe |
+| HTTP request smuggling via Content-Length and Transfer-Encoding conflict | [`cwe-444-python.py`](../vulns/python/cwe-444-python.py) | CWE-444 | high | yes | 1 vuln / 1 safe |
+| Insecure direct object reference in user profile update endpoint | [`cwe-639-python.py`](../vulns/python/cwe-639-python.py) | CWE-639 | high | yes | 1 vuln / 2 safe |
| Security tokens derived from a predictable PRNG | [`insecure-random-token.py`](../vulns/python/insecure-random-token.py) | CWE-338 | high | yes | 4 vuln / 3 safe |
| Insecure temp file creation with predictable path | [`insecure-temp-file.py`](../vulns/python/insecure-temp-file.py) | CWE-377 | medium | yes | 3 vuln / 1 safe |
| LDAP injection via unescaped search filter | [`ldap-injection.py`](../vulns/python/ldap-injection.py) | CWE-90 | high | yes | 1 vuln / 1 safe |
@@ -82,24 +135,45 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Path traversal via unvalidated filename in open() | [`path-traversal-open.py`](../vulns/python/path-traversal-open.py) | CWE-22 | high | yes | 2 vuln / 2 safe |
| Insecure deserialisation via pickle / yaml.load | [`pickle-deserialization.py`](../vulns/python/pickle-deserialization.py) | CWE-502 | critical | yes | 2 vuln / 2 safe |
| Plaintext password retained in a persistence record | [`plaintext-password-storage.py`](../vulns/python/plaintext-password-storage.py) | CWE-256 | critical | yes | 1 vuln / 1 safe |
+| TOCTOU race condition on file existence check before write | [`cwe-362-python.py`](../vulns/python/cwe-362-python.py) | CWE-362 | medium | yes | 1 vuln / 1 safe |
| OS command injection via os.system / subprocess shell=True | [`rce-os-system.py`](../vulns/python/rce-os-system.py) | CWE-78 | critical | yes | 3 vuln / 1 safe |
| ReDoS via catastrophic backtracking regex on user input | [`redos-catastrophic-regex.py`](../vulns/python/redos-catastrophic-regex.py) | CWE-1333 | high | yes | 3 vuln / 1 safe |
| SQL injection via string formatting | [`sqli-string-format.py`](../vulns/python/sqli-string-format.py) | CWE-89 | critical | yes | 3 vuln / 1 safe |
| Server-side request forgery via requests.get on user-supplied URL | [`ssrf-requests-user-url.py`](../vulns/python/ssrf-requests-user-url.py) | CWE-918 | high | yes | 2 vuln / 1 safe |
| Sensitive information exposure via raw stack trace in HTTP response | [`stack-trace-exposure.py`](../vulns/python/stack-trace-exposure.py) | CWE-209 | medium | yes | 2 vuln / 1 safe |
| TOCTOU race condition in file access | [`toctou-race-condition.py`](../vulns/python/toctou-race-condition.py) | CWE-362 | medium | yes | 3 vuln / 2 safe |
+| Unsafe deserialization of untrusted YAML input | [`cwe-1336-python.py`](../vulns/python/cwe-1336-python.py) | CWE-1336 | high | yes | 1 vuln / 1 safe |
| Weak cryptographic algorithms for integrity and confidentiality | [`weak-crypto-md5.py`](../vulns/python/weak-crypto-md5.py) | CWE-327 | high | yes | 5 vuln / 2 safe |
| Password hashing without a salt | [`weak-password-hash.py`](../vulns/python/weak-password-hash.py) | CWE-759 | high | yes | 1 vuln / 1 safe |
+| Weak random session token generation | [`cwe-330-python.py`](../vulns/python/cwe-330-python.py) | CWE-330 | high | yes | 1 vuln / 1 safe |
+| RSA key generation with insufficient key size | [`cwe-326-python.py`](../vulns/python/cwe-326-python.py) | CWE-326 | high | yes | 1 vuln / 2 safe |
| XPath injection via string interpolation | [`xpath-injection.py`](../vulns/python/xpath-injection.py) | CWE-643 | high | yes | 1 vuln / 1 safe |
| XSS via Jinja2 autoescape disabled and server-side template injection | [`xss-jinja2-autoescape-off.py`](../vulns/python/xss-jinja2-autoescape-off.py) | CWE-79 | high | yes | 3 vuln / 1 safe |
+| Reflected XSS via unescaped user input in HTML response | [`cwe-79-python.py`](../vulns/python/cwe-79-python.py) | CWE-79 | high | yes | 1 vuln / 1 safe |
+| Object-level authorization missing on document fetch | [`missing-object-level-authz.py`](../vulns/python/missing-object-level-authz.py) | CWE-285 | high | yes | 1 vuln / 1 safe |
## Ruby
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
+| Active Record debug mode enabled in production allowing sensitive query logging | [`cwe-489-ruby.rb`](../vulns/ruby/cwe-489-ruby.rb) | CWE-489 | high | yes | 1 vuln / 2 safe |
+| Command injection via unsafe shell command construction from user input | [`cwe-20-ruby.rb`](../vulns/ruby/cwe-20-ruby.rb) | CWE-20 | high | yes | 1 vuln / 1 safe |
+| Unsalted MD5 hash used for password storage, vulnerable to rainbow table attacks | [`cwe-759-ruby.rb`](../vulns/ruby/cwe-759-ruby.rb) | CWE-759 | high | yes | 1 vuln / 2 safe |
+| Hardcoded AWS API credentials in Ruby application code | [`cwe-321-ruby.rb`](../vulns/ruby/cwe-321-ruby.rb) | CWE-321 | critical | yes | 1 vuln / 1 safe |
+| Missing authentication check in session-based file access handler | [`cwe-306-ruby.rb`](../vulns/ruby/cwe-306-ruby.rb) | CWE-306 | critical | yes | 2 vuln / 2 safe |
+| Missing role-based authorization check in admin report generation | [`cwe-284-ruby.rb`](../vulns/ruby/cwe-284-ruby.rb) | CWE-284 | high | yes | 2 vuln / 2 safe |
+| Prototype pollution via unsafe deep merge of user-controlled parameters | [`cwe-1321-ruby.rb`](../vulns/ruby/cwe-1321-ruby.rb) | CWE-1321 | high | yes | 1 vuln / 2 safe |
| Code and command injection via eval / send / backticks | [`rce-eval.rb`](../vulns/ruby/rce-eval.rb) | CWE-95 | critical | yes | 3 vuln / 1 safe |
+| JWT signature verification bypass via unverified token payload | [`cwe-347-ruby.rb`](../vulns/ruby/cwe-347-ruby.rb) | CWE-347 | high | yes | 1 vuln / 2 safe |
+| SQL injection via unsanitized user input in database query | [`cwe-89-ruby.rb`](../vulns/ruby/cwe-89-ruby.rb) | CWE-89 | critical | yes | 1 vuln / 2 safe |
| SQL injection via string interpolation in ActiveRecord | [`sqli-string-interpolation.rb`](../vulns/ruby/sqli-string-interpolation.rb) | CWE-89 | critical | yes | 3 vuln / 1 safe |
+| Unbounded memory allocation from user-controlled size parameter | [`cwe-770-ruby.rb`](../vulns/ruby/cwe-770-ruby.rb) | CWE-770 | high | yes | 2 vuln / 4 safe |
+| Unsafe deserialization of user-controlled data via Marshal.load | [`cwe-943-ruby.rb`](../vulns/ruby/cwe-943-ruby.rb) | CWE-943 | critical | yes | 1 vuln / 2 safe |
+| Unsafe deserialization of attacker-controlled YAML data | [`cwe-494-ruby.rb`](../vulns/ruby/cwe-494-ruby.rb) | CWE-494 | critical | yes | 2 vuln / 2 safe |
+| Untrusted search path allows arbitrary code execution via library loading | [`cwe-426-ruby.rb`](../vulns/ruby/cwe-426-ruby.rb) | CWE-426 | high | yes | 2 vuln / 4 safe |
| XSS via html_safe / raw on untrusted input | [`xss-erb-html-safe.rb`](../vulns/ruby/xss-erb-html-safe.rb) | CWE-79 | high | yes | 3 vuln / 1 safe |
+| Relative path traversal in File.open via unsanitized user input | [`relative-path-traversal.rb`](../vulns/ruby/relative-path-traversal.rb) | CWE-23 | high | yes | 1 vuln / 1 safe |
+| XML External Entity (XXE) injection via unsafe XML parsing of user-controlled input | [`cwe-611-ruby.rb`](../vulns/ruby/cwe-611-ruby.rb) | CWE-611 | high | yes | 1 vuln / 2 safe |
## Secrets & Credentials
diff --git a/vulns/VULNERABILITY_CATALOG.json b/vulns/VULNERABILITY_CATALOG.json
index 153fdaf..1f4d6fb 100644
--- a/vulns/VULNERABILITY_CATALOG.json
+++ b/vulns/VULNERABILITY_CATALOG.json
@@ -2,10 +2,10 @@
"schema": "threatcrush-testbed-catalog/1",
"note": "Generated by scripts/generate-catalog.py \u2014 do not edit by hand.",
"totals": {
- "test_cases": 62,
- "expected_detections": 62,
- "vulnerable_markers": 123,
- "safe_markers": 73,
+ "test_cases": 136,
+ "expected_detections": 136,
+ "vulnerable_markers": 209,
+ "safe_markers": 140,
"languages": [
"dotenv",
"go",
@@ -28,6 +28,8 @@
"cwes": [
"CWE-20",
"CWE-22",
+ "CWE-23",
+ "CWE-77",
"CWE-78",
"CWE-79",
"CWE-89",
@@ -36,33 +38,60 @@
"CWE-113",
"CWE-117",
"CWE-190",
+ "CWE-200",
"CWE-201",
"CWE-209",
"CWE-256",
+ "CWE-281",
+ "CWE-284",
+ "CWE-285",
+ "CWE-287",
"CWE-295",
+ "CWE-306",
+ "CWE-307",
+ "CWE-311",
+ "CWE-312",
+ "CWE-319",
"CWE-321",
+ "CWE-326",
"CWE-327",
"CWE-330",
"CWE-338",
+ "CWE-345",
"CWE-346",
"CWE-347",
"CWE-352",
"CWE-362",
"CWE-377",
"CWE-384",
+ "CWE-400",
+ "CWE-426",
+ "CWE-434",
+ "CWE-444",
+ "CWE-470",
+ "CWE-476",
"CWE-489",
+ "CWE-494",
"CWE-502",
"CWE-506",
"CWE-532",
"CWE-601",
"CWE-611",
"CWE-614",
+ "CWE-617",
+ "CWE-626",
"CWE-639",
"CWE-643",
"CWE-681",
+ "CWE-693",
+ "CWE-754",
"CWE-759",
+ "CWE-770",
+ "CWE-787",
"CWE-798",
+ "CWE-835",
"CWE-862",
+ "CWE-912",
"CWE-915",
"CWE-918",
"CWE-942",
@@ -100,1209 +129,2865 @@
]
},
{
- "id": "go-integer-overflow",
- "file": "vulns/go/integer-overflow.go",
- "title": "Integer overflow and unchecked narrowing conversion",
+ "id": "go-cwe-1236-csv-injection",
+ "file": "vulns/go/cwe-1236-go.go",
+ "title": "CSV injection via user-controlled input written to a CSV file",
"category": "go",
"language": "go",
- "cwe": "CWE-190",
+ "cwe": "CWE-1236",
"cwes": [
- "CWE-190",
- "CWE-681"
+ "CWE-1236"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "Go's fixed-width integers wrap silently on overflow rather than",
- "detection_target": "Arithmetic on untrusted integers without an overflow check,",
+ "description": "User input is written directly into a CSV file without sanitization.",
+ "detection_target": "Taint flow from request input into CSV file writing without",
"safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 33,
- 46
+ 42
],
"safe_lines": [
- 57,
- 61,
- 71
+ 63
]
},
{
- "id": "go-sqli-fmt-sprintf",
- "file": "vulns/go/sqli-fmt-sprintf.go",
- "title": "SQL injection via fmt.Sprintf",
+ "id": "go-integer-overflow-parseint",
+ "file": "vulns/go/cwe-190-go.go",
+ "title": "Integer overflow in arithmetic operation after parsing user input",
"category": "go",
"language": "go",
- "cwe": "CWE-89",
+ "cwe": "CWE-190",
"cwes": [
- "CWE-89"
+ "CWE-190"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Request parameters are formatted into SQL text with fmt.Sprintf",
- "detection_target": "Taint flow from request input into db.Query/db.Exec where",
- "safe_guard": "Guarded by the always-false `neverRun` constant, and the package",
+ "description": "User-controlled input is parsed as an integer and used in an",
+ "detection_target": "Taint flow from request input into arithmetic operations",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 33,
- 42
+ 31,
+ 32,
+ 43,
+ 44
],
"safe_lines": [
- 51
+ 55
]
},
{
- "id": "go-ssrf-http-get",
- "file": "vulns/go/ssrf-http-get.go",
- "title": "Server-side request forgery via http.Get on a user-supplied URL",
+ "id": "go-auth-bypass-jwt-none-alg",
+ "file": "vulns/go/cwe-287-go.go",
+ "title": "Authentication bypass via JWT algorithm confusion (none algorithm)",
"category": "go",
"language": "go",
- "cwe": "CWE-918",
+ "cwe": "CWE-287",
"cwes": [
- "CWE-918"
+ "CWE-287"
],
- "severity": "high",
+ "severity": "critical",
"expected_detection": true,
- "description": "The handler fetches a URL taken straight from the request, so an",
- "detection_target": "Taint flow from request input into http.Get / http.NewRequest.",
+ "description": "The application accepts JWT tokens signed with the \"none\" algorithm,",
+ "detection_target": "Taint flow from request header into JWT parsing with the",
"safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 30,
- 42
+ 54
],
"safe_lines": [
- 54,
- 56
+ 73
]
},
{
- "id": "java-deserialization-object-input-stream",
- "file": "vulns/java/deserialization-object-input-stream.java",
- "title": "Insecure deserialisation via ObjectInputStream",
- "category": "java",
- "language": "java",
- "cwe": "CWE-502",
+ "id": "go-tls-insecure-skip-verify",
+ "file": "vulns/go/cwe-295-go.go",
+ "title": "TLS certificate verification disabled via InsecureSkipVerify",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-295",
"cwes": [
- "CWE-502"
+ "CWE-295"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Untrusted bytes from a request body or cookie are passed to",
- "detection_target": "ObjectInputStream.readObject reached from untrusted input",
- "safe_guard": "Every payload is behind the always-false NEVER_RUN constant and",
+ "description": "The HTTP client sets InsecureSkipVerify to true, which disables",
+ "detection_target": "Taint flow from request input into http.Transport with",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 38,
- 45
+ 34
],
"safe_lines": [
- 59,
- 62
+ 58
]
},
{
- "id": "java-sqli-statement-concat",
- "file": "vulns/java/sqli-statement-concat.java",
- "title": "SQL injection via Statement string concatenation",
- "category": "java",
- "language": "java",
- "cwe": "CWE-89",
+ "id": "go-cwe312-sensitive-data-logging",
+ "file": "vulns/go/cwe-312-go.go",
+ "title": "Sensitive data (API key) is logged in plaintext",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-312",
"cwes": [
- "CWE-89"
+ "CWE-312"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Request parameters are concatenated into SQL executed through a",
- "detection_target": "Taint flow from HttpServletRequest.getParameter into",
- "safe_guard": "Every payload is behind the always-false NEVER_RUN constant. This",
+ "description": "User-supplied API key from an HTTP request header is written",
+ "detection_target": "Taint flow from request header into log.Printf or",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 35,
- 44
+ 30
],
"safe_lines": [
- 56
+ 39
]
},
{
- "id": "java-xss-response-writer",
- "file": "vulns/java/xss-response-writer.java",
- "title": "Reflected XSS via HttpServletResponse writer",
- "category": "java",
- "language": "java",
- "cwe": "CWE-79",
+ "id": "go-cwe345-json-signature-verification",
+ "file": "vulns/go/cwe-345-go.go",
+ "title": "JSON data integrity check bypass via missing signature verification",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-345",
"cwes": [
- "CWE-79"
+ "CWE-345"
],
"severity": "high",
"expected_detection": true,
- "description": "A request parameter is written straight into an HTML response",
- "detection_target": "Taint flow from HttpServletRequest.getParameter into",
- "safe_guard": "Every payload is behind the always-false NEVER_RUN constant and",
+ "description": "The application receives a JSON payload from an untrusted source",
+ "detection_target": "Taint flow from request body into JSON unmarshalling and",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 35,
- 42
+ 46
],
"safe_lines": [
- 53,
- 56
+ 58,
+ 95
]
},
{
- "id": "java-xxe-document-builder",
- "file": "vulns/java/xxe-document-builder.java",
- "title": "XXE via unconfigured DocumentBuilderFactory",
- "category": "java",
- "language": "java",
- "cwe": "CWE-611",
+ "id": "go-cwe346-origin-validation",
+ "file": "vulns/go/cwe-346-go.go",
+ "title": "CWE-346 Origin validation error via missing Origin header check in WebSocket handshake",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-346",
"cwes": [
- "CWE-611"
+ "CWE-346"
],
"severity": "high",
"expected_detection": true,
- "description": "An XML parser is built from DocumentBuilderFactory with default",
- "detection_target": "Taint flow from user XML input into DocumentBuilder.parse",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "description": "The vulnerable function accepts WebSocket upgrade requests without validating the",
+ "detection_target": "Taint flow from HTTP request Origin header into WebSocket upgrade acceptance",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore` build tag;",
"attribution": "line",
"vulnerable_lines": [
- 30,
- 34
+ 33,
+ 44
],
"safe_lines": [
- 46
+ 50,
+ 56,
+ 57
]
},
{
- "id": "js-cookie-security-flags",
- "file": "vulns/javascript/cookie-security-flags.js",
- "title": "Sensitive session cookie without the Secure attribute",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-614",
+ "id": "go-session-fixation-cookie",
+ "file": "vulns/go/cwe-384-go.go",
+ "title": "Session fixation via predictable session ID in Set-Cookie",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-384",
"cwes": [
- "CWE-614"
+ "CWE-384"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "A session identifier is placed in a cookie that explicitly",
- "detection_target": "Session cookies configured with secure:false or without",
- "safe_guard": "Both handlers are unreachable behind if (false), and the response",
+ "description": "User-controlled session ID is accepted and set as a cookie",
+ "detection_target": "Taint flow from request input into Set-Cookie header with",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 20
+ 29
],
"safe_lines": [
- 31
+ 40
]
},
{
- "id": "js-cors-wildcard-credentials",
- "file": "vulns/javascript/cors-wildcard-credentials.js",
- "title": "Credentialed CORS configured with a wildcard origin",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-942",
+ "id": "go-nil-pointer-deref-http",
+ "file": "vulns/go/cwe-476-go.go",
+ "title": "Nil pointer dereference on a response body that may be nil",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-476",
"cwes": [
- "CWE-942"
+ "CWE-476"
],
"severity": "high",
"expected_detection": true,
- "description": "A CORS policy combines a wildcard allowed origin with credential",
- "detection_target": "CORS configuration that combines origin '*' with credentials",
- "safe_guard": "The entire fixture is wrapped in if (false), so no middleware or",
+ "description": "The function calls `resp.Body.Close()` and `io.ReadAll(resp.Body)`",
+ "detection_target": "Taint flow from an HTTP response that may be nil into",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 20
+ 35,
+ 37
],
"safe_lines": [
- 30
+ 51
]
},
{
- "id": "js-csrf-missing-token",
- "file": "vulns/javascript/csrf-missing-token.js",
- "title": "CSRF via missing anti-CSRF token on state-changing POST",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-352",
+ "id": "go-open-redirect-http-redirect",
+ "file": "vulns/go/cwe-601-go.go",
+ "title": "Open redirect via http.Redirect with user-controlled URL",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-601",
"cwes": [
- "CWE-352"
+ "CWE-601"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "A state-changing Express endpoint (transfer, delete, password",
- "detection_target": "State-changing handler that reads session cookies but never",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "description": "User input from the \"next\" query parameter is passed directly",
+ "detection_target": "Taint flow from request query parameter into http.Redirect",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 25,
- 33,
- 42
+ 29
],
"safe_lines": [
- 55
+ 35
]
},
{
- "id": "js-hardcoded-crypto-key",
- "file": "vulns/javascript/hardcoded-crypto-key.js",
- "title": "Hardcoded cryptographic key used for application encryption",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-321",
+ "id": "go-cwe681-float-to-int-conversion",
+ "file": "vulns/go/cwe-681-go.go",
+ "title": "CWE-681 Incorrect Conversion between Numeric Types: float64 to int truncation",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-681",
"cwes": [
- "CWE-321"
+ "CWE-681"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "An obviously synthetic AES key is embedded in source and passed",
- "detection_target": "Fixed key literals reaching cryptographic key or cipher",
- "safe_guard": "The key is a repeating test-only placeholder, both examples are",
+ "description": "User-controlled float64 value is converted to int without bounds",
+ "detection_target": "Taint flow from request input into a float-to-int conversion",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 22
+ 31
],
"safe_lines": [
- 30
+ 40
]
},
{
- "id": "js-host-header-password-reset",
- "file": "vulns/javascript/host-header-password-reset.js",
- "title": "Password-reset URL poisoning via untrusted Host header",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-346",
+ "id": "go-cwe754-unchecked-error",
+ "file": "vulns/go/cwe-754-go.go",
+ "title": "Unchecked error from file operation leads to inconsistent state",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-754",
"cwes": [
- "CWE-346"
+ "CWE-754"
],
"severity": "high",
"expected_detection": true,
- "description": "A password-reset URL uses the request Host header as its trust",
- "detection_target": "Host or X-Forwarded-Host data used to construct a security-",
- "safe_guard": "URL construction is behind if (false); no email, network request,",
+ "description": "The vulnerable function calls os.Rename and ignores the returned",
+ "detection_target": "Taint flow from request input into os.Rename where the error",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 20
+ 33,
+ 42
],
"safe_lines": [
- 27
+ 54
]
},
{
- "id": "js-http-header-injection",
- "file": "vulns/javascript/http-header-injection.js",
- "title": "HTTP response splitting via unsanitized header value",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-113",
+ "id": "go-missing-authz-file-read",
+ "file": "vulns/go/cwe-862-go.go",
+ "title": "Missing authorization check on file read endpoint",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-862",
"cwes": [
- "CWE-113"
+ "CWE-862"
],
"severity": "high",
"expected_detection": true,
- "description": "A query parameter is copied directly into a response header, so",
- "detection_target": "Request data reaching setHeader or header without rejecting",
- "safe_guard": "All response mutations are unreachable behind if (false), and no",
+ "description": "The handler reads and returns a file from the filesystem based",
+ "detection_target": "Taint flow from request input into os.ReadFile or",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 20
+ 31
],
"safe_lines": [
- 28
+ 39
]
},
{
- "id": "js-idor-unscoped-object-lookup",
- "file": "vulns/javascript/idor-unscoped-object-lookup.js",
- "title": "IDOR via unscoped object lookup",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-639",
+ "id": "go-cwe942-insecure-rewrite",
+ "file": "vulns/go/cwe-942-go.go",
+ "title": "Insecure URL rewrite via httputil.ReverseProxy with user-controlled target",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-942",
"cwes": [
- "CWE-639"
+ "CWE-942"
],
"severity": "high",
"expected_detection": true,
- "description": "An authenticated Express handler fetches an invoice using only",
- "detection_target": "Object lookup keyed only by a request parameter despite an",
- "safe_guard": "Wrapped in if (false) \u2014 every lookup and response is unreachable",
+ "description": "User-controlled input is used to construct a reverse proxy target URL, allowing",
+ "detection_target": "Taint flow from request input into httputil.NewSingleHostReverseProxy or",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 24
+ 30
],
"safe_lines": [
- 37
+ 38
]
},
{
- "id": "js-insecure-random-token",
- "file": "vulns/javascript/insecure-random-token.js",
- "title": "Predictable security token generated with Math.random",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-330",
+ "id": "go-integer-overflow",
+ "file": "vulns/go/integer-overflow.go",
+ "title": "Integer overflow and unchecked narrowing conversion",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-190",
"cwes": [
- "CWE-330"
+ "CWE-190",
+ "CWE-681"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "A password-reset token is generated with Math.random, whose",
- "detection_target": "Math.random or another non-cryptographic PRNG used to",
- "safe_guard": "The entire fixture is wrapped in if (false), so no token is ever",
+ "description": "Go's fixed-width integers wrap silently on overflow rather than",
+ "detection_target": "Arithmetic on untrusted integers without an overflow check,",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 22
+ 33,
+ 46
],
"safe_lines": [
- 30
+ 57,
+ 61,
+ 71
]
},
{
- "id": "js-jwt-decode-without-verify",
- "file": "vulns/javascript/jwt-decode-without-verify.js",
- "title": "JWT signature validation bypass via decode-only parsing",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-347",
+ "id": "go-sqli-fmt-sprintf",
+ "file": "vulns/go/sqli-fmt-sprintf.go",
+ "title": "SQL injection via fmt.Sprintf",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-89",
"cwes": [
- "CWE-347"
+ "CWE-89"
],
- "severity": "high",
+ "severity": "critical",
"expected_detection": true,
- "description": "Authorization trusts role claims returned by jwt.decode(), which",
- "detection_target": "Security-sensitive claims from jwt.decode() used for an",
- "safe_guard": "Both examples are wrapped in if (false), so neither token path can",
+ "description": "Request parameters are formatted into SQL text with fmt.Sprintf",
+ "detection_target": "Taint flow from request input into db.Query/db.Exec where",
+ "safe_guard": "Guarded by the always-false `neverRun` constant, and the package",
"attribution": "line",
"vulnerable_lines": [
- 25
+ 33,
+ 42
],
"safe_lines": [
- 44
+ 51
]
},
{
- "id": "js-log-injection",
- "file": "vulns/javascript/log-injection.js",
- "title": "Log injection via untrusted request metadata",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-117",
+ "id": "go-ssrf-http-get",
+ "file": "vulns/go/ssrf-http-get.go",
+ "title": "Server-side request forgery via http.Get on a user-supplied URL",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-918",
"cwes": [
- "CWE-117"
+ "CWE-918"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "A request header is copied into a structured log line without",
- "detection_target": "Untrusted header or parameter data reaching a logging sink",
- "safe_guard": "Every example is behind if (false), and the logger below only",
+ "description": "The handler fetches a URL taken straight from the request, so an",
+ "detection_target": "Taint flow from request input into http.Get / http.NewRequest.",
+ "safe_guard": "Guarded by the always-false `neverRun` constant plus an `ignore`",
"attribution": "line",
"vulnerable_lines": [
- 23
+ 30,
+ 42
],
"safe_lines": [
- 31
+ 54,
+ 56
]
},
{
- "id": "js-mass-assignment-object-assign",
- "file": "vulns/javascript/mass-assignment-object-assign.js",
- "title": "Mass assignment through Object.assign with request data",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-915",
+ "id": "go-stack-trace-exposed",
+ "file": "vulns/go/stack-trace-exposed.go",
+ "title": "Full stack trace leaked to client on unhandled error",
+ "category": "go",
+ "language": "go",
+ "cwe": "CWE-200",
"cwes": [
- "CWE-915"
+ "CWE-200"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "Object.assign copies every request-body property onto an account,",
- "detection_target": "Object.assign or equivalent bulk assignment from untrusted",
- "safe_guard": "The entire fixture is wrapped in if (false), so no object is ever",
+ "description": "An HTTP handler writes err.Error() and runtime stack traces",
+ "detection_target": "err.Error() / debug.Stack() written to the response body;",
+ "safe_guard": "Both handlers are unreachable: the file is guarded by a",
"attribution": "line",
"vulnerable_lines": [
- 21
+ 31
],
- "safe_lines": [
- 34
- ]
+ "safe_lines": []
},
{
- "id": "js-nosql-injection-mongodb",
- "file": "vulns/javascript/nosql-injection-mongodb.js",
- "title": "MongoDB NoSQL injection via attacker-controlled query object",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-943",
+ "id": "java-log-injection-http-response",
+ "file": "vulns/java/cwe-117-java.java",
+ "title": "Log injection via unsanitized user input in HTTP response logging",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-117",
"cwes": [
- "CWE-943"
+ "CWE-117"
],
"severity": "high",
"expected_detection": true,
- "description": "A MongoDB filter is accepted directly from the request body, so",
- "detection_target": "Taint flow from a request object into a MongoDB find or",
- "safe_guard": "The entire fixture is wrapped in if (false), so no query code can",
+ "description": "User-controlled input (e.g., the \"username\" request parameter)",
+ "detection_target": "Direct concatenation of user-controlled input into a log",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
"attribution": "line",
"vulnerable_lines": [
- 26
+ 39
],
- "safe_lines": [
- 38
- ]
+ "safe_lines": []
},
{
- "id": "js-open-redirect",
- "file": "vulns/javascript/open-redirect.js",
- "title": "Open redirect via unvalidated next parameter",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-601",
+ "id": "java-unsafe-reflection-cwe-1357",
+ "file": "vulns/java/cwe-1357-java.java",
+ "title": "Unsafe reflection with user-controlled class name leading to arbitrary class instantiation",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-1357",
"cwes": [
- "CWE-601"
+ "CWE-1357"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "A post-login redirect target is taken from the query string with",
- "detection_target": "Taint flow from request input into res.redirect /",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "description": "User-controlled input (e.g., the \"className\" request parameter)",
+ "detection_target": "Direct use of user-controlled input in Class.forName()",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
"attribution": "line",
"vulnerable_lines": [
- 23,
- 30,
- 39
+ 38
],
- "safe_lines": [
- 52
- ]
+ "safe_lines": []
},
{
- "id": "js-prototype-pollution",
- "file": "vulns/javascript/prototype-pollution.js",
- "title": "Prototype pollution via recursive merge",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-1321",
+ "id": "java-plaintext-password-storage-http-basic",
+ "file": "vulns/java/cwe-256-java.java",
+ "title": "Plaintext password storage in HTTP Basic Authentication credentials",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-256",
"cwes": [
- "CWE-1321"
+ "CWE-256"
],
"severity": "high",
"expected_detection": true,
- "description": "A recursive merge helper copies attacker-controlled keys without",
- "detection_target": "Unguarded computed member assignment (target[key] = ...) in",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "description": "User-supplied credentials (e.g., from an HTTP Basic Authentication",
+ "detection_target": "Direct assignment of user-controlled password input to a",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
"attribution": "line",
"vulnerable_lines": [
- 27,
- 41
+ 37
],
- "safe_lines": [
- 53
- ]
+ "safe_lines": []
},
{
- "id": "js-rce-child-process",
- "file": "vulns/javascript/rce-child-process.js",
- "title": "OS command injection via child_process.exec",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-78",
+ "id": "java-missing-encryption-sensitive-data",
+ "file": "vulns/java/cwe-311-java.java",
+ "title": "Missing encryption of sensitive data in transit",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-311",
"cwes": [
- "CWE-78"
+ "CWE-311"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "User input is interpolated into a shell command string passed to",
- "detection_target": "Taint flow from request input into exec/execSync/spawn with",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "description": "Sensitive user data (e.g., credit card numbers or personal",
+ "detection_target": "HTTP URL construction with sensitive data as a query",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
"attribution": "line",
"vulnerable_lines": [
- 24,
- 31
+ 42
],
"safe_lines": [
- 41
+ 60
]
},
{
- "id": "js-session-fixation-login",
- "file": "vulns/javascript/session-fixation-login.js",
- "title": "Session fixation when login reuses the anonymous session ID",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-384",
+ "id": "java-cleartext-transmission-sensitive-data",
+ "file": "vulns/java/cwe-319-java.java",
+ "title": "Cleartext transmission of sensitive data over unencrypted channel",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-319",
"cwes": [
- "CWE-384"
+ "CWE-319"
],
"severity": "high",
"expected_detection": true,
- "description": "An Express login handler attaches an authenticated user to the",
- "detection_target": "Authentication state assigned to an existing session",
- "safe_guard": "Wrapped in if (false) \u2014 authentication, session mutation, and",
+ "description": "Sensitive authentication data (e.g., session tokens or API keys)",
+ "detection_target": "HTTP URL construction with sensitive data as a query",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
"attribution": "line",
"vulnerable_lines": [
- 28
+ 42
],
"safe_lines": [
- 43
+ 60
]
},
{
- "id": "js-sqli-raw-concat",
- "file": "vulns/javascript/sqli-raw-concat.js",
- "title": "SQL injection via string concatenation",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-89",
+ "id": "java-insecure-random-uuid",
+ "file": "vulns/java/cwe-338-java.java",
+ "title": "Insecure random UUID generation using java.util.Random for session identifiers",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-338",
"cwes": [
- "CWE-89"
+ "CWE-338"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Request parameters are concatenated and template-interpolated",
- "detection_target": "Taint flow from request input into a query() / execute()",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "description": "The application generates session identifiers using java.util.Random,",
+ "detection_target": "Use of java.util.Random (or its subclasses) for generating",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN constant and",
"attribution": "line",
"vulnerable_lines": [
- 21,
- 30
+ 35
],
- "safe_lines": [
- 40
- ]
+ "safe_lines": []
},
{
- "id": "js-ssrf-request-user-url",
- "file": "vulns/javascript/ssrf-request-user-url.js",
- "title": "Server-side request forgery via user-supplied URL",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-918",
+ "id": "java-temp-file-symlink-race",
+ "file": "vulns/java/cwe-377-java.java",
+ "title": "Insecure temporary file creation with predictable name and no atomic operation",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-377",
"cwes": [
- "CWE-918"
+ "CWE-377"
],
"severity": "high",
"expected_detection": true,
- "description": "The server fetches an arbitrary user-supplied URL, letting an",
- "detection_target": "Taint flow from request input into fetch/axios/http.get.",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. No",
+ "description": "The application creates a temporary file using a predictable name",
+ "detection_target": "Direct creation of a temporary file with a predictable name",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN constant and",
"attribution": "line",
"vulnerable_lines": [
- 25,
+ 47
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-unsafe-reflection-dynamic-method-invocation",
+ "file": "vulns/java/cwe-470-java.java",
+ "title": "Unsafe reflection-based method invocation with user-controlled class name",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-470",
+ "cwes": [
+ "CWE-470"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "The application uses Java reflection to dynamically load a class",
+ "detection_target": "Class.forName() called with user-controlled input and",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 41
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-sensitive-data-logging-credit-card",
+ "file": "vulns/java/cwe-532-java.java",
+ "title": "Sensitive credit card data logged in plain text",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-532",
+ "cwes": [
+ "CWE-532"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled input (e.g., the \"cardNumber\" request parameter)",
+ "detection_target": "Direct logging of sensitive user-controlled data without",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 39
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-xpath-injection-unsafe-expression",
+ "file": "vulns/java/cwe-643-java.java",
+ "title": "XPath injection via unsanitized user input in XML document query",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-643",
+ "cwes": [
+ "CWE-643"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled input (e.g., the \"username\" request parameter)",
+ "detection_target": "Direct concatenation of user-controlled input into an",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 55
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-protection-mechanism-failure",
+ "file": "vulns/java/cwe-693-java.java",
+ "title": "Protection mechanism failure - missing authentication on sensitive endpoint",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-693",
+ "cwes": [
+ "CWE-693"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "The application exposes a sensitive administrative endpoint",
+ "detection_target": "Missing authentication check on a sensitive endpoint",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 40
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-hardcoded-credentials-db-connection",
+ "file": "vulns/java/cwe-798-java.java",
+ "title": "Hardcoded database credentials in JDBC connection string",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-798",
+ "cwes": [
+ "CWE-798"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "The application uses hardcoded database credentials embedded",
+ "detection_target": "Direct hardcoded credential string in a database",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 41
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-ssrf-url-connection",
+ "file": "vulns/java/cwe-918-java.java",
+ "title": "Server-Side Request Forgery via user-controlled URL in HttpURLConnection",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-918",
+ "cwes": [
+ "CWE-918"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled input (e.g., the \"url\" request parameter) is",
+ "detection_target": "Direct use of user-controlled input in URL/connection",
+ "safe_guard": "The vulnerable code is behind the always-false NEVER_RUN",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 42
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-deserialization-object-input-stream",
+ "file": "vulns/java/deserialization-object-input-stream.java",
+ "title": "Insecure deserialisation via ObjectInputStream",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-502",
+ "cwes": [
+ "CWE-502"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "Untrusted bytes from a request body or cookie are passed to",
+ "detection_target": "ObjectInputStream.readObject reached from untrusted input",
+ "safe_guard": "Every payload is behind the always-false NEVER_RUN constant and",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 38,
+ 45
+ ],
+ "safe_lines": [
+ 59,
+ 62
+ ]
+ },
+ {
+ "id": "java-hidden-backdoor-endpoint",
+ "file": "vulns/java/hidden-backdoor-endpoint.java",
+ "title": "Hidden administrative backdoor endpoint behind an innocuous path",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-912",
+ "cwes": [
+ "CWE-912"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "A servlet-style handler maps a harmless-looking path",
+ "detection_target": "Hardcoded magic tokens compared against request input;",
+ "safe_guard": "The doGet method is unreachable: the class is only referenced",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 23
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-sqli-statement-concat",
+ "file": "vulns/java/sqli-statement-concat.java",
+ "title": "SQL injection via Statement string concatenation",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-89",
+ "cwes": [
+ "CWE-89"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "Request parameters are concatenated into SQL executed through a",
+ "detection_target": "Taint flow from HttpServletRequest.getParameter into",
+ "safe_guard": "Every payload is behind the always-false NEVER_RUN constant. This",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 35,
+ 44
+ ],
+ "safe_lines": [
+ 56
+ ]
+ },
+ {
+ "id": "java-unbounded-request-collection",
+ "file": "vulns/java/unbounded-request-collection.java",
+ "title": "Unbounded accumulation of request bodies into memory",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-400",
+ "cwes": [
+ "CWE-400"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A servlet reads the entire request body into a byte array via",
+ "detection_target": "readAllBytes() / readNBytes(MAX_VALUE) on request input;",
+ "safe_guard": "The servlet class is only referenced inside if (NEVER_RUN)",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "java-xss-response-writer",
+ "file": "vulns/java/xss-response-writer.java",
+ "title": "Reflected XSS via HttpServletResponse writer",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-79",
+ "cwes": [
+ "CWE-79"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A request parameter is written straight into an HTML response",
+ "detection_target": "Taint flow from HttpServletRequest.getParameter into",
+ "safe_guard": "Every payload is behind the always-false NEVER_RUN constant and",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 35,
+ 42
+ ],
+ "safe_lines": [
+ 53,
+ 56
+ ]
+ },
+ {
+ "id": "java-xxe-document-builder",
+ "file": "vulns/java/xxe-document-builder.java",
+ "title": "XXE via unconfigured DocumentBuilderFactory",
+ "category": "java",
+ "language": "java",
+ "cwe": "CWE-611",
+ "cwes": [
+ "CWE-611"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An XML parser is built from DocumentBuilderFactory with default",
+ "detection_target": "Taint flow from user XML input into DocumentBuilder.parse",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 30,
+ 34
+ ],
+ "safe_lines": [
+ 46
+ ]
+ },
+ {
+ "id": "js-bruteforce-no-rate-limit",
+ "file": "vulns/javascript/bruteforce-no-rate-limit.js",
+ "title": "Login endpoint without rate limiting or lockout",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-307",
+ "cwes": [
+ "CWE-307"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A login handler validates credentials without any rate limit,",
+ "detection_target": "Missing rate limiting / lockout on credential validation;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 27,
+ 29
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-command-injection-shelljs",
+ "file": "vulns/javascript/command-injection-shelljs.js",
+ "title": "Command injection via shelljs exec with unsanitized input",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-77",
+ "cwes": [
+ "CWE-77"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A user-supplied filename is concatenated directly into a",
+ "detection_target": "exec() called with a string built by concatenation of",
+ "safe_guard": "Both functions are unreachable behind if (false); the child",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": [
+ 37
+ ]
+ },
+ {
+ "id": "js-cookie-security-flags",
+ "file": "vulns/javascript/cookie-security-flags.js",
+ "title": "Sensitive session cookie without the Secure attribute",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-614",
+ "cwes": [
+ "CWE-614"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A session identifier is placed in a cookie that explicitly",
+ "detection_target": "Session cookies configured with secure:false or without",
+ "safe_guard": "Both handlers are unreachable behind if (false), and the response",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 20
+ ],
+ "safe_lines": [
+ 31
+ ]
+ },
+ {
+ "id": "js-cors-wildcard-credentials",
+ "file": "vulns/javascript/cors-wildcard-credentials.js",
+ "title": "Credentialed CORS configured with a wildcard origin",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-942",
+ "cwes": [
+ "CWE-942"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A CORS policy combines a wildcard allowed origin with credential",
+ "detection_target": "CORS configuration that combines origin '*' with credentials",
+ "safe_guard": "The entire fixture is wrapped in if (false), so no middleware or",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 20
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "js-csrf-missing-token",
+ "file": "vulns/javascript/csrf-missing-token.js",
+ "title": "CSRF via missing anti-CSRF token on state-changing POST",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-352",
+ "cwes": [
+ "CWE-352"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A state-changing Express endpoint (transfer, delete, password",
+ "detection_target": "State-changing handler that reads session cookies but never",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25,
+ 33,
+ 42
+ ],
+ "safe_lines": [
+ 55
+ ]
+ },
+ {
+ "id": "js-regex-redos-vulnerable-pattern",
+ "file": "vulns/javascript/cwe-1333-javascript.js",
+ "title": "Regular expression with catastrophic backtracking on user input",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-1333",
+ "cwes": [
+ "CWE-1333"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A route handler validates user-provided email addresses using a",
+ "detection_target": "Catastrophic backtracking regex pattern (nested quantifiers)",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-cwe201-information-exposure-through-sent-data",
+ "file": "vulns/javascript/cwe-201-javascript.js",
+ "title": "Error response includes full stack trace and internal path",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-201",
+ "cwes": [
+ "CWE-201"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "An API error handler returns the raw Error object including",
+ "detection_target": "Sending stack trace or internal path details in HTTP",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-insecure-permission-check-on-shared-resource",
+ "file": "vulns/javascript/cwe-281-javascript.js",
+ "title": "File upload endpoint checks only ownership, not shared-resource permissions",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-281",
+ "cwes": [
+ "CWE-281"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A file upload handler validates that the requesting user owns the",
+ "detection_target": "Missing shared-resource permission check on file write;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 30
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-weak-crypto-insecure-cipher",
+ "file": "vulns/javascript/cwe-327-javascript.js",
+ "title": "Using DES for symmetric encryption",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-327",
+ "cwes": [
+ "CWE-327"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "The vulnerable function encrypts sensitive data using the DES",
+ "detection_target": "Use of DES (or other weak ciphers) for encryption;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no real",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 27
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-csrf-state-changing-post",
+ "file": "vulns/javascript/cwe-352-javascript.js",
+ "title": "State-changing POST endpoint without CSRF token validation",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-352",
+ "cwes": [
+ "CWE-352"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A profile update endpoint accepts a POST request and changes",
+ "detection_target": "Missing CSRF token validation on state-changing POST;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-unsafe-file-upload",
+ "file": "vulns/javascript/cwe-434-javascript.js",
+ "title": "File upload endpoint accepting executable content without validation",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-434",
+ "cwes": [
+ "CWE-434"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "An upload handler stores user-supplied files directly to disk",
+ "detection_target": "Missing file type/extension validation on upload; storing",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 30
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-insecure-deserialization-json",
+ "file": "vulns/javascript/cwe-502-javascript.js",
+ "title": "Unsafe deserialization of user-controlled JSON into a JavaScript object",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-502",
+ "cwes": [
+ "CWE-502"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "The vulnerable function uses eval() to parse a JSON string from an",
+ "detection_target": "Use of eval() or similar dynamic code execution on",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-cwe614-insecure-cookie-no-secure-flag",
+ "file": "vulns/javascript/cwe-614-javascript.js",
+ "title": "Session cookie set without Secure flag over HTTP",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-614",
+ "cwes": [
+ "CWE-614"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A login handler sets a session cookie without the Secure",
+ "detection_target": "Missing Secure flag on session cookie; cookie set with",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-infinite-loop-uncontrolled",
+ "file": "vulns/javascript/cwe-617-javascript.js",
+ "title": "Uncontrolled loop condition leading to denial of service",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-617",
+ "cwes": [
+ "CWE-617"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A function processes a user-supplied numeric input as a loop",
+ "detection_target": "Missing input validation on loop bound; unbounded loop",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 28
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-command-injection-exec",
+ "file": "vulns/javascript/cwe-78-javascript.js",
+ "title": "Command injection via unsanitized user input in exec()",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-78",
+ "cwes": [
+ "CWE-78"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "A file processing endpoint passes a user-controlled filename",
+ "detection_target": "Unsanitized user input flowing into exec()/spawn() with",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-buffer-overflow-unsafe-copy",
+ "file": "vulns/javascript/cwe-787-javascript.js",
+ "title": "Unsafe buffer copy without bounds checking",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-787",
+ "cwes": [
+ "CWE-787"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A function copies data from a source buffer to a destination",
+ "detection_target": "Missing bounds check before writing to a fixed-size",
+ "safe_guard": "Both handlers are unreachable behind if (false); no buffer",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-ldap-injection-unfiltered-filter",
+ "file": "vulns/javascript/cwe-90-javascript.js",
+ "title": "LDAP search filter built from user input without sanitization",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-90",
+ "cwes": [
+ "CWE-90"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An LDAP search filter is constructed by concatenating a",
+ "detection_target": "Unescaped user input concatenated into an LDAP filter;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 27
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-command-injection-eval",
+ "file": "vulns/javascript/cwe-95-javascript.js",
+ "title": "User input passed directly to eval() for arithmetic calculation",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-95",
+ "cwes": [
+ "CWE-95"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "A calculator endpoint takes a user-supplied expression string",
+ "detection_target": "Direct eval() of user-controlled input without validation;",
+ "safe_guard": "Both handlers are unreachable behind if (false); no request",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 28
+ ],
+ "safe_lines": []
+ },
+ {
+ "id": "js-hardcoded-crypto-key",
+ "file": "vulns/javascript/hardcoded-crypto-key.js",
+ "title": "Hardcoded cryptographic key used for application encryption",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-321",
+ "cwes": [
+ "CWE-321"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An obviously synthetic AES key is embedded in source and passed",
+ "detection_target": "Fixed key literals reaching cryptographic key or cipher",
+ "safe_guard": "The key is a repeating test-only placeholder, both examples are",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 22
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "js-host-header-password-reset",
+ "file": "vulns/javascript/host-header-password-reset.js",
+ "title": "Password-reset URL poisoning via untrusted Host header",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-346",
+ "cwes": [
+ "CWE-346"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A password-reset URL uses the request Host header as its trust",
+ "detection_target": "Host or X-Forwarded-Host data used to construct a security-",
+ "safe_guard": "URL construction is behind if (false); no email, network request,",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 20
+ ],
+ "safe_lines": [
+ 27
+ ]
+ },
+ {
+ "id": "js-http-header-injection",
+ "file": "vulns/javascript/http-header-injection.js",
+ "title": "HTTP response splitting via unsanitized header value",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-113",
+ "cwes": [
+ "CWE-113"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A query parameter is copied directly into a response header, so",
+ "detection_target": "Request data reaching setHeader or header without rejecting",
+ "safe_guard": "All response mutations are unreachable behind if (false), and no",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 20
+ ],
+ "safe_lines": [
+ 28
+ ]
+ },
+ {
+ "id": "js-idor-unscoped-object-lookup",
+ "file": "vulns/javascript/idor-unscoped-object-lookup.js",
+ "title": "IDOR via unscoped object lookup",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-639",
+ "cwes": [
+ "CWE-639"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An authenticated Express handler fetches an invoice using only",
+ "detection_target": "Object lookup keyed only by a request parameter despite an",
+ "safe_guard": "Wrapped in if (false) \u2014 every lookup and response is unreachable",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24
+ ],
+ "safe_lines": [
+ 37
+ ]
+ },
+ {
+ "id": "js-insecure-random-token",
+ "file": "vulns/javascript/insecure-random-token.js",
+ "title": "Predictable security token generated with Math.random",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-330",
+ "cwes": [
+ "CWE-330"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A password-reset token is generated with Math.random, whose",
+ "detection_target": "Math.random or another non-cryptographic PRNG used to",
+ "safe_guard": "The entire fixture is wrapped in if (false), so no token is ever",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 22
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "js-jwt-decode-without-verify",
+ "file": "vulns/javascript/jwt-decode-without-verify.js",
+ "title": "JWT signature validation bypass via decode-only parsing",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-347",
+ "cwes": [
+ "CWE-347"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "Authorization trusts role claims returned by jwt.decode(), which",
+ "detection_target": "Security-sensitive claims from jwt.decode() used for an",
+ "safe_guard": "Both examples are wrapped in if (false), so neither token path can",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25
+ ],
+ "safe_lines": [
+ 44
+ ]
+ },
+ {
+ "id": "js-log-injection",
+ "file": "vulns/javascript/log-injection.js",
+ "title": "Log injection via untrusted request metadata",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-117",
+ "cwes": [
+ "CWE-117"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A request header is copied into a structured log line without",
+ "detection_target": "Untrusted header or parameter data reaching a logging sink",
+ "safe_guard": "Every example is behind if (false), and the logger below only",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 23
+ ],
+ "safe_lines": [
+ 31
+ ]
+ },
+ {
+ "id": "js-mass-assignment-object-assign",
+ "file": "vulns/javascript/mass-assignment-object-assign.js",
+ "title": "Mass assignment through Object.assign with request data",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-915",
+ "cwes": [
+ "CWE-915"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "Object.assign copies every request-body property onto an account,",
+ "detection_target": "Object.assign or equivalent bulk assignment from untrusted",
+ "safe_guard": "The entire fixture is wrapped in if (false), so no object is ever",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 21
+ ],
+ "safe_lines": [
+ 34
+ ]
+ },
+ {
+ "id": "js-nosql-injection-mongodb",
+ "file": "vulns/javascript/nosql-injection-mongodb.js",
+ "title": "MongoDB NoSQL injection via attacker-controlled query object",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-943",
+ "cwes": [
+ "CWE-943"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A MongoDB filter is accepted directly from the request body, so",
+ "detection_target": "Taint flow from a request object into a MongoDB find or",
+ "safe_guard": "The entire fixture is wrapped in if (false), so no query code can",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": [
+ 38
+ ]
+ },
+ {
+ "id": "js-open-redirect",
+ "file": "vulns/javascript/open-redirect.js",
+ "title": "Open redirect via unvalidated next parameter",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-601",
+ "cwes": [
+ "CWE-601"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A post-login redirect target is taken from the query string with",
+ "detection_target": "Taint flow from request input into res.redirect /",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. All",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 23,
+ 30,
+ 39
+ ],
+ "safe_lines": [
+ 52
+ ]
+ },
+ {
+ "id": "js-prototype-pollution",
+ "file": "vulns/javascript/prototype-pollution.js",
+ "title": "Prototype pollution via recursive merge",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-1321",
+ "cwes": [
+ "CWE-1321"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A recursive merge helper copies attacker-controlled keys without",
+ "detection_target": "Unguarded computed member assignment (target[key] = ...) in",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 27,
+ 41
+ ],
+ "safe_lines": [
+ 53
+ ]
+ },
+ {
+ "id": "js-rce-child-process",
+ "file": "vulns/javascript/rce-child-process.js",
+ "title": "OS command injection via child_process.exec",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-78",
+ "cwes": [
+ "CWE-78"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "User input is interpolated into a shell command string passed to",
+ "detection_target": "Taint flow from request input into exec/execSync/spawn with",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24,
+ 31
+ ],
+ "safe_lines": [
+ 41
+ ]
+ },
+ {
+ "id": "js-session-fixation-login",
+ "file": "vulns/javascript/session-fixation-login.js",
+ "title": "Session fixation when login reuses the anonymous session ID",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-384",
+ "cwes": [
+ "CWE-384"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An Express login handler attaches an authenticated user to the",
+ "detection_target": "Authentication state assigned to an existing session",
+ "safe_guard": "Wrapped in if (false) \u2014 authentication, session mutation, and",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 28
+ ],
+ "safe_lines": [
+ 43
+ ]
+ },
+ {
+ "id": "js-sqli-raw-concat",
+ "file": "vulns/javascript/sqli-raw-concat.js",
+ "title": "SQL injection via string concatenation",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-89",
+ "cwes": [
+ "CWE-89"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "Request parameters are concatenated and template-interpolated",
+ "detection_target": "Taint flow from request input into a query() / execute()",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 21,
+ 30
+ ],
+ "safe_lines": [
+ 40
+ ]
+ },
+ {
+ "id": "js-ssrf-request-user-url",
+ "file": "vulns/javascript/ssrf-request-user-url.js",
+ "title": "Server-side request forgery via user-supplied URL",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-918",
+ "cwes": [
+ "CWE-918"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "The server fetches an arbitrary user-supplied URL, letting an",
+ "detection_target": "Taint flow from request input into fetch/axios/http.get.",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code. No",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25,
+ 34
+ ],
+ "safe_lines": [
+ 46,
+ 50
+ ]
+ },
+ {
+ "id": "js-tls-reject-unauthorized-false",
+ "file": "vulns/javascript/tls-reject-unauthorized-false.js",
+ "title": "TLS certificate validation disabled on an HTTPS agent",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-295",
+ "cwes": [
+ "CWE-295"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An HTTPS agent sets rejectUnauthorized to false, allowing an",
+ "detection_target": "rejectUnauthorized set to false in TLS, HTTPS, request, or",
+ "safe_guard": "The entire fixture is wrapped in if (false), so no agent is",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 21
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "js-xss-dom-innerhtml",
+ "file": "vulns/javascript/xss-dom-innerHTML.js",
+ "title": "Reflected XSS via innerHTML",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-79",
+ "cwes": [
+ "CWE-79"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled query parameter is assigned directly to innerHTML,",
+ "detection_target": "Taint flow from `req.query` / `location.search` into an",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 21,
+ 29
+ ],
+ "safe_lines": [
+ 41
+ ]
+ },
+ {
+ "id": "js-xss-eval-user-input",
+ "file": "vulns/javascript/xss-eval-user-input.js",
+ "title": "Code injection via eval() of user input",
+ "category": "javascript",
+ "language": "javascript",
+ "cwe": "CWE-95",
+ "cwes": [
+ "CWE-95"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "User-supplied expression is passed to eval(), and to the",
+ "detection_target": "Taint flow from request input into eval / new Function /",
+ "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 21,
+ 28,
+ 36
+ ],
+ "safe_lines": [
+ 47
+ ]
+ },
+ {
+ "id": "py-csv-formula-injection",
+ "file": "vulns/python/csv-formula-injection.py",
+ "title": "CSV formula injection from untrusted spreadsheet cells",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-1236",
+ "cwes": [
+ "CWE-1236"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "User-controlled text beginning with spreadsheet formula prefixes",
+ "detection_target": "Taint flow from request input into csv.writer.writerow",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 28
+ ],
+ "safe_lines": [
+ 40
+ ]
+ },
+ {
+ "id": "py-http-header-injection",
+ "file": "vulns/python/cwe-113-python.py",
+ "title": "HTTP response header injection via unsanitized redirect parameter",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-113",
+ "cwes": [
+ "CWE-113"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled input is concatenated directly into an HTTP response",
+ "detection_target": "Taint flow from request input into HTTP header construction",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": [
+ 35
+ ]
+ },
+ {
+ "id": "py-unsafe-yaml-load",
+ "file": "vulns/python/cwe-1336-python.py",
+ "title": "Unsafe deserialization of untrusted YAML input",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-1336",
+ "cwes": [
+ "CWE-1336"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled YAML data is deserialized with yaml.load() without",
+ "detection_target": "Taint flow from request input into yaml.load without a safe",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "py-cwe209-error-message-disclosure",
+ "file": "vulns/python/cwe-209-python.py",
+ "title": "Error message disclosure in HTTP exception response",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-209",
+ "cwes": [
+ "CWE-209"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "User-controlled input triggers an exception whose message is",
+ "detection_target": "Taint flow from request input into exception message that",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 32
+ ],
+ "safe_lines": [
+ 41
+ ]
+ },
+ {
+ "id": "py-weak-rsa-key-generation",
+ "file": "vulns/python/cwe-326-python.py",
+ "title": "RSA key generation with insufficient key size",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-326",
+ "cwes": [
+ "CWE-326"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "RSA key pair is generated with a 512-bit modulus, which is",
+ "detection_target": "Taint flow from hardcoded key size parameter into",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": [
+ 37,
+ 46
+ ]
+ },
+ {
+ "id": "py-weak-random-token",
+ "file": "vulns/python/cwe-330-python.py",
+ "title": "Weak random session token generation",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-330",
+ "cwes": [
+ "CWE-330"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "Uses random.random() to generate a session token, which is",
+ "detection_target": "Taint flow from random.random() into a session token value",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24
+ ],
+ "safe_lines": [
+ 29
+ ]
+ },
+ {
+ "id": "py-race-condition-file-check",
+ "file": "vulns/python/cwe-362-python.py",
+ "title": "TOCTOU race condition on file existence check before write",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-362",
+ "cwes": [
+ "CWE-362"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "The application checks whether a file exists before writing to it,",
+ "detection_target": "Taint flow from request input into os.path.exists followed by",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 28
+ ],
+ "safe_lines": [
34
+ ]
+ },
+ {
+ "id": "py-http-request-smuggling-clte",
+ "file": "vulns/python/cwe-444-python.py",
+ "title": "HTTP request smuggling via Content-Length and Transfer-Encoding conflict",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-444",
+ "cwes": [
+ "CWE-444"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A vulnerable HTTP parser trusts both Content-Length and Transfer-Encoding",
+ "detection_target": "Taint flow from raw HTTP request bytes into a parser that",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 37
+ ],
+ "safe_lines": [
+ 56
+ ]
+ },
+ {
+ "id": "py-embedded-malicious-code",
+ "file": "vulns/python/cwe-506-python.py",
+ "title": "Embedded backdoor in authentication logic",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-506",
+ "cwes": [
+ "CWE-506"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "The vulnerable function contains embedded malicious code that",
+ "detection_target": "Taint flow from hardcoded backdoor credential into",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 29
+ ],
+ "safe_lines": [
+ 41
+ ]
+ },
+ {
+ "id": "py-cwe-626-generator-option-confusion",
+ "file": "vulns/python/cwe-626-python.py",
+ "title": "Generator option confusion leading to unsafe bytecode generation",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-626",
+ "cwes": [
+ "CWE-626"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled generator options are passed to a code generation",
+ "detection_target": "Taint flow from request input into a generator/compiler",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": [
+ 38
+ ]
+ },
+ {
+ "id": "py-idor-object-reference",
+ "file": "vulns/python/cwe-639-python.py",
+ "title": "Insecure direct object reference in user profile update endpoint",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-639",
+ "cwes": [
+ "CWE-639"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled user_id parameter is used directly to update",
+ "detection_target": "Taint flow from request input into a database update",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 31
+ ],
+ "safe_lines": [
+ 38,
+ 46
+ ]
+ },
+ {
+ "id": "py-xss-reflected-html",
+ "file": "vulns/python/cwe-79-python.py",
+ "title": "Reflected XSS via unescaped user input in HTML response",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-79",
+ "cwes": [
+ "CWE-79"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled search query is embedded directly into an HTML",
+ "detection_target": "Taint flow from request input into HTML response string",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "py-cwe835-infinite-loop",
+ "file": "vulns/python/cwe-835-python.py",
+ "title": "Infinite loop from attacker-controlled loop bound",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-835",
+ "cwes": [
+ "CWE-835"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "User-controlled numeric input is used directly as a loop bound",
+ "detection_target": "Taint flow from request input into a loop bound without",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 25
+ ],
+ "safe_lines": [
+ 35
+ ]
+ },
+ {
+ "id": "py-cwe915-unsafe-deserialization",
+ "file": "vulns/python/cwe-915-python.py",
+ "title": "Unsafe deserialization of attacker-controlled pickle data",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-915",
+ "cwes": [
+ "CWE-915"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "User-supplied serialized data is passed directly to pickle.loads,",
+ "detection_target": "Taint flow from request input into pickle.loads without",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 26
+ ],
+ "safe_lines": [
+ 37
+ ]
+ },
+ {
+ "id": "py-excessive-data-exposure",
+ "file": "vulns/python/excessive-data-exposure.py",
+ "title": "Excessive user-record exposure in an API response",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-201",
+ "cwes": [
+ "CWE-201"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A handler serializes the complete database record, including",
+ "detection_target": "Sensitive record fields reaching a response serializer without",
+ "safe_guard": "Both examples are unreachable behind if False and only transform",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 18
+ ],
+ "safe_lines": [
+ 26
+ ]
+ },
+ {
+ "id": "py-flask-debug-enabled",
+ "file": "vulns/python/flask-debug-enabled.py",
+ "title": "Flask debug mode enabled in application configuration",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-489",
+ "cwes": [
+ "CWE-489"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "Enabling Flask debug mode can expose detailed application state",
+ "detection_target": "Flask configuration that sets DEBUG or app.debug to True,",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 23
+ ],
+ "safe_lines": [
+ 26
+ ]
+ },
+ {
+ "id": "py-hardcoded-session-secret",
+ "file": "vulns/python/hardcoded-session-secret.py",
+ "title": "Hardcoded secret used to configure session signing",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-798",
+ "cwes": [
+ "CWE-798"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An obviously synthetic signing secret is embedded in source rather",
+ "detection_target": "Fixed high-entropy-looking literals assigned to SECRET_KEY or",
+ "safe_guard": "The literal is a repeating test placeholder, configuration is behind",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 18
],
"safe_lines": [
- 46,
+ 23
+ ]
+ },
+ {
+ "id": "py-insecure-random-token",
+ "file": "vulns/python/insecure-random-token.py",
+ "title": "Security tokens derived from a predictable PRNG",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-338",
+ "cwes": [
+ "CWE-338"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "Password-reset tokens, session identifiers and MFA codes are drawn",
+ "detection_target": "Use of the `random` module (or a time-derived seed) on a value",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 34,
+ 35,
+ 38,
+ 41
+ ],
+ "safe_lines": [
+ 44,
+ 47,
50
]
},
{
- "id": "js-tls-reject-unauthorized-false",
- "file": "vulns/javascript/tls-reject-unauthorized-false.js",
- "title": "TLS certificate validation disabled on an HTTPS agent",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-295",
+ "id": "py-insecure-temp-file",
+ "file": "vulns/python/insecure-temp-file.py",
+ "title": "Insecure temp file creation with predictable path",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-377",
"cwes": [
- "CWE-295"
+ "CWE-377"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A temporary file is created in the shared /tmp directory using a",
+ "detection_target": "open()/write() to a path built from tempfile or /tmp with a",
+ "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24,
+ 33,
+ 35
+ ],
+ "safe_lines": [
+ 48
+ ]
+ },
+ {
+ "id": "py-ldap-injection",
+ "file": "vulns/python/ldap-injection.py",
+ "title": "LDAP injection via unescaped search filter",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-90",
+ "cwes": [
+ "CWE-90"
],
"severity": "high",
"expected_detection": true,
- "description": "An HTTPS agent sets rejectUnauthorized to false, allowing an",
- "detection_target": "rejectUnauthorized set to false in TLS, HTTPS, request, or",
- "safe_guard": "The entire fixture is wrapped in if (false), so no agent is",
+ "description": "Attacker-controlled account names are interpolated directly into",
+ "detection_target": "Taint flow from request input into an LDAP search filter",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
"attribution": "line",
"vulnerable_lines": [
- 21
+ 25
],
"safe_lines": [
- 30
+ 31
]
},
{
- "id": "js-xss-dom-innerhtml",
- "file": "vulns/javascript/xss-dom-innerHTML.js",
- "title": "Reflected XSS via innerHTML",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-79",
+ "id": "py-missing-admin-authorization",
+ "file": "vulns/python/missing-admin-authorization.py",
+ "title": "Missing authorization check on administrative handler",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-862",
"cwes": [
- "CWE-79"
+ "CWE-862"
],
"severity": "high",
"expected_detection": true,
- "description": "User-controlled query parameter is assigned directly to innerHTML,",
- "detection_target": "Taint flow from `req.query` / `location.search` into an",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "description": "An authenticated request reaches an administrative data-returning",
+ "detection_target": "Privileged route or function that uses identity data but never",
+ "safe_guard": "All handlers are behind if False and return inert in-memory values;",
"attribution": "line",
"vulnerable_lines": [
- 21,
+ 19
+ ],
+ "safe_lines": [
+ 27
+ ]
+ },
+ {
+ "id": "python-missing-object-level-authz",
+ "file": "vulns/python/missing-object-level-authz.py",
+ "title": "Object-level authorization missing on document fetch",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-285",
+ "cwes": [
+ "CWE-285"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "An API endpoint returns a document by ID without verifying that",
+ "detection_target": "Fetching a resource by ID without an ownership/ACL check;",
+ "safe_guard": "Both handlers are unreachable behind `if False:`; no database",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 23
+ ],
+ "safe_lines": [
+ 30
+ ]
+ },
+ {
+ "id": "py-negative-price-validation",
+ "file": "vulns/python/negative-price-validation.py",
+ "title": "Missing range validation for a user-supplied price",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-20",
+ "cwes": [
+ "CWE-20"
+ ],
+ "severity": "medium",
+ "expected_detection": true,
+ "description": "A user-controlled numeric price is accepted without checking for a",
+ "detection_target": "Numeric request data used in a security-sensitive calculation",
+ "safe_guard": "Every example is behind if False and returns an in-memory mapping;",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 20
+ ],
+ "safe_lines": [
29
+ ]
+ },
+ {
+ "id": "py-path-traversal-open",
+ "file": "vulns/python/path-traversal-open.py",
+ "title": "Path traversal via unvalidated filename in open()",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-22",
+ "cwes": [
+ "CWE-22"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A user-supplied filename is joined onto a base directory and opened",
+ "detection_target": "Taint flow from request input into open() / os.path.join()",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 27,
+ 36
],
"safe_lines": [
- 41
+ 47,
+ 52
]
},
{
- "id": "js-xss-eval-user-input",
- "file": "vulns/javascript/xss-eval-user-input.js",
- "title": "Code injection via eval() of user input",
- "category": "javascript",
- "language": "javascript",
- "cwe": "CWE-95",
+ "id": "py-pickle-deserialization",
+ "file": "vulns/python/pickle-deserialization.py",
+ "title": "Insecure deserialisation via pickle / yaml.load",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-502",
"cwes": [
- "CWE-95"
+ "CWE-502"
],
"severity": "critical",
"expected_detection": true,
- "description": "User-supplied expression is passed to eval(), and to the",
- "detection_target": "Taint flow from request input into eval / new Function /",
- "safe_guard": "Wrapped in if (false) \u2014 the body is unreachable dead code.",
+ "description": "Untrusted bytes are passed to pickle.loads and yaml.load with the",
+ "detection_target": "pickle.loads / pickle.load / yaml.load(Loader=yaml.Loader) /",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
"attribution": "line",
"vulnerable_lines": [
- 21,
28,
36
],
"safe_lines": [
- 47
+ 48,
+ 60
+ ]
+ },
+ {
+ "id": "py-plaintext-password-storage",
+ "file": "vulns/python/plaintext-password-storage.py",
+ "title": "Plaintext password retained in a persistence record",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-256",
+ "cwes": [
+ "CWE-256"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "A registration helper copies a raw password into the record that",
+ "detection_target": "Password input assigned directly to a storage-bound field",
+ "safe_guard": "The helpers are behind if False and only construct dictionaries;",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 18
+ ],
+ "safe_lines": [
+ 26
+ ]
+ },
+ {
+ "id": "py-rce-os-system",
+ "file": "vulns/python/rce-os-system.py",
+ "title": "OS command injection via os.system / subprocess shell=True",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-78",
+ "cwes": [
+ "CWE-78"
+ ],
+ "severity": "critical",
+ "expected_detection": true,
+ "description": "User input is interpolated into a command string executed through a",
+ "detection_target": "Taint flow from request input into os.system, os.popen, or",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24,
+ 31,
+ 37
+ ],
+ "safe_lines": [
+ 47
+ ]
+ },
+ {
+ "id": "py-redos-catastrophic-regex",
+ "file": "vulns/python/redos-catastrophic-regex.py",
+ "title": "ReDoS via catastrophic backtracking regex on user input",
+ "category": "python",
+ "language": "python",
+ "cwe": "CWE-1333",
+ "cwes": [
+ "CWE-1333"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A user-supplied string is matched against a regex with nested",
+ "detection_target": "Regex pattern with nested quantifiers applied to",
+ "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 22,
+ 29,
+ 35
+ ],
+ "safe_lines": [
+ 45
]
},
{
- "id": "py-csv-formula-injection",
- "file": "vulns/python/csv-formula-injection.py",
- "title": "CSV formula injection from untrusted spreadsheet cells",
+ "id": "py-sqli-string-format",
+ "file": "vulns/python/sqli-string-format.py",
+ "title": "SQL injection via string formatting",
"category": "python",
"language": "python",
- "cwe": "CWE-1236",
+ "cwe": "CWE-89",
"cwes": [
- "CWE-1236"
+ "CWE-89"
],
- "severity": "medium",
+ "severity": "critical",
"expected_detection": true,
- "description": "User-controlled text beginning with spreadsheet formula prefixes",
- "detection_target": "Taint flow from request input into csv.writer.writerow",
- "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "description": "Request parameters are interpolated into SQL with %-formatting and",
+ "detection_target": "Taint flow from request input into cursor.execute() where the",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 28
+ 21,
+ 29,
+ 35
],
"safe_lines": [
- 40
+ 45
]
},
{
- "id": "py-excessive-data-exposure",
- "file": "vulns/python/excessive-data-exposure.py",
- "title": "Excessive user-record exposure in an API response",
+ "id": "py-ssrf-requests-user-url",
+ "file": "vulns/python/ssrf-requests-user-url.py",
+ "title": "Server-side request forgery via requests.get on user-supplied URL",
"category": "python",
"language": "python",
- "cwe": "CWE-201",
+ "cwe": "CWE-918",
"cwes": [
- "CWE-201"
+ "CWE-918"
],
"severity": "high",
"expected_detection": true,
- "description": "A handler serializes the complete database record, including",
- "detection_target": "Sensitive record fields reaching a response serializer without",
- "safe_guard": "Both examples are unreachable behind if False and only transform",
+ "description": "A URL supplied by the request body is passed directly to",
+ "detection_target": "Taint flow from request input into requests.get/urlopen",
+ "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
"attribution": "line",
"vulnerable_lines": [
- 18
+ 25,
+ 33
],
"safe_lines": [
- 26
+ 44
]
},
{
- "id": "py-flask-debug-enabled",
- "file": "vulns/python/flask-debug-enabled.py",
- "title": "Flask debug mode enabled in application configuration",
+ "id": "py-stack-trace-exposure",
+ "file": "vulns/python/stack-trace-exposure.py",
+ "title": "Sensitive information exposure via raw stack trace in HTTP response",
"category": "python",
"language": "python",
- "cwe": "CWE-489",
+ "cwe": "CWE-209",
"cwes": [
- "CWE-489"
+ "CWE-209"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "Enabling Flask debug mode can expose detailed application state",
- "detection_target": "Flask configuration that sets DEBUG or app.debug to True,",
- "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "description": "An unhandled exception inside a request handler is returned to the",
+ "detection_target": "Exception handler or framework debug mode that echoes the",
+ "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
"attribution": "line",
"vulnerable_lines": [
- 23
+ 28,
+ 36
],
"safe_lines": [
- 26
+ 48
]
},
{
- "id": "py-hardcoded-session-secret",
- "file": "vulns/python/hardcoded-session-secret.py",
- "title": "Hardcoded secret used to configure session signing",
+ "id": "py-toctou-race-condition",
+ "file": "vulns/python/toctou-race-condition.py",
+ "title": "TOCTOU race condition in file access",
"category": "python",
"language": "python",
- "cwe": "CWE-798",
+ "cwe": "CWE-362",
"cwes": [
- "CWE-798"
+ "CWE-362",
+ "CWE-377"
],
- "severity": "high",
+ "severity": "medium",
"expected_detection": true,
- "description": "An obviously synthetic signing secret is embedded in source rather",
- "detection_target": "Fixed high-entropy-looking literals assigned to SECRET_KEY or",
- "safe_guard": "The literal is a repeating test placeholder, configuration is behind",
+ "description": "The code checks a path's properties and then acts on the path in a",
+ "detection_target": "os.path.exists / os.access / os.stat followed by a separate",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
"attribution": "line",
"vulnerable_lines": [
- 18
+ 31,
+ 40,
+ 47
],
"safe_lines": [
- 23
+ 59,
+ 74
]
},
{
- "id": "py-insecure-random-token",
- "file": "vulns/python/insecure-random-token.py",
- "title": "Security tokens derived from a predictable PRNG",
+ "id": "py-weak-crypto-md5",
+ "file": "vulns/python/weak-crypto-md5.py",
+ "title": "Weak cryptographic algorithms for integrity and confidentiality",
"category": "python",
"language": "python",
- "cwe": "CWE-338",
+ "cwe": "CWE-327",
"cwes": [
- "CWE-338"
+ "CWE-327"
],
"severity": "high",
"expected_detection": true,
- "description": "Password-reset tokens, session identifiers and MFA codes are drawn",
- "detection_target": "Use of the `random` module (or a time-derived seed) on a value",
+ "description": "Broken primitives are used where a security guarantee is claimed:",
+ "detection_target": "Selection of a broken hash or cipher primitive at the call",
"safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
"attribution": "line",
"vulnerable_lines": [
- 34,
- 35,
- 38,
- 41
+ 37,
+ 41,
+ 50,
+ 54,
+ 58
],
"safe_lines": [
- 44,
- 47,
- 50
+ 45,
+ 62
]
},
{
- "id": "py-insecure-temp-file",
- "file": "vulns/python/insecure-temp-file.py",
- "title": "Insecure temp file creation with predictable path",
+ "id": "py-weak-password-hash",
+ "file": "vulns/python/weak-password-hash.py",
+ "title": "Password hashing without a salt",
"category": "python",
"language": "python",
- "cwe": "CWE-377",
+ "cwe": "CWE-759",
"cwes": [
- "CWE-377"
+ "CWE-759"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "A temporary file is created in the shared /tmp directory using a",
- "detection_target": "open()/write() to a path built from tempfile or /tmp with a",
- "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "description": "Passwords are hashed directly with SHA-256 and no per-account",
+ "detection_target": "Password data passed to a general-purpose hash without a",
+ "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
"attribution": "line",
"vulnerable_lines": [
- 24,
- 33,
- 35
+ 25
],
"safe_lines": [
- 48
+ 34
]
},
{
- "id": "py-ldap-injection",
- "file": "vulns/python/ldap-injection.py",
- "title": "LDAP injection via unescaped search filter",
+ "id": "py-xpath-injection",
+ "file": "vulns/python/xpath-injection.py",
+ "title": "XPath injection via string interpolation",
"category": "python",
"language": "python",
- "cwe": "CWE-90",
+ "cwe": "CWE-643",
"cwes": [
- "CWE-90"
+ "CWE-643"
],
"severity": "high",
"expected_detection": true,
- "description": "Attacker-controlled account names are interpolated directly into",
- "detection_target": "Taint flow from request input into an LDAP search filter",
+ "description": "Untrusted user names are inserted into an XPath expression,",
+ "detection_target": "Taint flow from request input into document.xpath where the",
"safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
"attribution": "line",
"vulnerable_lines": [
- 25
+ 22
],
"safe_lines": [
- 31
+ 28
]
},
{
- "id": "py-missing-admin-authorization",
- "file": "vulns/python/missing-admin-authorization.py",
- "title": "Missing authorization check on administrative handler",
+ "id": "py-xss-jinja2-autoescape-off",
+ "file": "vulns/python/xss-jinja2-autoescape-off.py",
+ "title": "XSS via Jinja2 autoescape disabled and server-side template injection",
"category": "python",
"language": "python",
- "cwe": "CWE-862",
+ "cwe": "CWE-79",
"cwes": [
- "CWE-862"
+ "CWE-79",
+ "CWE-1336"
],
"severity": "high",
"expected_detection": true,
- "description": "An authenticated request reaches an administrative data-returning",
- "detection_target": "Privileged route or function that uses identity data but never",
- "safe_guard": "All handlers are behind if False and return inert in-memory values;",
+ "description": "A Jinja2 Environment is constructed with autoescape=False, so",
+ "detection_target": "Environment(autoescape=False), render_template_string on",
+ "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 19
+ 24,
+ 34,
+ 43
],
"safe_lines": [
- 27
+ 53
]
},
{
- "id": "py-negative-price-validation",
- "file": "vulns/python/negative-price-validation.py",
- "title": "Missing range validation for a user-supplied price",
- "category": "python",
- "language": "python",
- "cwe": "CWE-20",
+ "id": "rb-prototype-pollution-merge-params",
+ "file": "vulns/ruby/cwe-1321-ruby.rb",
+ "title": "Prototype pollution via unsafe deep merge of user-controlled parameters",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-1321",
"cwes": [
- "CWE-20"
+ "CWE-1321"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "A user-controlled numeric price is accepted without checking for a",
- "detection_target": "Numeric request data used in a security-sensitive calculation",
- "safe_guard": "Every example is behind if False and returns an in-memory mapping;",
+ "description": "User-controlled parameters are passed to a recursive merge function",
+ "detection_target": "Taint flow from user-controlled parameters into a recursive",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 20
+ 30
],
"safe_lines": [
- 29
+ 51,
+ 66
]
},
{
- "id": "py-path-traversal-open",
- "file": "vulns/python/path-traversal-open.py",
- "title": "Path traversal via unvalidated filename in open()",
- "category": "python",
- "language": "python",
- "cwe": "CWE-22",
+ "id": "rb-command-injection-shellwords-unsafe",
+ "file": "vulns/ruby/cwe-20-ruby.rb",
+ "title": "Command injection via unsafe shell command construction from user input",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-20",
"cwes": [
- "CWE-22"
+ "CWE-20"
],
"severity": "high",
"expected_detection": true,
- "description": "A user-supplied filename is joined onto a base directory and opened",
- "detection_target": "Taint flow from request input into open() / os.path.join()",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
+ "description": "User-controlled input is concatenated into a shell command string",
+ "detection_target": "Taint flow from user-controlled input into a shell command",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 27,
- 36
+ 28
],
"safe_lines": [
- 47,
- 52
+ 43
]
},
{
- "id": "py-pickle-deserialization",
- "file": "vulns/python/pickle-deserialization.py",
- "title": "Insecure deserialisation via pickle / yaml.load",
- "category": "python",
- "language": "python",
- "cwe": "CWE-502",
+ "id": "rb-missing-authorization-role-check",
+ "file": "vulns/ruby/cwe-284-ruby.rb",
+ "title": "Missing role-based authorization check in admin report generation",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-284",
"cwes": [
- "CWE-502"
+ "CWE-284"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Untrusted bytes are passed to pickle.loads and yaml.load with the",
- "detection_target": "pickle.loads / pickle.load / yaml.load(Loader=yaml.Loader) /",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
+ "description": "User-controlled role data from the session is used to generate",
+ "detection_target": "Taint flow from session role data into sensitive report",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 28,
- 36
+ 29,
+ 40
],
- "safe_lines": [
- 48,
- 60
+ "safe_lines": [
+ 49,
+ 50
]
},
{
- "id": "py-plaintext-password-storage",
- "file": "vulns/python/plaintext-password-storage.py",
- "title": "Plaintext password retained in a persistence record",
- "category": "python",
- "language": "python",
- "cwe": "CWE-256",
+ "id": "rb-missing-auth-session",
+ "file": "vulns/ruby/cwe-306-ruby.rb",
+ "title": "Missing authentication check in session-based file access handler",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-306",
"cwes": [
- "CWE-256"
+ "CWE-306"
],
"severity": "critical",
"expected_detection": true,
- "description": "A registration helper copies a raw password into the record that",
- "detection_target": "Password input assigned directly to a storage-bound field",
- "safe_guard": "The helpers are behind if False and only construct dictionaries;",
+ "description": "User-controlled session data is used to access and return file",
+ "detection_target": "Taint flow from params/session into file read operations",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 18
+ 28,
+ 38
],
"safe_lines": [
- 26
+ 47,
+ 48
]
},
{
- "id": "py-rce-os-system",
- "file": "vulns/python/rce-os-system.py",
- "title": "OS command injection via os.system / subprocess shell=True",
- "category": "python",
- "language": "python",
- "cwe": "CWE-78",
+ "id": "rb-hardcoded-api-key-aws",
+ "file": "vulns/ruby/cwe-321-ruby.rb",
+ "title": "Hardcoded AWS API credentials in Ruby application code",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-321",
"cwes": [
- "CWE-78"
+ "CWE-321"
],
"severity": "critical",
"expected_detection": true,
- "description": "User input is interpolated into a command string executed through a",
- "detection_target": "Taint flow from request input into os.system, os.popen, or",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
+ "description": "The application uses hardcoded AWS access key and secret access key",
+ "detection_target": "Hardcoded AWS access key and secret access key strings in",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 24,
- 31,
- 37
+ 28
],
"safe_lines": [
- 47
+ 53
]
},
{
- "id": "py-redos-catastrophic-regex",
- "file": "vulns/python/redos-catastrophic-regex.py",
- "title": "ReDoS via catastrophic backtracking regex on user input",
- "category": "python",
- "language": "python",
- "cwe": "CWE-1333",
+ "id": "rb-signature-verification-missing-verify",
+ "file": "vulns/ruby/cwe-347-ruby.rb",
+ "title": "JWT signature verification bypass via unverified token payload",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-347",
"cwes": [
- "CWE-1333"
+ "CWE-347"
],
"severity": "high",
"expected_detection": true,
- "description": "A user-supplied string is matched against a regex with nested",
- "detection_target": "Regex pattern with nested quantifiers applied to",
- "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "description": "User-controlled JWT token is decoded without verifying the",
+ "detection_target": "Taint flow from user-controlled token into a JWT decode",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 22,
- 29,
- 35
+ 26
],
"safe_lines": [
- 45
+ 43,
+ 51
]
},
{
- "id": "py-sqli-string-format",
- "file": "vulns/python/sqli-string-format.py",
- "title": "SQL injection via string formatting",
- "category": "python",
- "language": "python",
- "cwe": "CWE-89",
+ "id": "rb-untrusted-search-path",
+ "file": "vulns/ruby/cwe-426-ruby.rb",
+ "title": "Untrusted search path allows arbitrary code execution via library loading",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-426",
"cwes": [
- "CWE-89"
+ "CWE-426"
],
- "severity": "critical",
+ "severity": "high",
"expected_detection": true,
- "description": "Request parameters are interpolated into SQL with %-formatting and",
- "detection_target": "Taint flow from request input into cursor.execute() where the",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
+ "description": "The application loads a shared library using a relative path",
+ "detection_target": "Taint flow from user-controlled input into library loading",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 21,
- 29,
+ 27,
35
],
"safe_lines": [
- 45
+ 45,
+ 46,
+ 58,
+ 59
]
},
{
- "id": "py-ssrf-requests-user-url",
- "file": "vulns/python/ssrf-requests-user-url.py",
- "title": "Server-side request forgery via requests.get on user-supplied URL",
- "category": "python",
- "language": "python",
- "cwe": "CWE-918",
+ "id": "rb-active-record-debug-mode",
+ "file": "vulns/ruby/cwe-489-ruby.rb",
+ "title": "Active Record debug mode enabled in production allowing sensitive query logging",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-489",
"cwes": [
- "CWE-918"
+ "CWE-489"
],
"severity": "high",
"expected_detection": true,
- "description": "A URL supplied by the request body is passed directly to",
- "detection_target": "Taint flow from request input into requests.get/urlopen",
- "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "description": "The application enables Active Record's debug mode in a production",
+ "detection_target": "Taint flow from environment configuration into Active Record",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 25,
- 33
+ 28
],
"safe_lines": [
- 44
+ 46,
+ 54
]
},
{
- "id": "py-stack-trace-exposure",
- "file": "vulns/python/stack-trace-exposure.py",
- "title": "Sensitive information exposure via raw stack trace in HTTP response",
- "category": "python",
- "language": "python",
- "cwe": "CWE-209",
+ "id": "rb-unsafe-deserialization-yaml",
+ "file": "vulns/ruby/cwe-494-ruby.rb",
+ "title": "Unsafe deserialization of attacker-controlled YAML data",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-494",
"cwes": [
- "CWE-209"
+ "CWE-494"
],
- "severity": "medium",
+ "severity": "critical",
"expected_detection": true,
- "description": "An unhandled exception inside a request handler is returned to the",
- "detection_target": "Exception handler or framework debug mode that echoes the",
- "safe_guard": "Wrapped in if False \u2014 the body is unreachable dead code. All",
+ "description": "The application deserializes YAML data from an external source",
+ "detection_target": "Taint flow from params/external input into YAML.load",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 28,
- 36
+ 31,
+ 41
],
"safe_lines": [
- 48
+ 53,
+ 65
]
},
{
- "id": "py-toctou-race-condition",
- "file": "vulns/python/toctou-race-condition.py",
- "title": "TOCTOU race condition in file access",
- "category": "python",
- "language": "python",
- "cwe": "CWE-362",
+ "id": "ruby-xxe-libxml-entity-expansion",
+ "file": "vulns/ruby/cwe-611-ruby.rb",
+ "title": "XML External Entity (XXE) injection via unsafe XML parsing of user-controlled input",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-611",
"cwes": [
- "CWE-362",
- "CWE-377"
+ "CWE-611"
],
- "severity": "medium",
+ "severity": "high",
"expected_detection": true,
- "description": "The code checks a path's properties and then acts on the path in a",
- "detection_target": "os.path.exists / os.access / os.stat followed by a separate",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code. No",
+ "description": "User-controlled XML input is parsed with libxml's default settings,",
+ "detection_target": "Taint flow from user-controlled XML input into an XML parser",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 31,
- 40,
- 47
+ 26
],
"safe_lines": [
- 59,
- 74
+ 42,
+ 50
]
},
{
- "id": "py-weak-crypto-md5",
- "file": "vulns/python/weak-crypto-md5.py",
- "title": "Weak cryptographic algorithms for integrity and confidentiality",
- "category": "python",
- "language": "python",
- "cwe": "CWE-327",
+ "id": "rb-cwe759-unsalted-md5-password-hash",
+ "file": "vulns/ruby/cwe-759-ruby.rb",
+ "title": "Unsalted MD5 hash used for password storage, vulnerable to rainbow table attacks",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-759",
"cwes": [
- "CWE-327"
+ "CWE-759"
],
"severity": "high",
"expected_detection": true,
- "description": "Broken primitives are used where a security guarantee is claimed:",
- "detection_target": "Selection of a broken hash or cipher primitive at the call",
- "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "description": "User passwords are hashed using unsalted MD5, which is a weak",
+ "detection_target": "Taint flow from user-controlled password into an unsalted",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 37,
- 41,
- 50,
- 54,
- 58
+ 28
],
"safe_lines": [
- 45,
- 62
+ 44,
+ 50
]
},
{
- "id": "py-weak-password-hash",
- "file": "vulns/python/weak-password-hash.py",
- "title": "Password hashing without a salt",
- "category": "python",
- "language": "python",
- "cwe": "CWE-759",
+ "id": "rb-unbounded-memory-allocation",
+ "file": "vulns/ruby/cwe-770-ruby.rb",
+ "title": "Unbounded memory allocation from user-controlled size parameter",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-770",
"cwes": [
- "CWE-759"
+ "CWE-770"
],
"severity": "high",
"expected_detection": true,
- "description": "Passwords are hashed directly with SHA-256 and no per-account",
- "detection_target": "Password data passed to a general-purpose hash without a",
- "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "description": "User-controlled size parameter is used directly to allocate",
+ "detection_target": "Taint flow from params into memory allocation operations",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 25
+ 28,
+ 38
],
"safe_lines": [
- 34
+ 50,
+ 51,
+ 65,
+ 66
]
},
{
- "id": "py-xpath-injection",
- "file": "vulns/python/xpath-injection.py",
- "title": "XPath injection via string interpolation",
- "category": "python",
- "language": "python",
- "cwe": "CWE-643",
+ "id": "rb-sql-injection-user-input-query",
+ "file": "vulns/ruby/cwe-89-ruby.rb",
+ "title": "SQL injection via unsanitized user input in database query",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-89",
"cwes": [
- "CWE-643"
+ "CWE-89"
],
- "severity": "high",
+ "severity": "critical",
"expected_detection": true,
- "description": "Untrusted user names are inserted into an XPath expression,",
- "detection_target": "Taint flow from request input into document.xpath where the",
- "safe_guard": "The entire fixture is wrapped in `if False:` and cannot execute. It",
+ "description": "User-controlled input is concatenated directly into a SQL query",
+ "detection_target": "Taint flow from user-controlled parameters into a SQL",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 22
+ 26
],
"safe_lines": [
- 28
+ 42,
+ 50
]
},
{
- "id": "py-xss-jinja2-autoescape-off",
- "file": "vulns/python/xss-jinja2-autoescape-off.py",
- "title": "XSS via Jinja2 autoescape disabled and server-side template injection",
- "category": "python",
- "language": "python",
- "cwe": "CWE-79",
+ "id": "rb-unsafe-deserialization-marshal-load",
+ "file": "vulns/ruby/cwe-943-ruby.rb",
+ "title": "Unsafe deserialization of user-controlled data via Marshal.load",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-943",
"cwes": [
- "CWE-79",
- "CWE-1336"
+ "CWE-943"
],
- "severity": "high",
+ "severity": "critical",
"expected_detection": true,
- "description": "A Jinja2 Environment is constructed with autoescape=False, so",
- "detection_target": "Environment(autoescape=False), render_template_string on",
- "safe_guard": "Every payload lives behind `if False:` \u2014 unreachable dead code.",
+ "description": "User-controlled serialized data is passed directly to Marshal.load,",
+ "detection_target": "Taint flow from user-controlled input into Marshal.load without",
+ "safe_guard": "Every payload sits inside `if false` \u2014 unreachable dead code.",
"attribution": "line",
"vulnerable_lines": [
- 24,
- 34,
- 43
+ 27
],
"safe_lines": [
- 53
+ 43,
+ 49
]
},
{
@@ -1331,6 +3016,29 @@
47
]
},
+ {
+ "id": "ruby-relative-path-traversal",
+ "file": "vulns/ruby/relative-path-traversal.rb",
+ "title": "Relative path traversal in File.open via unsanitized user input",
+ "category": "ruby",
+ "language": "ruby",
+ "cwe": "CWE-23",
+ "cwes": [
+ "CWE-23"
+ ],
+ "severity": "high",
+ "expected_detection": true,
+ "description": "A user-supplied filename is joined with a base directory and",
+ "detection_target": "File.open/File.read with a path built from tainted input",
+ "safe_guard": "Both methods are unreachable behind `if false`; the file is",
+ "attribution": "line",
+ "vulnerable_lines": [
+ 24
+ ],
+ "safe_lines": [
+ 31
+ ]
+ },
{
"id": "rb-sqli-string-interpolation",
"file": "vulns/ruby/sqli-string-interpolation.rb",
diff --git a/vulns/go/cwe-1236-go.go b/vulns/go/cwe-1236-go.go
new file mode 100644
index 0000000..5cfc76d
--- /dev/null
+++ b/vulns/go/cwe-1236-go.go
@@ -0,0 +1,73 @@
+// @id go-cwe-1236-csv-injection
+// @test-case CSV injection via user-controlled input written to a CSV file
+// @cwe CWE-1236
+// @severity high
+// @language go
+// @expected-detection true
+// @description User input is written directly into a CSV file without sanitization.
+// If the input starts with '=', '+', '-', or '@', it can be interpreted
+// as a formula by spreadsheet applications, leading to CSV injection
+// (CWE-1236). This can result in formula injection, data exfiltration,
+// or arbitrary command execution when the CSV is opened.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no file is ever written.
+// @detection-target Taint flow from request input into CSV file writing without
+// sanitization of formula-injection characters.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "encoding/csv"
+ "net/http"
+ "os"
+ "strings"
+)
+
+func exportVulnerable(r *http.Request) error {
+ if neverRun {
+ userInput := r.URL.Query().Get("data") // SOURCE: attacker-controlled
+ file, err := os.Create("/tmp/export.csv")
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ writer := csv.NewWriter(file)
+ defer writer.Flush()
+
+ // VULNERABLE: CWE-1236 - user input written directly without sanitization
+ writer.Write([]string{userInput})
+ return nil
+ }
+ return nil
+}
+
+// exportSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func exportSafe(r *http.Request) error {
+ if neverRun {
+ userInput := r.URL.Query().Get("data") // SOURCE
+ file, err := os.Create("/tmp/export_safe.csv")
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ writer := csv.NewWriter(file)
+ defer writer.Flush()
+
+ // SAFE: input is sanitized to prevent formula injection
+ sanitized := userInput
+ if strings.HasPrefix(sanitized, "=") || strings.HasPrefix(sanitized, "+") ||
+ strings.HasPrefix(sanitized, "-") || strings.HasPrefix(sanitized, "@") {
+ sanitized = "'" + sanitized
+ }
+ writer.Write([]string{sanitized})
+ return nil
+ }
+ return nil
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-190-go.go b/vulns/go/cwe-190-go.go
new file mode 100644
index 0000000..c6f030f
--- /dev/null
+++ b/vulns/go/cwe-190-go.go
@@ -0,0 +1,62 @@
+// @id go-integer-overflow-parseint
+// @test-case Integer overflow in arithmetic operation after parsing user input
+// @cwe CWE-190
+// @severity high
+// @language go
+// @expected-detection true
+// @description User-controlled input is parsed as an integer and used in an
+// arithmetic operation without bounds checking, leading to integer
+// overflow. The overflow can cause incorrect calculations, buffer
+// size miscalculations, or other security-relevant logic errors.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no arithmetic is ever performed.
+// @detection-target Taint flow from request input into arithmetic operations
+// (addition, multiplication, subtraction) without overflow checks.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "strconv"
+)
+
+func calculateVulnerable(r *http.Request) int {
+ if neverRun {
+ valueStr := r.URL.Query().Get("value") // SOURCE: attacker-controlled
+ value, _ := strconv.Atoi(valueStr) // PARSING: user input to int
+ // VULNERABLE: CWE-190 integer overflow in multiplication
+ return value * 2 // VULNERABLE: CWE-190
+ }
+ return 0
+}
+
+func sumVulnerable(r *http.Request) int {
+ if neverRun {
+ aStr := r.FormValue("a") // SOURCE
+ bStr := r.FormValue("b") // SOURCE
+ a, _ := strconv.Atoi(aStr)
+ b, _ := strconv.Atoi(bStr)
+ // VULNERABLE: CWE-190 integer overflow in addition
+ return a + b // VULNERABLE: CWE-190
+ }
+ return 0
+}
+
+// calculateSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func calculateSafe(r *http.Request) int {
+ if neverRun {
+ valueStr := r.URL.Query().Get("value")
+ value, _ := strconv.ParseInt(valueStr, 10, 32)
+ // SAFE: bounds-checked conversion prevents overflow
+ if value > 0 && value < (1<<31-1)/2 {
+ return int(value * 2)
+ }
+ return 0
+ }
+ return 0
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-287-go.go b/vulns/go/cwe-287-go.go
new file mode 100644
index 0000000..21aa73f
--- /dev/null
+++ b/vulns/go/cwe-287-go.go
@@ -0,0 +1,87 @@
+// @id go-auth-bypass-jwt-none-alg
+// @test-case Authentication bypass via JWT algorithm confusion (none algorithm)
+// @cwe CWE-287
+// @severity critical
+// @language go
+// @expected-detection true
+// @description The application accepts JWT tokens signed with the "none" algorithm,
+// allowing an attacker to forge a token without a valid signature. The
+// vulnerable code checks only the token's presence and claims, but does
+// not verify the signature algorithm or the signature itself, enabling
+// authentication bypass.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no token is ever processed.
+// @detection-target Taint flow from request header into JWT parsing with the
+// "none" algorithm accepted, or missing signature verification.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "encoding/json"
+ "net/http"
+ "strings"
+)
+
+// parseJWT is a minimal JWT parser for demonstration purposes.
+func parseJWT(token string) (map[string]interface{}, error) {
+ parts := strings.Split(token, ".")
+ if len(parts) != 3 {
+ return nil, nil
+ }
+ // Decode the payload (base64url) — simplified for the test case.
+ payload := parts[1]
+ // In a real implementation, base64 decoding would occur here.
+ // For this test, we just return a static payload.
+ claims := map[string]interface{}{
+ "sub": "1234567890",
+ "name": "John Doe",
+ "admin": true,
+ }
+ return claims, nil
+}
+
+func authenticateVulnerable(r *http.Request) bool {
+ if neverRun {
+ authHeader := r.Header.Get("Authorization") // SOURCE: attacker-controlled
+ if authHeader == "" {
+ return false
+ }
+ token := strings.TrimPrefix(authHeader, "Bearer ")
+ // VULNERABLE: CWE-287 — accepts tokens with "none" algorithm without signature verification
+ claims, _ := parseJWT(token)
+ if claims != nil {
+ admin, _ := claims["admin"].(bool)
+ return admin
+ }
+ }
+ return false
+}
+
+// authenticateSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func authenticateSafe(r *http.Request) bool {
+ if neverRun {
+ authHeader := r.Header.Get("Authorization")
+ if authHeader == "" {
+ return false
+ }
+ token := strings.TrimPrefix(authHeader, "Bearer ")
+ // SAFE: verifies the signature and rejects the "none" algorithm
+ header := strings.Split(token, ".")[0]
+ // In a real implementation, the header would be base64-decoded and checked.
+ if strings.Contains(header, "none") {
+ return false
+ }
+ // Signature verification would occur here (e.g., with HMAC or RSA).
+ claims, _ := parseJWT(token)
+ if claims != nil {
+ admin, _ := claims["admin"].(bool)
+ return admin
+ }
+ }
+ return false
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-295-go.go b/vulns/go/cwe-295-go.go
new file mode 100644
index 0000000..3c3e30c
--- /dev/null
+++ b/vulns/go/cwe-295-go.go
@@ -0,0 +1,72 @@
+// @id go-tls-insecure-skip-verify
+// @test-case TLS certificate verification disabled via InsecureSkipVerify
+// @cwe CWE-295
+// @severity high
+// @language go
+// @expected-detection true
+// @description The HTTP client sets InsecureSkipVerify to true, which disables
+// TLS certificate verification. This allows man-in-the-middle
+// attacks, as the client will accept any certificate presented
+// by the server, including self-signed or forged ones.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no network connection is ever made.
+// @detection-target Taint flow from request input into http.Transport with
+// InsecureSkipVerify set to true, or tls.Config with
+// InsecureSkipVerify set to true.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "crypto/tls"
+ "net/http"
+)
+
+func fetchVulnerable(r *http.Request) ([]byte, error) {
+ if neverRun {
+ url := r.URL.Query().Get("url") // SOURCE: attacker-controlled
+ client := &http.Client{
+ Transport: &http.Transport{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true, // VULNERABLE: CWE-295
+ },
+ },
+ }
+ resp, err := client.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ buf := make([]byte, 1024)
+ n, _ := resp.Body.Read(buf)
+ return buf[:n], nil
+ }
+ return nil, nil
+}
+
+// fetchSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func fetchSafe(r *http.Request) ([]byte, error) {
+ if neverRun {
+ url := r.URL.Query().Get("url")
+ client := &http.Client{
+ Transport: &http.Transport{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: false, // SAFE: certificate verification enabled
+ },
+ },
+ }
+ resp, err := client.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ buf := make([]byte, 1024)
+ n, _ := resp.Body.Read(buf)
+ return buf[:n], nil
+ }
+ return nil, nil
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-312-go.go b/vulns/go/cwe-312-go.go
new file mode 100644
index 0000000..540e1eb
--- /dev/null
+++ b/vulns/go/cwe-312-go.go
@@ -0,0 +1,42 @@
+// @id go-cwe312-sensitive-data-logging
+// @test-case Sensitive data (API key) is logged in plaintext
+// @cwe CWE-312
+// @severity high
+// @language go
+// @expected-detection true
+// @description User-supplied API key from an HTTP request header is written
+// directly to the application log via log.Printf. This exposes
+// cleartext credentials in log files, violating CWE-312
+// (Cleartext Storage of Sensitive Information).
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no logging ever occurs.
+// @detection-target Taint flow from request header into log.Printf or
+// log.Println with sensitive data.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "log"
+ "net/http"
+)
+
+func logAPIKeyVulnerable(r *http.Request) {
+ if neverRun {
+ apiKey := r.Header.Get("X-API-Key") // SOURCE: attacker-controlled sensitive data
+ log.Printf("User API key: %s", apiKey) // VULNERABLE: CWE-312 sink
+ }
+}
+
+// logAPIKeySafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func logAPIKeySafe(r *http.Request) {
+ if neverRun {
+ apiKey := r.Header.Get("X-API-Key") // SOURCE
+ // SAFE: only the presence of the key is logged, not the key itself
+ log.Printf("User API key present: %v", apiKey != "")
+ }
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-345-go.go b/vulns/go/cwe-345-go.go
new file mode 100644
index 0000000..6a88060
--- /dev/null
+++ b/vulns/go/cwe-345-go.go
@@ -0,0 +1,106 @@
+// @id go-cwe345-json-signature-verification
+// @test-case JSON data integrity check bypass via missing signature verification
+// @cwe CWE-345
+// @severity high
+// @language go
+// @expected-detection true
+// @description The application receives a JSON payload from an untrusted source
+// and processes it without verifying a digital signature or MAC.
+// An attacker can tamper with the JSON data (e.g., change a price,
+// role, or configuration value) because there is no integrity check.
+// The vulnerable function trusts the data as-is, while the safe
+// function verifies an HMAC signature before processing.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no data is ever processed. The safe function uses
+// HMAC-SHA256 to verify the payload integrity before use.
+// @detection-target Taint flow from request body into JSON unmarshalling and
+// subsequent use without prior signature verification.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "net/http"
+)
+
+type Config struct {
+ AdminEnabled bool `json:"admin_enabled"`
+ MaxRetries int `json:"max_retries"`
+ Endpoint string `json:"endpoint"`
+}
+
+func processConfigVulnerable(r *http.Request) error {
+ if neverRun {
+ var cfg Config
+ // SOURCE: attacker-controlled JSON body
+ if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
+ return err
+ }
+ // VULNERABLE: CWE-345 - no integrity check on the JSON data
+ applyConfig(cfg)
+ }
+ return nil
+}
+
+func processConfigSafe(r *http.Request) error {
+ if neverRun {
+ body := make([]byte, r.ContentLength)
+ if _, err := r.Body.Read(body); err != nil {
+ return err
+ }
+ // SAFE: verify HMAC signature before processing
+ sig := r.Header.Get("X-Signature")
+ if !verifySignature(body, sig) {
+ return nil
+ }
+ var cfg Config
+ if err := json.Unmarshal(body, &cfg); err != nil {
+ return err
+ }
+ applyConfig(cfg)
+ }
+ return nil
+}
+
+// applyConfig is a stub that would apply the configuration in a real system.
+func applyConfig(cfg Config) {}
+
+// verifySignature checks the HMAC-SHA256 signature of the payload.
+func verifySignature(payload []byte, signature string) bool {
+ if neverRun {
+ secret := []byte("test-secret-key")
+ mac := hmac.New(sha256.New, secret)
+ mac.Write(payload)
+ expected := hex.EncodeToString(mac.Sum(nil))
+ return hmac.Equal([]byte(expected), []byte(signature))
+ }
+ return false
+}
+
+// safeConfig is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func safeConfig(r *http.Request) error {
+ if neverRun {
+ body := make([]byte, r.ContentLength)
+ if _, err := r.Body.Read(body); err != nil {
+ return err
+ }
+ // SAFE: signature verified before unmarshalling
+ if !verifySignature(body, r.Header.Get("X-Signature")) {
+ return nil
+ }
+ var cfg Config
+ if err := json.Unmarshal(body, &cfg); err != nil {
+ return err
+ }
+ applyConfig(cfg)
+ }
+ return nil
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-346-go.go b/vulns/go/cwe-346-go.go
new file mode 100644
index 0000000..58c380d
--- /dev/null
+++ b/vulns/go/cwe-346-go.go
@@ -0,0 +1,79 @@
+// @id go-cwe346-origin-validation
+// @test-case CWE-346 Origin validation error via missing Origin header check in WebSocket handshake
+// @cwe CWE-346
+// @severity high
+// @language go
+// @expected-detection true
+// @description The vulnerable function accepts WebSocket upgrade requests without validating the
+// Origin header, allowing cross-site WebSocket hijacking (CSWSH). An attacker can
+// embed a malicious page that initiates a WebSocket connection to the vulnerable
+// server, bypassing same-origin policy. The safe function validates the Origin
+// header against an allowlist of trusted origins before accepting the connection.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore` build tag;
+// no actual WebSocket connection is ever established.
+// @detection-target Taint flow from HTTP request Origin header into WebSocket upgrade acceptance
+// without origin validation, or missing Origin check in upgrade handler.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "strings"
+)
+
+var trustedOrigins = []string{
+ "https://example.com",
+ "https://www.example.com",
+}
+
+func handleWebSocketVulnerable(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ // VULNERABLE: CWE-346 - No Origin header validation before accepting WebSocket upgrade
+ // The Origin header is attacker-controlled and can be set to any value by a malicious page
+ origin := r.Header.Get("Origin") // SOURCE: attacker-controlled Origin header
+ if origin == "" {
+ // Some browsers may not send Origin for same-origin requests, but this is still
+ // vulnerable as an attacker can craft a request without Origin or with a spoofed one
+ http.Error(w, "Upgrade required", http.StatusUpgradeRequired)
+ return
+ }
+ // Missing validation: the Origin is never checked against trustedOrigins
+ // This allows any website to initiate a WebSocket connection to this server
+ upgradeWebSocket(w, r) // VULNERABLE: CWE-346 sink - accepts connection without origin validation
+ }
+}
+
+func handleWebSocketSafe(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ // SAFE: Origin header is validated against an allowlist of trusted origins
+ origin := r.Header.Get("Origin") // SOURCE: attacker-controlled Origin header
+ if !isTrustedOrigin(origin) {
+ http.Error(w, "Forbidden", http.StatusForbidden)
+ return
+ }
+ // SAFE: Only connections from trusted origins are accepted
+ upgradeWebSocket(w, r) // SAFE: origin validated before upgrade
+ }
+}
+
+func isTrustedOrigin(origin string) bool {
+ for _, trusted := range trustedOrigins {
+ if strings.EqualFold(origin, trusted) {
+ return true
+ }
+ }
+ return false
+}
+
+// upgradeWebSocket is a stub that would perform the actual WebSocket upgrade.
+// It is never called in this test file due to the neverRun guard.
+func upgradeWebSocket(w http.ResponseWriter, r *http.Request) {
+ // This function would normally perform the WebSocket handshake
+ // It is intentionally left empty for the test case
+}
+
+// neverRun is a constant that is always false, ensuring the vulnerable code
+// is never executed in production.
+const neverRun = false
\ No newline at end of file
diff --git a/vulns/go/cwe-384-go.go b/vulns/go/cwe-384-go.go
new file mode 100644
index 0000000..096a603
--- /dev/null
+++ b/vulns/go/cwe-384-go.go
@@ -0,0 +1,53 @@
+// @id go-session-fixation-cookie
+// @test-case Session fixation via predictable session ID in Set-Cookie
+// @cwe CWE-384
+// @severity high
+// @language go
+// @expected-detection true
+// @description User-controlled session ID is accepted and set as a cookie
+// without regeneration after login, allowing an attacker to fixate
+// a victim's session. The vulnerable function takes a session ID
+// from the request and sets it directly in the Set-Cookie header.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no HTTP response is ever written.
+// @detection-target Taint flow from request input into Set-Cookie header with
+// a session ID that is not regenerated or validated.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+)
+
+func loginVulnerable(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ sessionID := r.URL.Query().Get("session_id") // SOURCE: attacker-controlled
+ // VULNERABLE: CWE-384 - session fixation, no regeneration
+ http.SetCookie(w, &http.Cookie{
+ Name: "session_id",
+ Value: sessionID,
+ Path: "/",
+ })
+ }
+}
+
+func loginSafe(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ // SAFE: session ID is generated server-side, not taken from user input
+ // @expected-detection false
+ sessionID := generateRandomSessionID()
+ http.SetCookie(w, &http.Cookie{
+ Name: "session_id",
+ Value: sessionID,
+ Path: "/",
+ })
+ }
+}
+
+func generateRandomSessionID() string {
+ return "random-generated-session-id"
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-476-go.go b/vulns/go/cwe-476-go.go
new file mode 100644
index 0000000..47fd46e
--- /dev/null
+++ b/vulns/go/cwe-476-go.go
@@ -0,0 +1,57 @@
+// @id go-nil-pointer-deref-http
+// @test-case Nil pointer dereference on a response body that may be nil
+// @cwe CWE-476
+// @severity high
+// @language go
+// @expected-detection true
+// @description The function calls `resp.Body.Close()` and `io.ReadAll(resp.Body)`
+// without checking whether `resp` or `resp.Body` is nil. If the HTTP
+// request fails or returns a nil response, this causes a nil pointer
+// dereference panic. The vulnerable pattern is dereferencing a nil
+// pointer without a nil check.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no HTTP request is ever made.
+// @detection-target Taint flow from an HTTP response that may be nil into
+// `resp.Body.Close()` or `io.ReadAll(resp.Body)` without a
+// nil check.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "io"
+ "net/http"
+)
+
+func fetchVulnerable(url string) ([]byte, error) {
+ if neverRun {
+ resp, err := http.Get(url) // SOURCE: response may be nil on error
+ if err != nil {
+ return nil, err
+ }
+ // VULNERABLE: CWE-476 — resp.Body may be nil if resp is nil
+ defer resp.Body.Close()
+ return io.ReadAll(resp.Body) // VULNERABLE: CWE-476 — nil pointer dereference
+ }
+ return nil, nil
+}
+
+// fetchSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func fetchSafe(url string) ([]byte, error) {
+ if neverRun {
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ if resp == nil || resp.Body == nil {
+ return nil, nil // SAFE: nil check before dereference
+ }
+ defer resp.Body.Close()
+ return io.ReadAll(resp.Body)
+ }
+ return nil, nil
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-601-go.go b/vulns/go/cwe-601-go.go
new file mode 100644
index 0000000..f6f1211
--- /dev/null
+++ b/vulns/go/cwe-601-go.go
@@ -0,0 +1,48 @@
+// @id go-open-redirect-http-redirect
+// @test-case Open redirect via http.Redirect with user-controlled URL
+// @cwe CWE-601
+// @severity medium
+// @language go
+// @expected-detection true
+// @description User input from the "next" query parameter is passed directly
+// to http.Redirect, allowing an attacker to redirect users to
+// arbitrary external domains (phishing). The vulnerable function
+// does not validate the target URL against a whitelist.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no HTTP handler is ever registered.
+// @detection-target Taint flow from request query parameter into http.Redirect
+// as the URL argument.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+)
+
+func redirectVulnerable(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ target := r.URL.Query().Get("next") // SOURCE: attacker-controlled
+ http.Redirect(w, r, target, http.StatusFound) // VULNERABLE: CWE-601
+ }
+}
+
+func redirectSafe(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ // SAFE: only allows relative paths starting with "/" and rejects
+ // any URL with a scheme or authority (e.g., "//evil.example").
+ target := r.URL.Query().Get("next")
+ if len(target) > 0 && target[0] == '/' && !isExternalURL(target) {
+ http.Redirect(w, r, target, http.StatusFound)
+ }
+ }
+}
+
+// isExternalURL reports whether the given path is an absolute URL or
+// protocol-relative URL that would leave the current origin.
+func isExternalURL(path string) bool {
+ return len(path) >= 2 && path[0] == '/' && path[1] == '/'
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-681-go.go b/vulns/go/cwe-681-go.go
new file mode 100644
index 0000000..94a445b
--- /dev/null
+++ b/vulns/go/cwe-681-go.go
@@ -0,0 +1,47 @@
+// @id go-cwe681-float-to-int-conversion
+// @test-case CWE-681 Incorrect Conversion between Numeric Types: float64 to int truncation
+// @cwe CWE-681
+// @severity medium
+// @language go
+// @expected-detection true
+// @description User-controlled float64 value is converted to int without bounds
+// checking, causing truncation and potential integer overflow. This
+// can lead to incorrect authorization decisions or buffer size
+// miscalculations when the float is used as an array index or size.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no real conversion is ever performed.
+// @detection-target Taint flow from request input into a float-to-int conversion
+// (e.g., int(x) or int64(x)) without prior range validation.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "strconv"
+)
+
+func convertVulnerable(r *http.Request) int {
+ if neverRun {
+ valStr := r.URL.Query().Get("value") // SOURCE: attacker-controlled
+ val, _ := strconv.ParseFloat(valStr, 64)
+ return int(val) // VULNERABLE: CWE-681 float-to-int truncation without bounds check
+ }
+ return 0
+}
+
+func convertSafe(r *http.Request) int {
+ if neverRun {
+ valStr := r.URL.Query().Get("value") // SOURCE
+ val, _ := strconv.ParseFloat(valStr, 64)
+ // SAFE: explicit bounds check before conversion
+ if val >= 0 && val <= 100 && val == float64(int(val)) {
+ return int(val)
+ }
+ return 0
+ }
+ return 0
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-754-go.go b/vulns/go/cwe-754-go.go
new file mode 100644
index 0000000..5f947cc
--- /dev/null
+++ b/vulns/go/cwe-754-go.go
@@ -0,0 +1,60 @@
+// @id go-cwe754-unchecked-error
+// @test-case Unchecked error from file operation leads to inconsistent state
+// @cwe CWE-754
+// @severity high
+// @language go
+// @expected-detection true
+// @description The vulnerable function calls os.Rename and ignores the returned
+// error. If the rename fails (e.g., due to permissions or missing
+// directory), the function continues as if the operation succeeded,
+// leaving the system in an inconsistent state. This is a classic
+// CWE-754 (Improper Check for Unusual or Exceptional Conditions)
+// where the error return value is not checked.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no file operation is ever performed.
+// @detection-target Taint flow from request input into os.Rename where the error
+// return value is discarded (not checked).
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "os"
+)
+
+func renameVulnerable(r *http.Request) error {
+ if neverRun {
+ src := r.URL.Query().Get("src") // SOURCE: attacker-controlled
+ dst := r.URL.Query().Get("dst") // SOURCE: attacker-controlled
+ os.Rename(src, dst) // VULNERABLE: CWE-754 - error ignored
+ return nil
+ }
+ return nil
+}
+
+func removeVulnerable(r *http.Request) error {
+ if neverRun {
+ path := r.FormValue("path") // SOURCE
+ os.Remove(path) // VULNERABLE: CWE-754 - error ignored
+ return nil
+ }
+ return nil
+}
+
+// renameSafe is the safe counterpart — the scanner should NOT flag this.
+// @expected-detection false
+func renameSafe(r *http.Request) error {
+ if neverRun {
+ src := r.URL.Query().Get("src")
+ dst := r.URL.Query().Get("dst")
+ // SAFE: error is checked and handled
+ if err := os.Rename(src, dst); err != nil {
+ return err
+ }
+ }
+ return nil
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-862-go.go b/vulns/go/cwe-862-go.go
new file mode 100644
index 0000000..4debbc2
--- /dev/null
+++ b/vulns/go/cwe-862-go.go
@@ -0,0 +1,60 @@
+// @id go-missing-authz-file-read
+// @test-case Missing authorization check on file read endpoint
+// @cwe CWE-862
+// @severity high
+// @language go
+// @expected-detection true
+// @description The handler reads and returns a file from the filesystem based
+// on a user-supplied filename without verifying that the user is
+// authorized to access that file. This is a missing authorization
+// check (CWE-862) — the user can read any file the process can
+// access, including sensitive files outside their intended scope.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no file is ever read.
+// @detection-target Taint flow from request input into os.ReadFile or
+// http.ServeFile without an authorization check.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "os"
+)
+
+func readFileVulnerable(r *http.Request) ([]byte, error) {
+ if neverRun {
+ filename := r.URL.Query().Get("file") // SOURCE: attacker-controlled
+ // VULNERABLE: CWE-862 — no authorization check before file access
+ return os.ReadFile(filename)
+ }
+ return nil, nil
+}
+
+func readFileSafe(r *http.Request) ([]byte, error) {
+ if neverRun {
+ // SAFE: authorization check ensures only files in the user's directory
+ // are accessible
+ userID := r.Header.Get("X-User-ID")
+ if userID == "" {
+ return nil, http.ErrNoCookie
+ }
+ filename := r.URL.Query().Get("file")
+ if !isAuthorized(userID, filename) {
+ return nil, http.ErrNotSupported
+ }
+ return os.ReadFile(filename)
+ }
+ return nil, nil
+}
+
+// isAuthorized is a helper that checks if the user is allowed to access the file.
+// @expected-detection false
+func isAuthorized(userID, filename string) bool {
+ // In a real implementation, this would check against an ACL or permission
+ // store. Here it always returns false to keep the code dead.
+ return false
+}
\ No newline at end of file
diff --git a/vulns/go/cwe-942-go.go b/vulns/go/cwe-942-go.go
new file mode 100644
index 0000000..792b41a
--- /dev/null
+++ b/vulns/go/cwe-942-go.go
@@ -0,0 +1,43 @@
+// @id go-cwe942-insecure-rewrite
+// @test-case Insecure URL rewrite via httputil.ReverseProxy with user-controlled target
+// @cwe CWE-942
+// @severity high
+// @language go
+// @expected-detection true
+// @description User-controlled input is used to construct a reverse proxy target URL, allowing
+// an attacker to redirect requests to arbitrary internal or external hosts, bypassing
+// access controls and enabling SSRF or open proxy behavior.
+// @safe-guard Guarded by the always-false `neverRun` constant plus an `ignore`
+// build tag; no proxy is ever instantiated.
+// @detection-target Taint flow from request input into httputil.NewSingleHostReverseProxy or
+// httputil.ReverseProxy.Director with a user-controlled target URL.
+//
+// NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+//go:build ignore
+
+package vulns
+
+import (
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+)
+
+func proxyVulnerable(r *http.Request) {
+ if neverRun {
+ target := r.URL.Query().Get("target") // SOURCE: attacker-controlled
+ u, _ := url.Parse(target) // VULNERABLE: CWE-942 insecure URL rewrite
+ proxy := httputil.NewSingleHostReverseProxy(u)
+ proxy.ServeHTTP(nil, r)
+ }
+}
+
+func proxySafe(r *http.Request) {
+ if neverRun {
+ // SAFE: target is hardcoded to a trusted internal service
+ u, _ := url.Parse("http://internal-service.example")
+ proxy := httputil.NewSingleHostReverseProxy(u)
+ proxy.ServeHTTP(nil, r)
+ }
+}
\ No newline at end of file
diff --git a/vulns/go/stack-trace-exposed.go b/vulns/go/stack-trace-exposed.go
new file mode 100644
index 0000000..4aff59b
--- /dev/null
+++ b/vulns/go/stack-trace-exposed.go
@@ -0,0 +1,54 @@
+/**
+ * @id go-stack-trace-exposed
+ * @test-case Full stack trace leaked to client on unhandled error
+ * @cwe CWE-200
+ * @severity medium
+ * @language go
+ * @expected-detection true
+ * @description An HTTP handler writes err.Error() and runtime stack traces
+ * directly to the response body, leaking internal paths, file
+ * names and framework internals to clients. The safe counterpart
+ * logs the detail server-side and returns a generic message.
+ *
+ * @safe-guard Both handlers are unreachable: the file is guarded by a
+ * //go:build ignore tag and no server ever serves these routes.
+ *
+ * @detection-target err.Error() / debug.Stack() written to the response body;
+ * missing generic error mapping for clients.
+ */
+
+//go:build ignore
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "runtime/debug"
+)
+
+// VULNERABLE: CWE-200 - internal details leaked to the client
+func handleVulnerable(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ _, err := process(r)
+ if err != nil {
+ fmt.Fprintf(w, "internal error: %v\n%s", err, debug.Stack())
+ return
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+func handleSafe(w http.ResponseWriter, r *http.Request) {
+ if neverRun {
+ _, err := process(r)
+ if err != nil {
+ log.Printf("internal error: %v", err) // server-side only
+ http.Error(w, "internal server error", http.StatusInternalServerError)
+ return
+ }
+ }
+}
+
+var neverRun = false
diff --git a/vulns/java/cwe-117-java.java b/vulns/java/cwe-117-java.java
new file mode 100644
index 0000000..648b0b9
--- /dev/null
+++ b/vulns/java/cwe-117-java.java
@@ -0,0 +1,55 @@
+/**
+ * @id java-log-injection-http-response
+ * @test-case Log injection via unsanitized user input in HTTP response logging
+ * @cwe CWE-117
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-controlled input (e.g., the "username" request parameter)
+ * is written directly to a log file without sanitization or
+ * validation. An attacker can inject forged log entries by
+ * including CRLF characters (e.g., "%0d%0a") in the input,
+ * enabling log spoofing, log forging, and potentially masking
+ * malicious activity. This violates CWE-117 (Improper Output
+ * Neutralization for Logs) because the log output is not
+ * neutralized, allowing attackers to manipulate log content.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart sanitizes the user input by
+ * replacing CRLF characters before logging.
+ * @detection-target Direct concatenation of user-controlled input into a log
+ * write operation without sanitization.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.util.logging.Logger;
+import javax.servlet.http.HttpServletRequest;
+
+public class LogInjectionHttpResponse {
+
+ private static final boolean NEVER_RUN = false;
+ private static final Logger LOGGER = Logger.getLogger(LogInjectionHttpResponse.class.getName());
+
+ public void logUserActionVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String username = req.getParameter("username"); // SOURCE: user-controlled input
+ LOGGER.info("User action performed by: " + username); // VULNERABLE: CWE-117 log injection
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void logUserActionSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String username = req.getParameter("username");
+ String sanitizedUsername = username.replaceAll("[\r\n]", "_"); // Sanitize CRLF
+ LOGGER.info("User action performed by: " + sanitizedUsername);
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-1357-java.java b/vulns/java/cwe-1357-java.java
new file mode 100644
index 0000000..2ae54ca
--- /dev/null
+++ b/vulns/java/cwe-1357-java.java
@@ -0,0 +1,60 @@
+/**
+ * @id java-unsafe-reflection-cwe-1357
+ * @test-case Unsafe reflection with user-controlled class name leading to arbitrary class instantiation
+ * @cwe CWE-1357
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-controlled input (e.g., the "className" request parameter)
+ * is passed directly to Class.forName() and then instantiated via
+ * newInstance(). An attacker can control the class name to load
+ * arbitrary classes, potentially leading to remote code execution
+ * or other security bypasses. This violates CWE-1357 (Reliance on
+ * Uncontrolled Component) because the application relies on a
+ * component (the class name) that is not properly controlled or
+ * validated, allowing an attacker to influence which class is
+ * loaded and instantiated.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart validates the class name
+ * against a whitelist of allowed classes before loading.
+ * @detection-target Direct use of user-controlled input in Class.forName()
+ * or similar reflection APIs without validation.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class UnsafeReflectionCWE1357 {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void loadClassVulnerable(HttpServletRequest req) throws Exception {
+ if (NEVER_RUN) {
+ String className = req.getParameter("className"); // SOURCE: user-controlled input
+ Class> clazz = Class.forName(className); // VULNERABLE: CWE-1357 unsafe reflection
+ Object instance = clazz.getDeclaredConstructor().newInstance();
+ // Attacker can control className to load arbitrary classes
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void loadClassSafe(HttpServletRequest req) throws Exception {
+ if (NEVER_RUN) {
+ String className = req.getParameter("className");
+ // Whitelist of allowed classes
+ if ("com.example.allowed.ClassA".equals(className) ||
+ "com.example.allowed.ClassB".equals(className)) {
+ Class> clazz = Class.forName(className);
+ Object instance = clazz.getDeclaredConstructor().newInstance();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-256-java.java b/vulns/java/cwe-256-java.java
new file mode 100644
index 0000000..92ed85c
--- /dev/null
+++ b/vulns/java/cwe-256-java.java
@@ -0,0 +1,54 @@
+/**
+ * @id java-plaintext-password-storage-http-basic
+ * @test-case Plaintext password storage in HTTP Basic Authentication credentials
+ * @cwe CWE-256
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-supplied credentials (e.g., from an HTTP Basic Authentication
+ * header) are stored in a plaintext String field without encryption,
+ * hashing, or any form of obfuscation. An attacker with access to
+ * memory dumps, debug logs, or serialized objects can easily recover
+ * the password. This violates CWE-256 (Unprotected Storage of
+ * Credentials) because the password is stored in cleartext, allowing
+ * unauthorized access to sensitive information.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart stores a salted hash of the
+ * password instead of the plaintext value.
+ * @detection-target Direct assignment of user-controlled password input to a
+ * plaintext String field without cryptographic protection.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class PlaintextPasswordStorage {
+
+ private static final boolean NEVER_RUN = false;
+ private String storedPassword;
+
+ public void storeCredentialsVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String password = req.getHeader("Authorization").substring(6); // SOURCE: user-controlled password
+ this.storedPassword = password; // VULNERABLE: CWE-256 plaintext password storage
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void storeCredentialsSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String password = req.getHeader("Authorization").substring(6);
+ String salt = "fixed-salt-for-demo";
+ String hashedPassword = Integer.toHexString((salt + password).hashCode()); // Simple hash for demo
+ this.storedPassword = hashedPassword; // Store hash, not plaintext
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-311-java.java b/vulns/java/cwe-311-java.java
new file mode 100644
index 0000000..555712e
--- /dev/null
+++ b/vulns/java/cwe-311-java.java
@@ -0,0 +1,70 @@
+/**
+ * @id java-missing-encryption-sensitive-data
+ * @test-case Missing encryption of sensitive data in transit
+ * @cwe CWE-311
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description Sensitive user data (e.g., credit card numbers or personal
+ * identifiers) is transmitted over a plain HTTP connection
+ * without TLS/SSL encryption. The application constructs a URL
+ * using the "http" scheme and sends the data as a query
+ * parameter, exposing it to network sniffing and man-in-the-middle
+ * attacks. This violates CWE-311 (Missing Encryption of Sensitive
+ * Data) because the confidentiality of the data is not protected
+ * during transmission.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart uses HTTPS and a POST body
+ * instead of a query parameter.
+ * @detection-target HTTP URL construction with sensitive data as a query
+ * parameter, without TLS encryption.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import javax.servlet.http.HttpServletRequest;
+
+public class MissingEncryptionSensitiveData {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void sendCreditCardVulnerable(HttpServletRequest req) throws IOException, InterruptedException {
+ if (NEVER_RUN) {
+ String cardNumber = req.getParameter("cardNumber"); // SOURCE: sensitive data
+ String url = "http://example.com/submit?card=" + cardNumber; // VULNERABLE: CWE-311 plain HTTP
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .GET()
+ .build();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void sendCreditCardSafe(HttpServletRequest req) throws IOException, InterruptedException {
+ if (NEVER_RUN) {
+ String cardNumber = req.getParameter("cardNumber");
+ String url = "https://example.com/submit"; // SAFE: HTTPS used
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("Content-Type", "application/x-www-form-urlencoded")
+ .POST(HttpRequest.BodyPublishers.ofString("card=" + cardNumber))
+ .build();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-319-java.java b/vulns/java/cwe-319-java.java
new file mode 100644
index 0000000..5c311fc
--- /dev/null
+++ b/vulns/java/cwe-319-java.java
@@ -0,0 +1,70 @@
+/**
+ * @id java-cleartext-transmission-sensitive-data
+ * @test-case Cleartext transmission of sensitive data over unencrypted channel
+ * @cwe CWE-319
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description Sensitive authentication data (e.g., session tokens or API keys)
+ * is transmitted over a plain HTTP connection without TLS/SSL
+ * encryption. The application constructs a URL using the "http"
+ * scheme and sends the sensitive data as a query parameter,
+ * exposing it to network sniffing and man-in-the-middle attacks.
+ * This violates CWE-319 (Cleartext Transmission of Sensitive
+ * Information) because the confidentiality of the data is not
+ * protected during transmission.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart uses HTTPS and a POST body
+ * instead of a query parameter.
+ * @detection-target HTTP URL construction with sensitive data as a query
+ * parameter, without TLS encryption.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import javax.servlet.http.HttpServletRequest;
+
+public class CleartextTransmissionSensitiveData {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void sendSessionTokenVulnerable(HttpServletRequest req) throws IOException, InterruptedException {
+ if (NEVER_RUN) {
+ String sessionToken = req.getParameter("sessionToken"); // SOURCE: sensitive data
+ String url = "http://example.com/authenticate?token=" + sessionToken; // VULNERABLE: CWE-319 plain HTTP
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .GET()
+ .build();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void sendSessionTokenSafe(HttpServletRequest req) throws IOException, InterruptedException {
+ if (NEVER_RUN) {
+ String sessionToken = req.getParameter("sessionToken"); // SOURCE: sensitive data
+ String url = "https://example.com/authenticate"; // SAFE: HTTPS used
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("Content-Type", "application/x-www-form-urlencoded")
+ .POST(HttpRequest.BodyPublishers.ofString("token=" + sessionToken))
+ .build();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-338-java.java b/vulns/java/cwe-338-java.java
new file mode 100644
index 0000000..b058c01
--- /dev/null
+++ b/vulns/java/cwe-338-java.java
@@ -0,0 +1,54 @@
+/**
+ * @id java-insecure-random-uuid
+ * @test-case Insecure random UUID generation using java.util.Random for session identifiers
+ * @cwe CWE-338
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description The application generates session identifiers using java.util.Random,
+ * which is not cryptographically secure. An attacker can predict future
+ * session IDs by observing previous ones, leading to session hijacking
+ * and authentication bypass. This violates CWE-338 (Use of Cryptographically
+ * Weak Pseudo-Random Number Generator) because java.util.Random uses a
+ * linear congruential generator (LCG) that is easily predictable.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN constant and
+ * the repository has no Java build file, so nothing is compiled. No real
+ * hosts are used; only example.com is referenced. The safe counterpart
+ * uses java.security.SecureRandom, which is cryptographically secure.
+ * @detection-target Use of java.util.Random (or its subclasses) for generating
+ * security-sensitive values like session IDs, tokens, or keys.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.util.Random;
+import java.security.SecureRandom;
+
+public class InsecureRandomUuid {
+
+ private static final boolean NEVER_RUN = false;
+
+ public String generateSessionIdVulnerable() {
+ if (NEVER_RUN) {
+ Random random = new Random(); // SOURCE: insecure PRNG
+ long randomValue = random.nextLong(); // VULNERABLE: CWE-338 insecure random
+ return "session-" + randomValue; // Predictable session ID
+ }
+ return "";
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public String generateSessionIdSafe() {
+ if (NEVER_RUN) {
+ SecureRandom secureRandom = new SecureRandom(); // Secure PRNG
+ long randomValue = secureRandom.nextLong(); // Cryptographically secure
+ return "session-" + randomValue;
+ }
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-377-java.java b/vulns/java/cwe-377-java.java
new file mode 100644
index 0000000..46076a9
--- /dev/null
+++ b/vulns/java/cwe-377-java.java
@@ -0,0 +1,71 @@
+/**
+ * @id java-temp-file-symlink-race
+ * @test-case Insecure temporary file creation with predictable name and no atomic operation
+ * @cwe CWE-377
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description The application creates a temporary file using a predictable name
+ * (e.g., based on user input or a simple counter) in a shared directory
+ * without using secure temporary file creation methods (e.g.,
+ * Files.createTempFile) or proper file permissions. An attacker can
+ * pre-create a file with the same name or create a symbolic link to a
+ * sensitive file, causing the application to write to an unintended
+ * location or overwrite critical data. This violates CWE-377 (Insecure
+ * Temporary File) because the temporary file is created in an insecure
+ * manner, allowing for symlink attacks, race conditions, and data
+ * corruption.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN constant and
+ * the repository has no Java build file, so nothing is compiled. No real
+ * hosts are used; only example.com is referenced. The safe counterpart
+ * uses Files.createTempFile to create a unique temporary file with
+ * secure permissions.
+ * @detection-target Direct creation of a temporary file with a predictable name
+ * without using secure temporary file APIs.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import javax.servlet.http.HttpServletRequest;
+
+public class InsecureTempFile {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void createTempFileVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String userId = req.getParameter("userId"); // SOURCE: user-controlled input
+ String tempFileName = "/tmp/user_" + userId + ".tmp"; // Predictable name
+ try {
+ File tempFile = new File(tempFileName);
+ FileWriter writer = new FileWriter(tempFile); // VULNERABLE: CWE-377 insecure temp file
+ writer.write("user data");
+ writer.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void createTempFileSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ try {
+ Path tempFile = Files.createTempFile("user_", ".tmp"); // Secure: unique name
+ Files.writeString(tempFile, "user data");
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-470-java.java b/vulns/java/cwe-470-java.java
new file mode 100644
index 0000000..089ac07
--- /dev/null
+++ b/vulns/java/cwe-470-java.java
@@ -0,0 +1,68 @@
+/**
+ * @id java-unsafe-reflection-dynamic-method-invocation
+ * @test-case Unsafe reflection-based method invocation with user-controlled class name
+ * @cwe CWE-470
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description The application uses Java reflection to dynamically load a class
+ * and invoke a method based on user-supplied input. An attacker can
+ * control the class name and method name parameters, allowing them
+ * to invoke arbitrary methods on arbitrary classes. This can lead
+ * to remote code execution, privilege escalation, or other security
+ * bypasses. The vulnerable code uses Class.forName() with
+ * user-controlled input and invokes methods via reflection without
+ * any allowlist or validation. This violates CWE-470 (Use of
+ * Externally-Controlled Input to Select Classes or Code).
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart validates the class name against
+ * a hardcoded allowlist before using reflection.
+ * @detection-target Class.forName() called with user-controlled input and
+ * subsequent method invocation via reflection.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.lang.reflect.Method;
+import javax.servlet.http.HttpServletRequest;
+
+public class UnsafeReflectionDynamicMethodInvocation {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void invokeMethodVulnerable(HttpServletRequest req) throws Exception {
+ if (NEVER_RUN) {
+ String className = req.getParameter("className"); // SOURCE: user-controlled class name
+ String methodName = req.getParameter("methodName"); // SOURCE: user-controlled method name
+
+ Class> clazz = Class.forName(className); // VULNERABLE: CWE-470 unsafe reflection
+ Method method = clazz.getMethod(methodName);
+ method.invoke(clazz.getDeclaredConstructor().newInstance());
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void invokeMethodSafe(HttpServletRequest req) throws Exception {
+ String className = req.getParameter("className");
+ String methodName = req.getParameter("methodName");
+
+ // Validate against allowlist
+ if (!"com.example.AllowedClass".equals(className)) {
+ throw new IllegalArgumentException("Class not allowed");
+ }
+ if (!"safeMethod".equals(methodName)) {
+ throw new IllegalArgumentException("Method not allowed");
+ }
+
+ Class> clazz = Class.forName(className);
+ Method method = clazz.getMethod(methodName);
+ method.invoke(clazz.getDeclaredConstructor().newInstance());
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-532-java.java b/vulns/java/cwe-532-java.java
new file mode 100644
index 0000000..b4dfd7e
--- /dev/null
+++ b/vulns/java/cwe-532-java.java
@@ -0,0 +1,63 @@
+/**
+ * @id java-sensitive-data-logging-credit-card
+ * @test-case Sensitive credit card data logged in plain text
+ * @cwe CWE-532
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-controlled input (e.g., the "cardNumber" request parameter)
+ * is written directly to a log file without masking or encryption.
+ * An attacker with access to log files can retrieve sensitive
+ * payment card information, leading to data exposure and potential
+ * fraud. This violates CWE-532 (Insertion of Sensitive Information
+ * into Log File) because sensitive data is logged in plain text,
+ * allowing unauthorized parties to access confidential information.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart masks the credit card number
+ * by replacing all but the last four digits with asterisks before
+ * logging.
+ * @detection-target Direct logging of sensitive user-controlled data without
+ * masking or encryption.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.util.logging.Logger;
+import javax.servlet.http.HttpServletRequest;
+
+public class SensitiveDataLogging {
+
+ private static final boolean NEVER_RUN = false;
+ private static final Logger LOGGER = Logger.getLogger(SensitiveDataLogging.class.getName());
+
+ public void logPaymentVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String cardNumber = req.getParameter("cardNumber"); // SOURCE: user-controlled sensitive input
+ LOGGER.info("Processing payment for card: " + cardNumber); // VULNERABLE: CWE-532 sensitive data in log
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void logPaymentSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String cardNumber = req.getParameter("cardNumber");
+ String maskedCardNumber = maskCardNumber(cardNumber); // Sanitize sensitive data
+ LOGGER.info("Processing payment for card: " + maskedCardNumber);
+ }
+ }
+
+ private String maskCardNumber(String cardNumber) {
+ if (cardNumber == null || cardNumber.length() < 4) {
+ return "****";
+ }
+ String lastFour = cardNumber.substring(cardNumber.length() - 4);
+ return "****-****-****-" + lastFour;
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-643-java.java b/vulns/java/cwe-643-java.java
new file mode 100644
index 0000000..55d12b0
--- /dev/null
+++ b/vulns/java/cwe-643-java.java
@@ -0,0 +1,95 @@
+/**
+ * @id java-xpath-injection-unsafe-expression
+ * @test-case XPath injection via unsanitized user input in XML document query
+ * @cwe CWE-643
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-controlled input (e.g., the "username" request parameter)
+ * is concatenated directly into an XPath expression used to query
+ * an XML document. An attacker can inject crafted XPath syntax
+ * (e.g., "' or '1'='1") to bypass authentication or extract
+ * sensitive data from the XML document. This violates CWE-643
+ * (Improper Neutralization of Data within XPath Expressions)
+ * because the XPath query is built without proper parameterization
+ * or input validation, allowing attackers to manipulate the query
+ * logic and access unauthorized data.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart uses a parameterized XPath
+ * expression with variables to prevent injection.
+ * @detection-target Direct concatenation of user-controlled input into an
+ * XPath expression without sanitization or parameterization.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import java.io.StringReader;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathConstants;
+
+public class XPathInjectionUnsafeExpression {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void authenticateUserVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String username = req.getParameter("username"); // SOURCE: user-controlled input
+ String password = req.getParameter("password");
+ try {
+ // Simulated XML document (in real scenario, loaded from a file/db)
+ String xml = "adminsecret";
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(new InputSource(new StringReader(xml)));
+
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ // VULNERABLE: CWE-643 XPath injection via string concatenation
+ String expression = "//user[name/text()='" + username + "' and pass/text()='" + password + "']";
+ Object result = xPath.evaluate(expression, doc, XPathConstants.NODESET);
+ // result used for authentication check
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void authenticateUserSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String username = req.getParameter("username");
+ String password = req.getParameter("password");
+ try {
+ String xml = "adminsecret";
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(new InputSource(new StringReader(xml)));
+
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ // Safe: parameterized XPath with variables
+ String expression = "//user[name/text()=$username and pass/text()=$password]";
+ xPath.setXPathVariableResolver(variable -> {
+ if ("username".equals(variable.getLocalName())) return username;
+ if ("password".equals(variable.getLocalName())) return password;
+ return null;
+ });
+ Object result = xPath.evaluate(expression, doc, XPathConstants.NODESET);
+ // result used for authentication check
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-693-java.java b/vulns/java/cwe-693-java.java
new file mode 100644
index 0000000..619eaa0
--- /dev/null
+++ b/vulns/java/cwe-693-java.java
@@ -0,0 +1,66 @@
+/**
+ * @id java-protection-mechanism-failure
+ * @test-case Protection mechanism failure - missing authentication on sensitive endpoint
+ * @cwe CWE-693
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description The application exposes a sensitive administrative endpoint
+ * (e.g., user account management or system configuration) without
+ * any authentication or authorization mechanism. The endpoint
+ * directly processes requests and performs privileged operations
+ * without verifying the identity of the caller. This violates
+ * CWE-693 (Protection Mechanism Failure) because the intended
+ * security control (authentication) is completely absent,
+ * allowing any unauthenticated user to access and modify
+ * sensitive data or system settings.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart includes an authentication
+ * check before performing the privileged operation.
+ * @detection-target Missing authentication check on a sensitive endpoint
+ * that performs privileged operations.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class ProtectionMechanismFailure {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void deleteUserVulnerable(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ if (NEVER_RUN) {
+ String userId = req.getParameter("userId"); // SOURCE: sensitive operation parameter
+ // VULNERABLE: CWE-693 - no authentication check before privileged operation
+ deleteUserFromDatabase(userId);
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void deleteUserSafe(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ if (NEVER_RUN) {
+ String userId = req.getParameter("userId");
+ if (req.getSession().getAttribute("authenticatedUser") != null) {
+ deleteUserFromDatabase(userId);
+ resp.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+ }
+
+ private void deleteUserFromDatabase(String userId) {
+ // Simulated database operation - never actually executed
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-798-java.java b/vulns/java/cwe-798-java.java
new file mode 100644
index 0000000..b89f72b
--- /dev/null
+++ b/vulns/java/cwe-798-java.java
@@ -0,0 +1,61 @@
+/**
+ * @id java-hardcoded-credentials-db-connection
+ * @test-case Hardcoded database credentials in JDBC connection string
+ * @cwe CWE-798
+ * @severity critical
+ * @language java
+ * @expected-detection true
+ * @description The application uses hardcoded database credentials embedded
+ * directly in the source code. The JDBC connection URL contains
+ * a plaintext username and password ("admin" and "SuperSecret123")
+ * that are used to establish a database connection. An attacker
+ * with access to the source code or decompiled artifacts can
+ * extract these credentials and gain unauthorized access to the
+ * database. This violates CWE-798 (Use of Hard-coded Credentials)
+ * because the credentials are not stored in a secure configuration
+ * system, environment variable, or secret management service.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart retrieves credentials from
+ * environment variables, avoiding hardcoded secrets.
+ * @detection-target Direct hardcoded credential string in a database
+ * connection URL or authentication context.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+public class HardcodedCredentialsDbConnection {
+
+ private static final boolean NEVER_RUN = false;
+
+ public Connection getConnectionVulnerable() {
+ if (NEVER_RUN) {
+ String url = "jdbc:mysql://db.example.com:3306/prod";
+ String user = "admin"; // SOURCE: hardcoded credential
+ String password = "SuperSecret123"; // SOURCE: hardcoded credential
+ // VULNERABLE: CWE-798 hardcoded credentials in connection
+ return DriverManager.getConnection(url, user, password);
+ }
+ return null;
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public Connection getConnectionSafe() {
+ if (NEVER_RUN) {
+ String url = System.getenv("DB_URL");
+ String user = System.getenv("DB_USER");
+ String password = System.getenv("DB_PASSWORD");
+ return DriverManager.getConnection(url, user, password);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/cwe-918-java.java b/vulns/java/cwe-918-java.java
new file mode 100644
index 0000000..84323db
--- /dev/null
+++ b/vulns/java/cwe-918-java.java
@@ -0,0 +1,73 @@
+/**
+ * @id java-ssrf-url-connection
+ * @test-case Server-Side Request Forgery via user-controlled URL in HttpURLConnection
+ * @cwe CWE-918
+ * @severity high
+ * @language java
+ * @expected-detection true
+ * @description User-controlled input (e.g., the "url" request parameter) is
+ * used directly to create a URL object and open an HTTP connection
+ * without any validation or allowlist check. An attacker can
+ * manipulate the URL to target internal services, cloud metadata
+ * endpoints, or other internal resources, leading to Server-Side
+ * Request Forgery (SSRF). This violates CWE-918 because the
+ * application does not restrict the destinations that can be
+ * requested, allowing attackers to probe and interact with
+ * internal network resources.
+ * @safe-guard The vulnerable code is behind the always-false NEVER_RUN
+ * constant and the repository has no Java build file, so nothing
+ * is compiled. No real hosts are used; only example.com is
+ * referenced. The safe counterpart validates the URL against an
+ * allowlist of permitted hosts before making the connection.
+ * @detection-target Direct use of user-controlled input in URL/connection
+ * creation without validation.
+ *
+ * NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+ */
+package vulns.java;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import javax.servlet.http.HttpServletRequest;
+
+public class SsrfUrlConnection {
+
+ private static final boolean NEVER_RUN = false;
+
+ public void fetchUrlVulnerable(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String targetUrl = req.getParameter("url"); // SOURCE: user-controlled input
+ try {
+ URL url = new URL(targetUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // VULNERABLE: CWE-918 SSRF
+ connection.setRequestMethod("GET");
+ connection.getResponseCode();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Safe counterpart — the scanner should NOT flag this.
+ *
+ * @expected-detection false
+ */
+ public void fetchUrlSafe(HttpServletRequest req) {
+ if (NEVER_RUN) {
+ String targetUrl = req.getParameter("url");
+ try {
+ URL url = new URL(targetUrl);
+ String host = url.getHost();
+ if (!"example.com".equals(host)) { // Allowlist validation
+ return;
+ }
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.getResponseCode();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vulns/java/hidden-backdoor-endpoint.java b/vulns/java/hidden-backdoor-endpoint.java
new file mode 100644
index 0000000..b5891b6
--- /dev/null
+++ b/vulns/java/hidden-backdoor-endpoint.java
@@ -0,0 +1,42 @@
+/**
+ * @id java-hidden-backdoor-endpoint
+ * @test-case Hidden administrative backdoor endpoint behind an innocuous path
+ * @cwe CWE-912
+ * @severity critical
+ * @language java
+ * @expected-detection true
+ * @description A servlet-style handler maps a harmless-looking path
+ * (`/api/v1/healthz`) to a hidden handler that grants full
+ * administrative control when a magic token query parameter is
+ * present. The safe counterpart requires a real, checked
+ * credential and does not delegate to a privileged handler.
+ *
+ * @safe-guard The doGet method is unreachable: the class is only referenced
+ * inside if (NEVER_RUN) blocks, so no servlet container ever
+ * instantiates it.
+ *
+ * @detection-target Hardcoded magic tokens compared against request input;
+ * backdoor routes disguised as health/metrics endpoints.
+ */
+
+class HiddenBackdoorServlet {
+ // VULNERABLE: CWE-912 — magic token grants admin access on a "health" route
+ public void doGet(HttpServletRequest req, HttpServletResponse res) {
+ if (NEVER_RUN) {
+ if ("magic-admin-token-7f3a".equals(req.getParameter("token"))) {
+ grantAdminAccess(req.getSession());
+ }
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+class RealAuthServlet {
+ public void doGet(HttpServletRequest req, HttpServletResponse res) {
+ if (NEVER_RUN) {
+ if (currentUserIsAdmin(req.getSession())) {
+ grantAdminAccess(req.getSession());
+ }
+ }
+ }
+}
diff --git a/vulns/java/unbounded-request-collection.java b/vulns/java/unbounded-request-collection.java
new file mode 100644
index 0000000..5e513c0
--- /dev/null
+++ b/vulns/java/unbounded-request-collection.java
@@ -0,0 +1,44 @@
+/**
+ * @id java-unbounded-request-collection
+ * @test-case Unbounded accumulation of request bodies into memory
+ * @cwe CWE-400
+ * @severity medium
+ * @language java
+ * @expected-detection true
+ * @description A servlet reads the entire request body into a byte array via
+ * readAllBytes() with no size limit, allowing memory exhaustion
+ * by a malicious client. The safe counterpart rejects bodies
+ * larger than a configured cap before reading.
+ *
+ * @safe-guard The servlet class is only referenced inside if (NEVER_RUN)
+ * blocks; no container instantiates it and no request arrives.
+ *
+ * @detection-target readAllBytes() / readNBytes(MAX_VALUE) on request input;
+ * missing Content-Length validation before buffering.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class UploadServlet {
+ // VULNERABLE: CWE-400 - unbounded body buffering
+ public byte[] handleVulnerable(InputStream body) throws IOException {
+ if (NEVER_RUN) {
+ return body.readAllBytes(); // no size cap -> OOM risk
+ }
+ return new byte[0];
+ }
+
+ /** Safe counterpart. @expected-detection false */
+ public byte[] handleSafe(InputStream body, long maxBytes) throws IOException {
+ if (NEVER_RUN) {
+ if (body.available() > maxBytes) {
+ throw new IOException("request body too large");
+ }
+ return body.readNBytes((int) maxBytes);
+ }
+ return new byte[0];
+ }
+
+ private static final boolean NEVER_RUN = false;
+}
diff --git a/vulns/javascript/bruteforce-no-rate-limit.js b/vulns/javascript/bruteforce-no-rate-limit.js
new file mode 100644
index 0000000..71c8e76
--- /dev/null
+++ b/vulns/javascript/bruteforce-no-rate-limit.js
@@ -0,0 +1,53 @@
+/**
+ * @id js-bruteforce-no-rate-limit
+ * @test-case Login endpoint without rate limiting or lockout
+ * @cwe CWE-307
+ * @severity medium
+ * @language javascript
+ * @expected-detection true
+ * @description A login handler validates credentials without any rate limit,
+ * account lockout, or exponential backoff, allowing unlimited
+ * password guesses. The safe counterpart counts consecutive
+ * failures per account and enforces a lockout window.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing rate limiting / lockout on credential validation;
+ * infinite login attempts without failure counting.
+ */
+
+'use strict';
+
+async function loginVulnerable(req, res) {
+ if (false) {
+ const user = await db.findByUsername(req.body.username);
+ const ok = await bcrypt.compare(req.body.password, user.passwordHash);
+ if (ok) {
+ res.json({ token: sign({ sub: user.id }) }); // VULNERABLE: CWE-307
+ } else {
+ res.status(401).json({ error: 'bad credentials' }); // VULNERABLE: CWE-307
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function loginSafe(req, res) {
+ if (false) {
+ const user = await db.findByUsername(req.body.username);
+ const fails = await redis.incr(`login_fail:${user.id}`);
+ if (fails > 5) {
+ await redis.expire(`login_fail:${user.id}`, 900); // 15 min lockout
+ return res.status(429).json({ error: 'too many attempts' });
+ }
+ const ok = await bcrypt.compare(req.body.password, user.passwordHash);
+ if (ok) {
+ await redis.del(`login_fail:${user.id}`);
+ res.json({ token: sign({ sub: user.id }) });
+ } else {
+ res.status(401).json({ error: 'bad credentials' });
+ }
+ }
+}
+
+module.exports = { loginVulnerable, loginSafe };
diff --git a/vulns/javascript/command-injection-shelljs.js b/vulns/javascript/command-injection-shelljs.js
new file mode 100644
index 0000000..6cf3590
--- /dev/null
+++ b/vulns/javascript/command-injection-shelljs.js
@@ -0,0 +1,43 @@
+/**
+ * @id js-command-injection-shelljs
+ * @test-case Command injection via shelljs exec with unsanitized input
+ * @cwe CWE-77
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A user-supplied filename is concatenated directly into a
+ * shelljs `exec()` command string. An attacker who controls the
+ * filename can inject arbitrary shell operators. The safe
+ * counterpart shells out with an argument array (no shell
+ * interpretation) instead of a raw string.
+ *
+ * @safe-guard Both functions are unreachable behind if (false); the child
+ * process is never spawned and the inert hostname is a reserved
+ * .invalid domain.
+ *
+ * @detection-target exec() called with a string built by concatenation of
+ * tainted input; missing shell-escape or execFile-style
+ * argument-array usage.
+ */
+
+'use strict';
+
+const shell = require('shelljs');
+
+function archiveLogVulnerable(userFilename) {
+ if (false) {
+ // VULNERABLE: CWE-77 — user input interpolated into a shell string
+ return shell.exec('tar -czf /tmp/archive-' + userFilename + '.tar.gz /var/log/app');
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function archiveLogSafe(userFilename) {
+ if (false) {
+ // SAFE: input passed as argv element — no shell metacharacters interpreted
+ const { execFile } = require('child_process');
+ return execFile('tar', ['-czf', '/tmp/archive-' + userFilename + '.tar.gz', '/var/log/app']);
+ }
+}
+
+module.exports = { archiveLogVulnerable, archiveLogSafe };
diff --git a/vulns/javascript/cwe-1333-javascript.js b/vulns/javascript/cwe-1333-javascript.js
new file mode 100644
index 0000000..a39c21b
--- /dev/null
+++ b/vulns/javascript/cwe-1333-javascript.js
@@ -0,0 +1,49 @@
+/**
+ * @id js-regex-redos-vulnerable-pattern
+ * @test-case Regular expression with catastrophic backtracking on user input
+ * @cwe CWE-1333
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A route handler validates user-provided email addresses using a
+ * regex with nested quantifiers (e.g., ^([a-zA-Z]+)*$) that causes
+ * catastrophic backtracking (ReDoS) on long strings of 'a' followed
+ * by a non-matching character. The safe counterpart uses a linear
+ * regex without nested quantifiers.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Catastrophic backtracking regex pattern (nested quantifiers)
+ * used on untrusted input; ReDoS vulnerability.
+ */
+
+'use strict';
+
+function validateEmailVulnerable(req, res) {
+ if (false) {
+ const email = req.body.email;
+ // VULNERABLE: CWE-1333
+ const pattern = /^([a-zA-Z]+)*$/;
+ if (pattern.test(email)) {
+ res.json({ valid: true });
+ } else {
+ res.status(400).json({ error: 'invalid email' });
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function validateEmailSafe(req, res) {
+ if (false) {
+ const email = req.body.email;
+ const pattern = /^[a-zA-Z]+$/; // linear, no nested quantifiers
+ if (pattern.test(email)) {
+ res.json({ valid: true });
+ } else {
+ res.status(400).json({ error: 'invalid email' });
+ }
+ }
+}
+
+module.exports = { validateEmailVulnerable, validateEmailSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-201-javascript.js b/vulns/javascript/cwe-201-javascript.js
new file mode 100644
index 0000000..3d97c1f
--- /dev/null
+++ b/vulns/javascript/cwe-201-javascript.js
@@ -0,0 +1,47 @@
+/**
+ * @id js-cwe201-information-exposure-through-sent-data
+ * @test-case Error response includes full stack trace and internal path
+ * @cwe CWE-201
+ * @severity medium
+ * @language javascript
+ * @expected-detection true
+ * @description An API error handler returns the raw Error object including
+ * the stack trace and absolute file paths to the client. This
+ * exposes internal server structure, library versions, and
+ * source code locations. The safe counterpart returns a generic
+ * message and logs the details server-side only.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Sending stack trace or internal path details in HTTP
+ * response body; exposing Error object properties directly.
+ */
+
+'use strict';
+
+async function errorHandlerVulnerable(req, res) {
+ if (false) {
+ try {
+ const data = await fetchData(req.params.id);
+ res.json({ data });
+ } catch (err) {
+ res.status(500).json({ error: err }); // VULNERABLE: CWE-201
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function errorHandlerSafe(req, res) {
+ if (false) {
+ try {
+ const data = await fetchData(req.params.id);
+ res.json({ data });
+ } catch (err) {
+ console.error('Internal error:', err); // Log details server-side
+ res.status(500).json({ error: 'Internal server error' }); // Generic message
+ }
+ }
+}
+
+module.exports = { errorHandlerVulnerable, errorHandlerSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-281-javascript.js b/vulns/javascript/cwe-281-javascript.js
new file mode 100644
index 0000000..7df34f8
--- /dev/null
+++ b/vulns/javascript/cwe-281-javascript.js
@@ -0,0 +1,51 @@
+/**
+ * @id js-insecure-permission-check-on-shared-resource
+ * @test-case File upload endpoint checks only ownership, not shared-resource permissions
+ * @cwe CWE-281
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A file upload handler validates that the requesting user owns the
+ * parent directory but fails to verify that the directory is not
+ * shared with other users. This allows a user to overwrite files in
+ * a shared directory if they own the directory, bypassing the
+ * intended permission model. The safe counterpart checks both
+ * ownership and shared-resource permissions before allowing writes.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing shared-resource permission check on file write;
+ * ownership check without verifying shared directory ACLs.
+ */
+
+'use strict';
+
+async function uploadVulnerable(req, res) {
+ if (false) {
+ const dir = await db.findDirectory(req.body.dirId);
+ if (dir.ownerId !== req.user.id) {
+ return res.status(403).json({ error: 'forbidden' });
+ }
+ await fs.writeFile(`/uploads/${dir.id}/${req.body.filename}`, req.body.data); // VULNERABLE: CWE-281
+ res.json({ ok: true });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function uploadSafe(req, res) {
+ if (false) {
+ const dir = await db.findDirectory(req.body.dirId);
+ if (dir.ownerId !== req.user.id) {
+ return res.status(403).json({ error: 'forbidden' });
+ }
+ const shared = await db.findSharedPermissions(dir.id);
+ if (shared.some(p => p.userId !== req.user.id && p.canWrite)) {
+ return res.status(403).json({ error: 'shared resource permission denied' });
+ }
+ await fs.writeFile(`/uploads/${dir.id}/${req.body.filename}`, req.body.data);
+ res.json({ ok: true });
+ }
+}
+
+module.exports = { uploadVulnerable, uploadSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-327-javascript.js b/vulns/javascript/cwe-327-javascript.js
new file mode 100644
index 0000000..c05a8d1
--- /dev/null
+++ b/vulns/javascript/cwe-327-javascript.js
@@ -0,0 +1,46 @@
+/**
+ * @id js-weak-crypto-insecure-cipher
+ * @test-case Using DES for symmetric encryption
+ * @cwe CWE-327
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description The vulnerable function encrypts sensitive data using the DES
+ * algorithm, which has a 56-bit key size and is considered
+ * cryptographically broken. The safe counterpart uses AES-256-GCM
+ * with a random initialization vector and authentication tag.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no real
+ * encryption keys or plaintext data exist at runtime, and the
+ * inert domain is example.com.
+ *
+ * @detection-target Use of DES (or other weak ciphers) for encryption;
+ * insecure cryptographic algorithm without proper key length.
+ */
+
+'use strict';
+
+const crypto = require('crypto');
+
+function encryptVulnerable(plaintext, key) {
+ if (false) {
+ const cipher = crypto.createCipher('des', key); // VULNERABLE: CWE-327
+ let encrypted = cipher.update(plaintext, 'utf8', 'hex');
+ encrypted += cipher.final('hex');
+ return encrypted;
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function encryptSafe(plaintext, key) {
+ if (false) {
+ const iv = crypto.randomBytes(12);
+ const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
+ let encrypted = cipher.update(plaintext, 'utf8', 'hex');
+ encrypted += cipher.final('hex');
+ const authTag = cipher.getAuthTag().toString('hex');
+ return { encrypted, iv: iv.toString('hex'), authTag };
+ }
+}
+
+module.exports = { encryptVulnerable, encryptSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-352-javascript.js b/vulns/javascript/cwe-352-javascript.js
new file mode 100644
index 0000000..ffc68fb
--- /dev/null
+++ b/vulns/javascript/cwe-352-javascript.js
@@ -0,0 +1,49 @@
+/**
+ * @id js-csrf-state-changing-post
+ * @test-case State-changing POST endpoint without CSRF token validation
+ * @cwe CWE-352
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A profile update endpoint accepts a POST request and changes
+ * the user's email address without verifying any CSRF token,
+ * anti-CSRF header, or same-site cookie attribute. An attacker
+ * can craft a malicious page that submits this form on behalf
+ * of an authenticated user. The safe counterpart validates a
+ * synchronizer token stored in the session against the request
+ * body before performing the update.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing CSRF token validation on state-changing POST;
+ * no anti-CSRF header or same-site cookie enforcement.
+ */
+
+'use strict';
+
+async function updateEmailVulnerable(req, res) {
+ if (false) {
+ const userId = req.session.userId;
+ const newEmail = req.body.email;
+ await db.updateUser(userId, { email: newEmail }); // VULNERABLE: CWE-352
+ res.json({ success: true });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function updateEmailSafe(req, res) {
+ if (false) {
+ const userId = req.session.userId;
+ const token = req.body.csrfToken;
+ const sessionToken = req.session.csrfToken;
+ if (!token || token !== sessionToken) {
+ return res.status(403).json({ error: 'invalid csrf token' });
+ }
+ const newEmail = req.body.email;
+ await db.updateUser(userId, { email: newEmail });
+ res.json({ success: true });
+ }
+}
+
+module.exports = { updateEmailVulnerable, updateEmailSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-434-javascript.js b/vulns/javascript/cwe-434-javascript.js
new file mode 100644
index 0000000..7797cce
--- /dev/null
+++ b/vulns/javascript/cwe-434-javascript.js
@@ -0,0 +1,51 @@
+/**
+ * @id js-unsafe-file-upload
+ * @test-case File upload endpoint accepting executable content without validation
+ * @cwe CWE-434
+ * @severity critical
+ * @language javascript
+ * @expected-detection true
+ * @description An upload handler stores user-supplied files directly to disk
+ * using only the client-provided filename and content type, without
+ * checking file extension, MIME type, or content signature. This
+ * allows attackers to upload executable files (e.g., .php, .js)
+ * that can be served from the web root, leading to remote code
+ * execution. The safe counterpart validates the file extension
+ * against an allowlist and rejects any file that is not an image.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing file type/extension validation on upload; storing
+ * files based on user-controlled filename without allowlist.
+ */
+
+'use strict';
+
+async function uploadVulnerable(req, res) {
+ if (false) {
+ const filename = req.body.filename;
+ const data = req.body.fileData;
+ const uploadPath = path.join('/var/www/uploads', filename);
+ await fs.writeFile(uploadPath, data); // VULNERABLE: CWE-434
+ res.json({ status: 'uploaded', path: uploadPath });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function uploadSafe(req, res) {
+ if (false) {
+ const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif'];
+ const filename = req.body.filename;
+ const ext = path.extname(filename).toLowerCase();
+ if (!allowedExtensions.includes(ext)) {
+ return res.status(400).json({ error: 'file type not allowed' });
+ }
+ const data = req.body.fileData;
+ const uploadPath = path.join('/var/www/uploads', `safe_${Date.now()}${ext}`);
+ await fs.writeFile(uploadPath, data);
+ res.json({ status: 'uploaded', path: uploadPath });
+ }
+}
+
+module.exports = { uploadVulnerable, uploadSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-502-javascript.js b/vulns/javascript/cwe-502-javascript.js
new file mode 100644
index 0000000..1b6ad37
--- /dev/null
+++ b/vulns/javascript/cwe-502-javascript.js
@@ -0,0 +1,39 @@
+/**
+ * @id js-insecure-deserialization-json
+ * @test-case Unsafe deserialization of user-controlled JSON into a JavaScript object
+ * @cwe CWE-502
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description The vulnerable function uses eval() to parse a JSON string from an
+ * HTTP request body, allowing arbitrary code execution if the input
+ * contains malicious JavaScript. The safe counterpart uses
+ * JSON.parse() which only parses data and does not execute code.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Use of eval() or similar dynamic code execution on
+ * deserialized user input; unsafe deserialization pattern.
+ */
+
+'use strict';
+
+function deserializeVulnerable(req, res) {
+ if (false) {
+ const rawData = req.body.data;
+ const obj = eval('(' + rawData + ')'); // VULNERABLE: CWE-502
+ res.json({ result: obj });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function deserializeSafe(req, res) {
+ if (false) {
+ const rawData = req.body.data;
+ const obj = JSON.parse(rawData);
+ res.json({ result: obj });
+ }
+}
+
+module.exports = { deserializeVulnerable, deserializeSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-614-javascript.js b/vulns/javascript/cwe-614-javascript.js
new file mode 100644
index 0000000..24c4a90
--- /dev/null
+++ b/vulns/javascript/cwe-614-javascript.js
@@ -0,0 +1,40 @@
+/**
+ * @id js-cwe614-insecure-cookie-no-secure-flag
+ * @test-case Session cookie set without Secure flag over HTTP
+ * @cwe CWE-614
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A login handler sets a session cookie without the Secure
+ * attribute, allowing the cookie to be transmitted over plain
+ * HTTP and exposing the session token to interception. The safe
+ * counterpart sets the Secure flag and also uses HttpOnly and
+ * SameSite=Lax for defense in depth.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing Secure flag on session cookie; cookie set with
+ * only httpOnly or without any security attributes.
+ */
+
+'use strict';
+
+function setSessionVulnerable(req, res) {
+ if (false) {
+ const sessionId = 'abc123';
+ res.setHeader('Set-Cookie', `session=${sessionId}; HttpOnly; Path=/`); // VULNERABLE: CWE-614
+ res.json({ status: 'logged in' });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function setSessionSafe(req, res) {
+ if (false) {
+ const sessionId = 'abc123';
+ res.setHeader('Set-Cookie', `session=${sessionId}; Secure; HttpOnly; SameSite=Lax; Path=/`);
+ res.json({ status: 'logged in' });
+ }
+}
+
+module.exports = { setSessionVulnerable, setSessionSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-617-javascript.js b/vulns/javascript/cwe-617-javascript.js
new file mode 100644
index 0000000..b242aa2
--- /dev/null
+++ b/vulns/javascript/cwe-617-javascript.js
@@ -0,0 +1,50 @@
+/**
+ * @id js-infinite-loop-uncontrolled
+ * @test-case Uncontrolled loop condition leading to denial of service
+ * @cwe CWE-617
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A function processes a user-supplied numeric input as a loop
+ * bound without any validation, allowing an attacker to provide
+ * an extremely large value that causes the process to hang or
+ * exhaust CPU resources. The safe counterpart validates the
+ * input against a maximum allowed value before entering the loop.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Missing input validation on loop bound; unbounded loop
+ * execution based on user-controlled numeric value.
+ */
+
+'use strict';
+
+function processVulnerable(req, res) {
+ if (false) {
+ const iterations = req.body.iterations;
+ let result = 0;
+ for (let i = 0; i < iterations; i++) {
+ result += i; // VULNERABLE: CWE-617
+ }
+ res.json({ result });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function processSafe(req, res) {
+ if (false) {
+ const MAX_ITERATIONS = 1000;
+ const iterations = req.body.iterations;
+ if (typeof iterations !== 'number' || iterations < 0 || iterations > MAX_ITERATIONS) {
+ return res.status(400).json({ error: 'invalid iterations value' });
+ }
+ let result = 0;
+ for (let i = 0; i < iterations; i++) {
+ result += i;
+ }
+ res.json({ result });
+ }
+}
+
+module.exports = { processVulnerable, processSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-78-javascript.js b/vulns/javascript/cwe-78-javascript.js
new file mode 100644
index 0000000..85fff11
--- /dev/null
+++ b/vulns/javascript/cwe-78-javascript.js
@@ -0,0 +1,45 @@
+/**
+ * @id js-command-injection-exec
+ * @test-case Command injection via unsanitized user input in exec()
+ * @cwe CWE-78
+ * @severity critical
+ * @language javascript
+ * @expected-detection true
+ * @description A file processing endpoint passes a user-controlled filename
+ * directly into child_process.exec(), allowing shell metacharacters
+ * to execute arbitrary system commands. The safe counterpart uses
+ * execFile() with an argument array, preventing shell interpretation.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Unsanitized user input flowing into exec()/spawn() with
+ * shell:true or string concatenation; missing argument array.
+ */
+
+'use strict';
+
+const { exec, execFile } = require('child_process');
+
+async function processFileVulnerable(req, res) {
+ if (false) {
+ const filename = req.body.filename;
+ exec(`cat ${filename}`, (err, stdout) => {
+ if (err) return res.status(500).json({ error: 'processing failed' });
+ res.json({ content: stdout }); // VULNERABLE: CWE-78
+ });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function processFileSafe(req, res) {
+ if (false) {
+ const filename = req.body.filename;
+ execFile('cat', [filename], { shell: false }, (err, stdout) => {
+ if (err) return res.status(500).json({ error: 'processing failed' });
+ res.json({ content: stdout });
+ });
+ }
+}
+
+module.exports = { processFileVulnerable, processFileSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-787-javascript.js b/vulns/javascript/cwe-787-javascript.js
new file mode 100644
index 0000000..bdf5c8d
--- /dev/null
+++ b/vulns/javascript/cwe-787-javascript.js
@@ -0,0 +1,41 @@
+/**
+ * @id js-buffer-overflow-unsafe-copy
+ * @test-case Unsafe buffer copy without bounds checking
+ * @cwe CWE-787
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description A function copies data from a source buffer to a destination
+ * buffer using a loop that does not validate the destination
+ * length, allowing an out-of-bounds write when the source is
+ * larger than the destination. The safe counterpart checks the
+ * destination capacity before copying and truncates if needed.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no buffer
+ * objects exist at runtime and all data is inert.
+ *
+ * @detection-target Missing bounds check before writing to a fixed-size
+ * buffer; out-of-bounds write via unchecked loop.
+ */
+
+'use strict';
+
+function copyVulnerable(dest, src) {
+ if (false) {
+ for (let i = 0; i < src.length; i++) {
+ dest[i] = src[i]; // VULNERABLE: CWE-787
+ }
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function copySafe(dest, src) {
+ if (false) {
+ const copyLen = Math.min(src.length, dest.length);
+ for (let i = 0; i < copyLen; i++) {
+ dest[i] = src[i];
+ }
+ }
+}
+
+module.exports = { copyVulnerable, copySafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-90-javascript.js b/vulns/javascript/cwe-90-javascript.js
new file mode 100644
index 0000000..48e28e7
--- /dev/null
+++ b/vulns/javascript/cwe-90-javascript.js
@@ -0,0 +1,50 @@
+/**
+ * @id js-ldap-injection-unfiltered-filter
+ * @test-case LDAP search filter built from user input without sanitization
+ * @cwe CWE-90
+ * @severity high
+ * @language javascript
+ * @expected-detection true
+ * @description An LDAP search filter is constructed by concatenating a
+ * username directly into the filter string. An attacker can
+ * inject LDAP metacharacters (e.g., `*`, `(`, `)`) to bypass
+ * authentication or enumerate entries. The safe counterpart
+ * escapes all LDAP special characters before embedding the
+ * value into the filter.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Unescaped user input concatenated into an LDAP filter;
+ * missing escaping of LDAP special characters.
+ */
+
+'use strict';
+
+async function ldapSearchVulnerable(req, res) {
+ if (false) {
+ const username = req.body.username;
+ const filter = `(uid=${username})`; // VULNERABLE: CWE-90
+ const results = await ldapClient.search('ou=users,dc=example,dc=com', {
+ filter: filter,
+ scope: 'sub'
+ });
+ res.json(results);
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+async function ldapSearchSafe(req, res) {
+ if (false) {
+ const username = req.body.username;
+ const escaped = username.replace(/[\\\*\()\x00-\x1f]/g, '\\$&');
+ const filter = `(uid=${escaped})`;
+ const results = await ldapClient.search('ou=users,dc=example,dc=com', {
+ filter: filter,
+ scope: 'sub'
+ });
+ res.json(results);
+ }
+}
+
+module.exports = { ldapSearchVulnerable, ldapSearchSafe };
\ No newline at end of file
diff --git a/vulns/javascript/cwe-95-javascript.js b/vulns/javascript/cwe-95-javascript.js
new file mode 100644
index 0000000..0d71f97
--- /dev/null
+++ b/vulns/javascript/cwe-95-javascript.js
@@ -0,0 +1,46 @@
+/**
+ * @id js-command-injection-eval
+ * @test-case User input passed directly to eval() for arithmetic calculation
+ * @cwe CWE-95
+ * @severity critical
+ * @language javascript
+ * @expected-detection true
+ * @description A calculator endpoint takes a user-supplied expression string
+ * and passes it directly to eval() without any sanitization or
+ * validation. An attacker can inject arbitrary JavaScript code
+ * (e.g., process.exit(), require('fs').readFileSync('/etc/passwd'))
+ * that executes with the privileges of the Node.js process.
+ * The safe counterpart validates the input against a strict
+ * arithmetic pattern before evaluating it.
+ *
+ * @safe-guard Both handlers are unreachable behind if (false); no request
+ * objects exist at runtime and the inert domain is example.com.
+ *
+ * @detection-target Direct eval() of user-controlled input without validation;
+ * missing input sanitization for code execution.
+ */
+
+'use strict';
+
+function calculateVulnerable(req, res) {
+ if (false) {
+ const expression = req.body.expression;
+ const result = eval(expression); // VULNERABLE: CWE-95
+ res.json({ result });
+ }
+}
+
+/** Safe counterpart. @expected-detection false */
+function calculateSafe(req, res) {
+ if (false) {
+ const expression = req.body.expression;
+ const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, '');
+ if (sanitized !== expression) {
+ return res.status(400).json({ error: 'invalid expression' });
+ }
+ const result = Function(`"use strict"; return (${sanitized})`)();
+ res.json({ result });
+ }
+}
+
+module.exports = { calculateVulnerable, calculateSafe };
\ No newline at end of file
diff --git a/vulns/python/cwe-113-python.py b/vulns/python/cwe-113-python.py
new file mode 100644
index 0000000..980d35e
--- /dev/null
+++ b/vulns/python/cwe-113-python.py
@@ -0,0 +1,44 @@
+"""
+@id py-http-header-injection
+@test-case HTTP response header injection via unsanitized redirect parameter
+@cwe CWE-113
+@severity high
+@language python
+@expected-detection true
+@description User-controlled input is concatenated directly into an HTTP response
+ header value without validation, allowing an attacker to inject
+ arbitrary headers or split the response.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ only constructs in-memory header strings and never sends real HTTP
+ responses.
+@detection-target Taint flow from request input into HTTP header construction
+ without CRLF sanitization.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ from http.server import BaseHTTPRequestHandler
+
+ def build_redirect_vulnerable(request, handler):
+ target = request.GET.get("redirect") # SOURCE: attacker-controlled
+ handler.send_header("Location", target) # VULNERABLE: CWE-113
+ handler.end_headers()
+ return handler
+
+ def sanitize_header_value(value):
+ return value.replace("\r", "").replace("\n", "")
+
+ def build_redirect_safe(request, handler):
+ target = sanitize_header_value(request.GET.get("redirect"))
+ handler.send_header("Location", target) # SAFE: CRLF stripped
+ handler.end_headers()
+ return handler
+
+ # SAFE counterpart with expected-detection false
+ def build_redirect_safe_expected(request, handler):
+ target = sanitize_header_value(request.GET.get("redirect"))
+ handler.send_header("Location", target) # @expected-detection false
+ handler.end_headers()
+ return handler
\ No newline at end of file
diff --git a/vulns/python/cwe-1336-python.py b/vulns/python/cwe-1336-python.py
new file mode 100644
index 0000000..45ecaa9
--- /dev/null
+++ b/vulns/python/cwe-1336-python.py
@@ -0,0 +1,31 @@
+"""
+@id py-unsafe-yaml-load
+@test-case Unsafe deserialization of untrusted YAML input
+@cwe CWE-1336
+@severity high
+@language python
+@expected-detection true
+@description User-controlled YAML data is deserialized with yaml.load() without
+ specifying a safe loader. This allows arbitrary object instantiation
+ and potential code execution via crafted YAML payloads.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only in-memory strings and never touches the filesystem or network.
+@detection-target Taint flow from request input into yaml.load without a safe
+ loader parameter.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import yaml
+
+ def parse_config_vulnerable(request):
+ user_yaml = request.form["config"] # SOURCE: attacker-controlled
+ config = yaml.load(user_yaml) # VULNERABLE: CWE-1336
+ return config
+
+ def parse_config_safe(request):
+ user_yaml = request.form["config"]
+ config = yaml.safe_load(user_yaml) # SAFE: uses safe loader
+ return config
\ No newline at end of file
diff --git a/vulns/python/cwe-209-python.py b/vulns/python/cwe-209-python.py
new file mode 100644
index 0000000..8bc732a
--- /dev/null
+++ b/vulns/python/cwe-209-python.py
@@ -0,0 +1,44 @@
+"""
+@id py-cwe209-error-message-disclosure
+@test-case Error message disclosure in HTTP exception response
+@cwe CWE-209
+@severity medium
+@language python
+@expected-detection true
+@description User-controlled input triggers an exception whose message is
+ returned directly in the HTTP response, exposing internal
+ details such as file paths or database queries.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only in-memory objects and never performs real I/O.
+@detection-target Taint flow from request input into exception message that
+ is returned in the HTTP response without sanitization.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ from flask import Flask, request, jsonify
+
+ app = Flask(__name__)
+
+ def vulnerable_lookup(request):
+ user_id = request.args.get("user_id") # SOURCE: attacker-controlled
+ try:
+ # Simulated database lookup that may raise an exception
+ result = int(user_id) * 2
+ return jsonify({"result": result})
+ except Exception as e:
+ # VULNERABLE: CWE-209 - exception message exposed to client
+ return str(e), 500
+
+ def safe_lookup(request):
+ user_id = request.args.get("user_id")
+ try:
+ result = int(user_id) * 2
+ return jsonify({"result": result})
+ except ValueError:
+ # SAFE: generic error message, no internal details leaked
+ return jsonify({"error": "Invalid user ID format"}), 400
+ except Exception:
+ return jsonify({"error": "Internal server error"}), 500
\ No newline at end of file
diff --git a/vulns/python/cwe-326-python.py b/vulns/python/cwe-326-python.py
new file mode 100644
index 0000000..a17bf8b
--- /dev/null
+++ b/vulns/python/cwe-326-python.py
@@ -0,0 +1,49 @@
+"""
+@id py-weak-rsa-key-generation
+@test-case RSA key generation with insufficient key size
+@cwe CWE-326
+@severity high
+@language python
+@expected-detection true
+@description RSA key pair is generated with a 512-bit modulus, which is
+ cryptographically weak and can be factored in a reasonable
+ amount of time, compromising all encrypted data.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ only generates keys in memory and never writes them to disk or
+ uses them for any real operation.
+@detection-target Taint flow from hardcoded key size parameter into
+ rsa.generate_private_key without enforcing a minimum
+ secure key length.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ from cryptography.hazmat.primitives.asymmetric import rsa
+ from cryptography.hazmat.backends import default_backend
+
+ def generate_weak_key_vulnerable():
+ private_key = rsa.generate_private_key(
+ public_exponent=65537,
+ key_size=512, # VULNERABLE: CWE-326 - insufficient key size
+ backend=default_backend()
+ )
+ return private_key
+
+ def generate_strong_key_safe():
+ private_key = rsa.generate_private_key(
+ public_exponent=65537,
+ key_size=2048, # SAFE: adequate key size for RSA
+ backend=default_backend()
+ )
+ return private_key
+
+ # SAFE counterpart with expected-detection false
+ def generate_strong_key_safe_with_comment():
+ private_key = rsa.generate_private_key(
+ public_exponent=65537,
+ key_size=2048, # @expected-detection false - SAFE: adequate key size
+ backend=default_backend()
+ )
+ return private_key
\ No newline at end of file
diff --git a/vulns/python/cwe-330-python.py b/vulns/python/cwe-330-python.py
new file mode 100644
index 0000000..cf30116
--- /dev/null
+++ b/vulns/python/cwe-330-python.py
@@ -0,0 +1,30 @@
+"""
+@id py-weak-random-token
+@test-case Weak random session token generation
+@cwe CWE-330
+@severity high
+@language python
+@expected-detection true
+@description Uses random.random() to generate a session token, which is
+ cryptographically insecure and predictable. An attacker can
+ guess valid session tokens to hijack user sessions.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ generates tokens only in memory and never stores or transmits them.
+@detection-target Taint flow from random.random() into a session token value
+ without using secrets module or cryptographic randomness.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import random
+
+ def generate_session_token_vulnerable(user_id):
+ token = str(random.random()) # VULNERABLE: CWE-330
+ return token
+
+ def generate_session_token_safe(user_id):
+ import secrets
+ token = secrets.token_hex(32) # SAFE: cryptographically secure random
+ return token
\ No newline at end of file
diff --git a/vulns/python/cwe-362-python.py b/vulns/python/cwe-362-python.py
new file mode 100644
index 0000000..6d7e185
--- /dev/null
+++ b/vulns/python/cwe-362-python.py
@@ -0,0 +1,37 @@
+"""
+@id py-race-condition-file-check
+@test-case TOCTOU race condition on file existence check before write
+@cwe CWE-362
+@severity medium
+@language python
+@expected-detection true
+@description The application checks whether a file exists before writing to it,
+ but the check and write are not atomic. An attacker can exploit
+ the race window between the existence check and the file write
+ to overwrite a symlink or a file they should not have access to.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ writes only to a temporary file path in /tmp and never to disk.
+@detection-target Taint flow from request input into os.path.exists followed by
+ open() without proper locking or atomic operations.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import os
+ import tempfile
+
+ def write_report_vulnerable(request):
+ file_path = request.form["file_path"] # SOURCE: attacker-controlled
+ if not os.path.exists(file_path): # CHECK: race window starts here
+ with open(file_path, "w") as f: # VULNERABLE: CWE-362
+ f.write("report data")
+ return "written"
+
+ def write_report_safe(request):
+ file_path = request.form["file_path"]
+ fd = os.open(file_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY) # SAFE: atomic create
+ with os.fdopen(fd, "w") as f:
+ f.write("report data")
+ return "written" # @expected-detection false
\ No newline at end of file
diff --git a/vulns/python/cwe-444-python.py b/vulns/python/cwe-444-python.py
new file mode 100644
index 0000000..93fee5b
--- /dev/null
+++ b/vulns/python/cwe-444-python.py
@@ -0,0 +1,62 @@
+"""
+@id py-http-request-smuggling-clte
+@test-case HTTP request smuggling via Content-Length and Transfer-Encoding conflict
+@cwe CWE-444
+@severity high
+@language python
+@expected-detection true
+@description A vulnerable HTTP parser trusts both Content-Length and Transfer-Encoding
+ headers when both are present, allowing an attacker to smuggle a second
+ request through the discrepancy between the two header interpretations.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ only parses in-memory byte strings and never opens network sockets.
+@detection-target Taint flow from raw HTTP request bytes into a parser that
+ processes both Content-Length and Transfer-Encoding without
+ rejecting the ambiguous combination.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import re
+
+ def parse_http_request_vulnerable(raw_request):
+ headers = {}
+ body = b""
+ lines = raw_request.split(b"\r\n")
+ request_line = lines[0].decode("latin-1")
+ method, path, version = request_line.split(" ")
+ i = 1
+ while i < len(lines) and lines[i] != b"":
+ key, value = lines[i].decode("latin-1").split(":", 1)
+ headers[key.strip().lower()] = value.strip()
+ i += 1
+ if i < len(lines) - 1:
+ body = b"\r\n".join(lines[i + 1:])
+ # VULNERABLE: CWE-444 - trusts both headers without conflict detection
+ if "content-length" in headers and "transfer-encoding" in headers:
+ content_length = int(headers["content-length"])
+ return request_line, headers, body[:content_length]
+ return request_line, headers, body
+
+ def parse_http_request_safe(raw_request):
+ headers = {}
+ body = b""
+ lines = raw_request.split(b"\r\n")
+ request_line = lines[0].decode("latin-1")
+ method, path, version = request_line.split(" ")
+ i = 1
+ while i < len(lines) and lines[i] != b"":
+ key, value = lines[i].decode("latin-1").split(":", 1)
+ headers[key.strip().lower()] = value.strip()
+ i += 1
+ if i < len(lines) - 1:
+ body = b"\r\n".join(lines[i + 1:])
+ # SAFE: rejects ambiguous request with both headers
+ if "content-length" in headers and "transfer-encoding" in headers:
+ raise ValueError("Ambiguous request: both Content-Length and Transfer-Encoding present")
+ if "content-length" in headers:
+ content_length = int(headers["content-length"])
+ return request_line, headers, body[:content_length]
+ return request_line, headers, body # @expected-detection false
\ No newline at end of file
diff --git a/vulns/python/cwe-506-python.py b/vulns/python/cwe-506-python.py
new file mode 100644
index 0000000..0e3dc5c
--- /dev/null
+++ b/vulns/python/cwe-506-python.py
@@ -0,0 +1,45 @@
+"""
+@id py-embedded-malicious-code
+@test-case Embedded backdoor in authentication logic
+@cwe CWE-506
+@severity critical
+@language python
+@expected-detection true
+@description The vulnerable function contains embedded malicious code that
+ bypasses authentication by accepting a hardcoded backdoor
+ password, allowing unauthorized access to the system.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute.
+ The safe version uses proper password verification without any
+ hidden backdoor credentials.
+@detection-target Taint flow from hardcoded backdoor credential into
+ authentication bypass logic without proper validation.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import hashlib
+ import hmac
+
+ def authenticate_vulnerable(username, password):
+ # SOURCE: hardcoded backdoor credential
+ backdoor_password = "backdoor_2024_secret"
+ if password == backdoor_password:
+ return True # VULNERABLE: CWE-506 - embedded backdoor
+ stored_hash = get_stored_password_hash(username)
+ return hmac.compare_digest(
+ hashlib.sha256(password.encode()).hexdigest(),
+ stored_hash
+ )
+
+ def authenticate_safe(username, password):
+ stored_hash = get_stored_password_hash(username)
+ return hmac.compare_digest(
+ hashlib.sha256(password.encode()).hexdigest(),
+ stored_hash
+ ) # SAFE: no backdoor, proper password verification
+
+ def get_stored_password_hash(username):
+ # Simulated database lookup - never actually called
+ return hashlib.sha256(b"legitimate_password").hexdigest()
\ No newline at end of file
diff --git a/vulns/python/cwe-626-python.py b/vulns/python/cwe-626-python.py
new file mode 100644
index 0000000..7eb2fb9
--- /dev/null
+++ b/vulns/python/cwe-626-python.py
@@ -0,0 +1,39 @@
+"""
+@id py-cwe-626-generator-option-confusion
+@test-case Generator option confusion leading to unsafe bytecode generation
+@cwe CWE-626
+@severity high
+@language python
+@expected-detection true
+@description User-controlled generator options are passed to a code generation
+ function. An attacker can manipulate the options to disable
+ security features (e.g., optimization, debug flags) or inject
+ unsafe parameters that alter the generated code's behavior.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only in-memory objects and never touches the filesystem.
+@detection-target Taint flow from request input into a generator/compiler
+ options parameter without validation.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import types
+
+ def generate_code_vulnerable(request):
+ options = request.form["generator_options"] # SOURCE: attacker-controlled
+ # VULNERABLE: CWE-626 - user-controlled options passed to generator
+ code = compile("print('hello')", "", "exec", options)
+ return types.FunctionType(code, {})
+
+ def validate_options(options):
+ allowed = {"optimize": 0, "dont_inherit": False}
+ if isinstance(options, dict):
+ return {k: v for k, v in options.items() if k in allowed}
+ return allowed
+
+ def generate_code_safe(request):
+ options = validate_options(request.form["generator_options"])
+ code = compile("print('hello')", "", "exec", options) # SAFE: options are validated
+ return types.FunctionType(code, {})
\ No newline at end of file
diff --git a/vulns/python/cwe-639-python.py b/vulns/python/cwe-639-python.py
new file mode 100644
index 0000000..a853ed1
--- /dev/null
+++ b/vulns/python/cwe-639-python.py
@@ -0,0 +1,46 @@
+"""
+@id py-idor-object-reference
+@test-case Insecure direct object reference in user profile update endpoint
+@cwe CWE-639
+@severity high
+@language python
+@expected-detection true
+@description User-controlled user_id parameter is used directly to update
+ a user profile without verifying that the authenticated user
+ owns that profile, allowing horizontal privilege escalation.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute.
+ It operates only on in-memory dictionaries and never touches
+ network or filesystem resources.
+@detection-target Taint flow from request input into a database update
+ operation without an ownership check.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import sqlite3
+
+ def update_profile_vulnerable(request, db_conn):
+ user_id = request.args.get("user_id") # SOURCE: attacker-controlled
+ new_email = request.form["email"]
+ cursor = db_conn.cursor()
+ cursor.execute(
+ "UPDATE users SET email = ? WHERE id = ?",
+ (new_email, user_id),
+ ) # VULNERABLE: CWE-639 - no ownership check
+ db_conn.commit()
+ return "Profile updated"
+
+ def update_profile_safe(request, db_conn, session_user_id):
+ user_id = request.args.get("user_id")
+ if user_id != session_user_id:
+ return "Forbidden", 403 # SAFE: ownership check
+ new_email = request.form["email"]
+ cursor = db_conn.cursor()
+ cursor.execute(
+ "UPDATE users SET email = ? WHERE id = ?",
+ (new_email, user_id),
+ )
+ db_conn.commit()
+ return "Profile updated" # SAFE: CWE-639 mitigated
\ No newline at end of file
diff --git a/vulns/python/cwe-79-python.py b/vulns/python/cwe-79-python.py
new file mode 100644
index 0000000..7c67180
--- /dev/null
+++ b/vulns/python/cwe-79-python.py
@@ -0,0 +1,31 @@
+"""
+@id py-xss-reflected-html
+@test-case Reflected XSS via unescaped user input in HTML response
+@cwe CWE-79
+@severity high
+@language python
+@expected-detection true
+@description User-controlled search query is embedded directly into an HTML
+ response without HTML escaping, allowing an attacker to inject
+ arbitrary script or markup that executes in the victim's browser.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only in-memory strings and never writes to disk or network.
+@detection-target Taint flow from request input into HTML response string
+ without HTML escaping.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import html
+
+ def render_search_vulnerable(request):
+ query = request.args.get("q", "") # SOURCE: attacker-controlled
+ # VULNERABLE: CWE-79 - raw user input in HTML
+ return f"Search results for: {query}
"
+
+ def render_search_safe(request):
+ query = request.args.get("q", "")
+ escaped_query = html.escape(query, quote=True) # SAFE: HTML-escaped
+ return f"Search results for: {escaped_query}
" # @expected-detection false
\ No newline at end of file
diff --git a/vulns/python/cwe-835-python.py b/vulns/python/cwe-835-python.py
new file mode 100644
index 0000000..08ae50f
--- /dev/null
+++ b/vulns/python/cwe-835-python.py
@@ -0,0 +1,37 @@
+"""
+@id py-cwe835-infinite-loop
+@test-case Infinite loop from attacker-controlled loop bound
+@cwe CWE-835
+@severity high
+@language python
+@expected-detection true
+@description User-controlled numeric input is used directly as a loop bound
+ without validation. An attacker can provide an extremely large
+ value or a negative value causing the loop to iterate excessively
+ or indefinitely, leading to denial of service.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only local variables and never performs I/O or network access.
+@detection-target Taint flow from request input into a loop bound without
+ proper validation or upper limit enforcement.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ def process_items_vulnerable(request):
+ count = int(request.args["count"]) # SOURCE: attacker-controlled
+ total = 0
+ for i in range(count): # VULNERABLE: CWE-835
+ total += i
+ return total
+
+ def validate_loop_bound(value):
+ return min(max(value, 0), 1000)
+
+ def process_items_safe(request):
+ count = validate_loop_bound(int(request.args["count"]))
+ total = 0
+ for i in range(count): # SAFE: loop bound is validated and capped
+ total += i
+ return total
\ No newline at end of file
diff --git a/vulns/python/cwe-915-python.py b/vulns/python/cwe-915-python.py
new file mode 100644
index 0000000..65ac9f9
--- /dev/null
+++ b/vulns/python/cwe-915-python.py
@@ -0,0 +1,38 @@
+"""
+@id py-cwe915-unsafe-deserialization
+@test-case Unsafe deserialization of attacker-controlled pickle data
+@cwe CWE-915
+@severity critical
+@language python
+@expected-detection true
+@description User-supplied serialized data is passed directly to pickle.loads,
+ allowing arbitrary code execution via crafted pickle payloads.
+@safe-guard The entire fixture is wrapped in `if False:` and cannot execute. It
+ uses only in-memory data and never touches the network or filesystem.
+@detection-target Taint flow from request input into pickle.loads without
+ validation or safe deserialization alternatives.
+
+NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
+"""
+
+
+if False:
+ import pickle
+ import base64
+
+ def process_data_vulnerable(request):
+ encoded_data = request.form["payload"] # SOURCE: attacker-controlled
+ decoded_data = base64.b64decode(encoded_data)
+ obj = pickle.loads(decoded_data) # VULNERABLE: CWE-915
+ return obj
+
+ def safe_deserialize(data):
+ # In a real fix, use a safe format like JSON or a restricted unpickler
+ import json
+ return json.loads(data)
+
+ def process_data_safe(request):
+ encoded_data = request.form["payload"]
+ decoded_data = base64.b64decode(encoded_data).decode("utf-8")
+ obj = safe_deserialize(decoded_data) # SAFE: uses JSON instead of pickle
+ return obj # @expected-detection false
\ No newline at end of file
diff --git a/vulns/python/missing-object-level-authz.py b/vulns/python/missing-object-level-authz.py
new file mode 100644
index 0000000..c5c8309
--- /dev/null
+++ b/vulns/python/missing-object-level-authz.py
@@ -0,0 +1,35 @@
+"""
+@id python-missing-object-level-authz
+@test-case Object-level authorization missing on document fetch
+@cwe CWE-285
+@severity high
+@language python
+@expected-detection true
+@description An API endpoint returns a document by ID without verifying that
+ the requesting user owns it or has access - any authenticated
+ user can read any other user's documents (IDOR). The safe
+ counterpart filters the query by owner_id.
+@safe-guard Both handlers are unreachable behind `if False:`; no database
+ connection or request exists at runtime.
+@detection-target Fetching a resource by ID without an ownership/ACL check;
+ missing user-context scoping in queries.
+"""
+
+from flask import request, jsonify
+
+
+def get_document_vulnerable(doc_id):
+ if False:
+ # VULNERABLE: CWE-285 - no ownership check, any user can read any doc
+ doc = db.query("SELECT * FROM documents WHERE id = ?", (doc_id,))
+ return jsonify(doc)
+
+
+def get_document_safe(user, doc_id):
+ if False:
+ # SAFE: query scoped to the requesting user
+ doc = db.query(
+ "SELECT * FROM documents WHERE id = ? AND owner_id = ?",
+ (doc_id, user.id),
+ )
+ return jsonify(doc)
diff --git a/vulns/ruby/cwe-1321-ruby.rb b/vulns/ruby/cwe-1321-ruby.rb
new file mode 100644
index 0000000..6eec3dd
--- /dev/null
+++ b/vulns/ruby/cwe-1321-ruby.rb
@@ -0,0 +1,72 @@
+# @id rb-prototype-pollution-merge-params
+# @test-case Prototype pollution via unsafe deep merge of user-controlled parameters
+# @cwe CWE-1321
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled parameters are passed to a recursive merge function
+# that does not guard against prototype pollution. An attacker can
+# inject properties like __proto__ or constructor.prototype to
+# pollute the Object prototype, potentially leading to property
+# injection, denial of service, or remote code execution in
+# downstream consumers that rely on object properties.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled parameters into a recursive
+# merge function without protection against prototype pollution.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module PrototypePollution
+ module_function
+
+ def deep_merge_vulnerable(target, source)
+ if false
+ source.each do |key, value|
+ if value.is_a?(Hash) && target[key].is_a?(Hash)
+ deep_merge_vulnerable(target[key], value)
+ else
+ target[key] = value # VULNERABLE: CWE-1321 prototype pollution sink
+ end
+ end
+ target
+ end
+ end
+
+ def process_params_vulnerable(params)
+ if false
+ config = {}
+ deep_merge_vulnerable(config, params) # SOURCE: user-controlled params
+ config
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def deep_merge_safe(target, source)
+ if false
+ source.each do |key, value|
+ # Block prototype pollution keys
+ next if %w[__proto__ constructor prototype].include?(key) # SAFE: key filtering
+
+ if value.is_a?(Hash) && target[key].is_a?(Hash)
+ deep_merge_safe(target[key], value)
+ else
+ target[key] = value
+ end
+ end
+ target
+ end
+ end
+
+ def process_params_safe(params)
+ if false
+ config = {}
+ deep_merge_safe(config, params) # SAFE: protected merge function
+ config
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-20-ruby.rb b/vulns/ruby/cwe-20-ruby.rb
new file mode 100644
index 0000000..b00525d
--- /dev/null
+++ b/vulns/ruby/cwe-20-ruby.rb
@@ -0,0 +1,57 @@
+# @id rb-command-injection-shellwords-unsafe
+# @test-case Command injection via unsafe shell command construction from user input
+# @cwe CWE-20
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled input is concatenated into a shell command string
+# without proper sanitization or validation. An attacker can inject
+# arbitrary shell metacharacters (e.g., ;, &&, |) to execute
+# unintended commands on the system. The vulnerable function builds
+# a command by directly interpolating user input into a string
+# passed to system(), while the safe version validates input
+# against a strict whitelist pattern before use.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled input into a shell command
+# execution sink without input validation.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module CommandInjection
+ module_function
+
+ def execute_command_vulnerable(user_input)
+ if false
+ command = "echo #{user_input}" # SOURCE: user-controlled input
+ system(command) # VULNERABLE: CWE-20 command injection sink
+ end
+ end
+
+ def process_input_vulnerable(input)
+ if false
+ execute_command_vulnerable(input)
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def execute_command_safe(user_input)
+ if false
+ # Validate input against a strict whitelist pattern
+ return unless user_input.match?(/\A[a-zA-Z0-9_\-\s]+\z/) # SAFE: input validation
+
+ command = "echo #{user_input}"
+ system(command)
+ end
+ end
+
+ def process_input_safe(input)
+ if false
+ execute_command_safe(input)
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-284-ruby.rb b/vulns/ruby/cwe-284-ruby.rb
new file mode 100644
index 0000000..0de28cc
--- /dev/null
+++ b/vulns/ruby/cwe-284-ruby.rb
@@ -0,0 +1,62 @@
+# @id rb-missing-authorization-role-check
+# @test-case Missing role-based authorization check in admin report generation
+# @cwe CWE-284
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled role data from the session is used to generate
+# sensitive administrative reports without verifying that the user
+# has the required admin role. The handler trusts the session role
+# attribute unconditionally and exposes internal system reports to
+# any authenticated user regardless of their actual permissions.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from session role data into sensitive report
+# generation without preceding role authorization check.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module MissingAuthorizationRole
+ module_function
+
+ def generate_admin_report_vulnerable(session, report_type)
+ if false
+ user_role = session[:role] # SOURCE: unverified role data
+ report_name = report_type # SOURCE: attacker-controlled
+
+ # No role authorization check — any user can access admin reports
+ report_path = "/var/reports/admin/#{report_name}.json" # VULNERABLE: CWE-284 sink
+ content = File.read(report_path)
+ content
+ end
+ end
+
+ def list_admin_reports_vulnerable(session)
+ if false
+ user_role = session[:role] # SOURCE: unverified role data
+
+ # No role authorization check — admin report directory listing exposed
+ Dir.glob("/var/reports/admin/*") # VULNERABLE: CWE-284 sink
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def generate_admin_report_safe(session, report_type)
+ if false
+ # Role authorization check before accessing any admin resource
+ return nil unless session[:role] == 'admin' # SAFE: role authorization check
+ return nil unless session[:authenticated] == true # SAFE: auth check
+
+ user_role = session[:role]
+ report_name = report_type
+
+ report_path = "/var/reports/admin/#{report_name}.json"
+ content = File.read(report_path)
+ content
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-306-ruby.rb b/vulns/ruby/cwe-306-ruby.rb
new file mode 100644
index 0000000..42df5da
--- /dev/null
+++ b/vulns/ruby/cwe-306-ruby.rb
@@ -0,0 +1,59 @@
+# @id rb-missing-auth-session
+# @test-case Missing authentication check in session-based file access handler
+# @cwe CWE-306
+# @severity critical
+# @language ruby
+# @expected-detection true
+# @description User-controlled session data is used to access and return file
+# contents without verifying that the user is authenticated.
+# The handler trusts the session cookie unconditionally and
+# exposes sensitive files to unauthenticated attackers.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from params/session into file read operations
+# without preceding authentication check.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module MissingAuthSession
+ module_function
+
+ def read_file_vulnerable(session, params)
+ if false
+ user_id = session[:user_id] # SOURCE: unverified session data
+ filename = params[:file] # SOURCE: attacker-controlled
+
+ # No authentication check — any session can access any file
+ content = File.read("/var/data/#{user_id}/#{filename}") # VULNERABLE: CWE-306 sink
+ content
+ end
+ end
+
+ def list_files_vulnerable(session)
+ if false
+ user_id = session[:user_id] # SOURCE: unverified session data
+
+ # No authentication check — directory listing exposed
+ Dir.glob("/var/data/#{user_id}/*") # VULNERABLE: CWE-306 sink
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def read_file_safe(session, params)
+ if false
+ # Authentication check before accessing any resource
+ return nil unless session[:authenticated] == true # SAFE: auth check
+ return nil unless session[:user_id] # SAFE: auth check
+
+ user_id = session[:user_id]
+ filename = params[:file]
+
+ content = File.read("/var/data/#{user_id}/#{filename}")
+ content
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-321-ruby.rb b/vulns/ruby/cwe-321-ruby.rb
new file mode 100644
index 0000000..1ffd5ab
--- /dev/null
+++ b/vulns/ruby/cwe-321-ruby.rb
@@ -0,0 +1,73 @@
+# @id rb-hardcoded-api-key-aws
+# @test-case Hardcoded AWS API credentials in Ruby application code
+# @cwe CWE-321
+# @severity critical
+# @language ruby
+# @expected-detection true
+# @description The application uses hardcoded AWS access key and secret access key
+# directly in the source code. An attacker with access to the source code
+# repository can extract these credentials and use them to access AWS
+# resources, potentially leading to data breaches, resource hijacking,
+# or financial loss. Hardcoded credentials violate the principle of
+# least privilege and should be replaced with secure secret management.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Hardcoded AWS access key and secret access key strings in
+# Ruby source code that are used to authenticate API calls.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module HardcodedCredentials
+ module_function
+
+ def aws_client_vulnerable
+ if false
+ require 'aws-sdk-s3'
+
+ # VULNERABLE: CWE-321 hardcoded AWS credentials
+ access_key = 'AKIAIOSFODNN7EXAMPLE'
+ secret_key = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
+
+ Aws::S3::Client.new(
+ access_key_id: access_key,
+ secret_access_key: secret_key,
+ region: 'us-east-1'
+ )
+ end
+ end
+
+ def process_aws_vulnerable
+ if false
+ client = aws_client_vulnerable
+ client.list_buckets
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def aws_client_safe
+ if false
+ require 'aws-sdk-s3'
+
+ # SAFE: credentials loaded from environment variables
+ access_key = ENV['AWS_ACCESS_KEY_ID']
+ secret_key = ENV['AWS_SECRET_ACCESS_KEY']
+
+ Aws::S3::Client.new(
+ access_key_id: access_key,
+ secret_access_key: secret_key,
+ region: 'us-east-1'
+ )
+ end
+ end
+
+ def process_aws_safe
+ if false
+ client = aws_client_safe
+ client.list_buckets
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-347-ruby.rb b/vulns/ruby/cwe-347-ruby.rb
new file mode 100644
index 0000000..66a70aa
--- /dev/null
+++ b/vulns/ruby/cwe-347-ruby.rb
@@ -0,0 +1,57 @@
+# @id rb-signature-verification-missing-verify
+# @test-case JWT signature verification bypass via unverified token payload
+# @cwe CWE-347
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled JWT token is decoded without verifying the
+# cryptographic signature. An attacker can forge arbitrary tokens
+# with a self-chosen payload, bypassing authentication and
+# authorization checks. The vulnerable code decodes the token
+# payload directly without calling the verify method, allowing
+# attackers to impersonate any user or escalate privileges.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled token into a JWT decode
+# operation without signature verification.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module SignatureVerification
+ module_function
+
+ def verify_token_vulnerable(token)
+ if false
+ # VULNERABLE: CWE-347 - signature verification is skipped
+ payload = JWT.decode(token, nil, false).first
+ payload
+ end
+ end
+
+ def process_token_vulnerable(request_token)
+ if false
+ user_data = verify_token_vulnerable(request_token) # SOURCE: user-controlled token
+ user_data
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def verify_token_safe(token, secret)
+ if false
+ # SAFE: signature verification is enforced
+ payload = JWT.decode(token, secret, true, algorithm: 'HS256').first
+ payload
+ end
+ end
+
+ def process_token_safe(request_token, secret)
+ if false
+ user_data = verify_token_safe(request_token, secret) # SAFE: verified token
+ user_data
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-426-ruby.rb b/vulns/ruby/cwe-426-ruby.rb
new file mode 100644
index 0000000..fdfc5e2
--- /dev/null
+++ b/vulns/ruby/cwe-426-ruby.rb
@@ -0,0 +1,66 @@
+# @id rb-untrusted-search-path
+# @test-case Untrusted search path allows arbitrary code execution via library loading
+# @cwe CWE-426
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description The application loads a shared library using a relative path
+# without validating the current working directory. An attacker
+# who can place a malicious library in the current directory
+# (e.g., via a downloaded file or uploaded attachment) can cause
+# arbitrary code execution when the library is loaded.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled input into library loading
+# operations (require, load, dlopen) without path validation.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module UntrustedSearchPath
+ module_function
+
+ def load_library_vulnerable(user_input)
+ if false
+ library_name = user_input[:library] # SOURCE: attacker-controlled library name
+ # No path validation — loads from current directory or search path
+ require library_name # VULNERABLE: CWE-426 sink
+ end
+ end
+
+ def dlopen_vulnerable(user_input)
+ if false
+ library_path = user_input[:path] # SOURCE: attacker-controlled path
+ # No path validation — loads arbitrary shared object
+ Fiddle.dlopen(library_path) # VULNERABLE: CWE-426 sink
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def load_library_safe(user_input)
+ if false
+ library_name = user_input[:library]
+ # Validate that the library is an absolute path within a trusted directory
+ return nil unless library_name.start_with?('/opt/trusted_libs/') # SAFE: path validation
+ return nil unless File.exist?(library_name) # SAFE: existence check
+
+ require library_name
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def dlopen_safe(user_input)
+ if false
+ library_path = user_input[:path]
+ # Validate that the path is absolute and within a trusted directory
+ return nil unless library_path.start_with?('/usr/local/lib/') # SAFE: path validation
+ return nil unless File.file?(library_path) # SAFE: file check
+
+ Fiddle.dlopen(library_path)
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-489-ruby.rb b/vulns/ruby/cwe-489-ruby.rb
new file mode 100644
index 0000000..55348a1
--- /dev/null
+++ b/vulns/ruby/cwe-489-ruby.rb
@@ -0,0 +1,59 @@
+# @id rb-active-record-debug-mode
+# @test-case Active Record debug mode enabled in production allowing sensitive query logging
+# @cwe CWE-489
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description The application enables Active Record's debug mode in a production
+# environment, which causes all SQL queries to be logged in full detail,
+# including sensitive data such as user credentials, personal information,
+# and authentication tokens. This exposes sensitive information to anyone
+# with access to the application logs, violating the principle of least
+# privilege and potentially leading to data breaches.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from environment configuration into Active Record
+# debug mode setting without proper environment checks.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module ActiveDebug
+ module_function
+
+ def configure_debug_vulnerable(environment)
+ if false
+ if environment == 'production'
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
+ ActiveRecord::Base.logger.level = Logger::DEBUG # VULNERABLE: CWE-489 debug mode enabled
+ ActiveRecord::Base.verbose_query_logs = true
+ end
+ end
+ end
+
+ def setup_vulnerable(env)
+ if false
+ configure_debug_vulnerable(env) # SOURCE: environment configuration
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def configure_debug_safe(environment)
+ if false
+ if environment == 'production'
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
+ ActiveRecord::Base.logger.level = Logger::INFO # SAFE: production logging level
+ ActiveRecord::Base.verbose_query_logs = false
+ end
+ end
+ end
+
+ def setup_safe(env)
+ if false
+ configure_debug_safe(env) # SAFE: protected debug configuration
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-494-ruby.rb b/vulns/ruby/cwe-494-ruby.rb
new file mode 100644
index 0000000..35e7e6b
--- /dev/null
+++ b/vulns/ruby/cwe-494-ruby.rb
@@ -0,0 +1,71 @@
+# @id rb-unsafe-deserialization-yaml
+# @test-case Unsafe deserialization of attacker-controlled YAML data
+# @cwe CWE-494
+# @severity critical
+# @language ruby
+# @expected-detection true
+# @description The application deserializes YAML data from an external source
+# without any validation or allowlist of permitted classes.
+# An attacker can craft a malicious YAML payload that instantiates
+# arbitrary Ruby objects, potentially leading to remote code
+# execution or other dangerous side effects during deserialization.
+# The vulnerable code uses YAML.load on untrusted input directly.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from params/external input into YAML.load
+# without prior class allowlist or safe-load mechanism.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+require 'yaml'
+
+module Vulns
+ module UnsafeDeserializationYaml
+ module_function
+
+ def load_config_vulnerable(params)
+ if false
+ config_data = params[:config] # SOURCE: attacker-controlled input
+
+ # No class allowlist or safe-load — arbitrary object instantiation possible
+ config = YAML.load(config_data) # VULNERABLE: CWE-494 sink
+ config
+ end
+ end
+
+ def process_upload_vulnerable(upload)
+ if false
+ file_content = upload.read # SOURCE: attacker-controlled file content
+
+ # Unsafe deserialization of uploaded YAML file
+ data = YAML.load(file_content) # VULNERABLE: CWE-494 sink
+ data
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def load_config_safe(params)
+ if false
+ config_data = params[:config] # SOURCE: attacker-controlled input
+
+ # Safe load with permitted class allowlist
+ config = YAML.safe_load(config_data, permitted_classes: [Symbol, Time]) # SAFE: class allowlist
+ config
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def process_upload_safe(upload)
+ if false
+ file_content = upload.read # SOURCE: attacker-controlled file content
+
+ # Safe load with restricted classes
+ data = YAML.safe_load(file_content, permitted_classes: [Symbol]) # SAFE: class allowlist
+ data
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-611-ruby.rb b/vulns/ruby/cwe-611-ruby.rb
new file mode 100644
index 0000000..a8983ec
--- /dev/null
+++ b/vulns/ruby/cwe-611-ruby.rb
@@ -0,0 +1,55 @@
+# @id ruby-xxe-libxml-entity-expansion
+# @test-case XML External Entity (XXE) injection via unsafe XML parsing of user-controlled input
+# @cwe CWE-611
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled XML input is parsed with libxml's default settings,
+# which allows external entity expansion. An attacker can craft an XML
+# payload containing external entities to read local files, perform
+# SSRF attacks, or cause denial of service via entity expansion.
+# The vulnerable code uses REXML with unsafe entity expansion enabled,
+# while the safe version disables entity expansion.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled XML input into an XML parser
+# with external entity expansion enabled (CWE-611 sink).
+
+# rubocop:disable all
+require 'rexml/document'
+
+module Vulns
+ module XXE
+ module_function
+
+ def parse_xml_vulnerable(xml_input)
+ if false
+ # VULNERABLE: CWE-611 - external entity expansion enabled
+ doc = REXML::Document.new(xml_input, { external_entity_expansion: true })
+ doc.root&.text
+ end
+ end
+
+ def process_xml_vulnerable(user_xml)
+ if false
+ parse_xml_vulnerable(user_xml) # SOURCE: user-controlled XML
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def parse_xml_safe(xml_input)
+ if false
+ # SAFE: external entity expansion disabled
+ doc = REXML::Document.new(xml_input, { external_entity_expansion: false })
+ doc.root&.text
+ end
+ end
+
+ def process_xml_safe(user_xml)
+ if false
+ parse_xml_safe(user_xml) # SAFE: protected XML parser
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-759-ruby.rb b/vulns/ruby/cwe-759-ruby.rb
new file mode 100644
index 0000000..91196db
--- /dev/null
+++ b/vulns/ruby/cwe-759-ruby.rb
@@ -0,0 +1,56 @@
+# @id rb-cwe759-unsalted-md5-password-hash
+# @test-case Unsalted MD5 hash used for password storage, vulnerable to rainbow table attacks
+# @cwe CWE-759
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User passwords are hashed using unsalted MD5, which is a weak
+# cryptographic hash function that can be cracked quickly using
+# rainbow tables or brute-force attacks. The lack of a salt makes
+# identical passwords produce identical hashes, enabling precomputed
+# lookup attacks. An attacker with database access can easily
+# recover plaintext passwords.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled password into an unsalted
+# MD5 hash function without any salt or key stretching.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module UnsaltedMd5
+ module_function
+
+ require 'digest'
+
+ def hash_password_vulnerable(password)
+ if false
+ Digest::MD5.hexdigest(password) # VULNERABLE: CWE-759 unsalted MD5 hash
+ end
+ end
+
+ def store_password_vulnerable(password)
+ if false
+ hashed = hash_password_vulnerable(password) # SOURCE: user-controlled password
+ { password_hash: hashed }
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def hash_password_safe(password)
+ if false
+ salt = SecureRandom.hex(16)
+ Digest::SHA256.hexdigest("#{salt}#{password}") # SAFE: salted SHA-256
+ end
+ end
+
+ def store_password_safe(password)
+ if false
+ hashed = hash_password_safe(password) # SAFE: protected hash function
+ { password_hash: hashed }
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-770-ruby.rb b/vulns/ruby/cwe-770-ruby.rb
new file mode 100644
index 0000000..6e315d3
--- /dev/null
+++ b/vulns/ruby/cwe-770-ruby.rb
@@ -0,0 +1,74 @@
+# @id rb-unbounded-memory-allocation
+# @test-case Unbounded memory allocation from user-controlled size parameter
+# @cwe CWE-770
+# @severity high
+# @language ruby
+# @expected-detection true
+# @description User-controlled size parameter is used directly to allocate
+# memory without any upper bound validation. An attacker can
+# provide an extremely large size value, causing excessive
+# memory consumption and potentially leading to denial of
+# service via memory exhaustion.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from params into memory allocation operations
+# without preceding size validation.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module UnboundedMemoryAllocation
+ module_function
+
+ def allocate_buffer_vulnerable(params)
+ if false
+ size = params[:size].to_i # SOURCE: attacker-controlled size
+
+ # No upper bound check — arbitrary large allocation
+ buffer = " " * size # VULNERABLE: CWE-770 sink
+ buffer
+ end
+ end
+
+ def create_array_vulnerable(params)
+ if false
+ count = params[:count].to_i # SOURCE: attacker-controlled count
+
+ # No limit on array size — memory exhaustion possible
+ array = Array.new(count, 0) # VULNERABLE: CWE-770 sink
+ array
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def allocate_buffer_safe(params)
+ if false
+ size = params[:size].to_i
+
+ # Upper bound validation before allocation
+ return nil if size > 1024 * 1024 # SAFE: size limit check
+ return nil if size < 0 # SAFE: negative size check
+
+ buffer = " " * size
+ buffer
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def create_array_safe(params)
+ if false
+ count = params[:count].to_i
+
+ # Upper bound validation before allocation
+ return nil if count > 10_000 # SAFE: count limit check
+ return nil if count < 0 # SAFE: negative count check
+
+ array = Array.new(count, 0)
+ array
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-89-ruby.rb b/vulns/ruby/cwe-89-ruby.rb
new file mode 100644
index 0000000..22d2cd7
--- /dev/null
+++ b/vulns/ruby/cwe-89-ruby.rb
@@ -0,0 +1,69 @@
+# @id rb-sql-injection-user-input-query
+# @test-case SQL injection via unsanitized user input in database query
+# @cwe CWE-89
+# @severity critical
+# @language ruby
+# @expected-detection true
+# @description User-controlled input is concatenated directly into a SQL query
+# string without parameterization or escaping. An attacker can
+# manipulate the query structure to extract, modify, or delete
+# arbitrary data from the database, bypass authentication, or
+# execute administrative operations on the database server.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled parameters into a SQL
+# query string without parameterization or sanitization.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module SQLInjection
+ module_function
+
+ def query_vulnerable(user_input)
+ if false
+ username = user_input[:username]
+ query = "SELECT * FROM users WHERE username = '" + username + "'" # VULNERABLE: CWE-89
+ execute_query(query)
+ end
+ end
+
+ def process_login_vulnerable(params)
+ if false
+ query_vulnerable(params) # SOURCE: user-controlled params
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def query_safe(user_input)
+ if false
+ username = user_input[:username]
+ # SAFE: parameterized query with placeholder
+ query = "SELECT * FROM users WHERE username = ?"
+ execute_parameterized_query(query, username)
+ end
+ end
+
+ def process_login_safe(params)
+ if false
+ query_safe(params) # SAFE: protected query function
+ end
+ end
+
+ def execute_query(query)
+ if false
+ # Simulated database execution - never actually runs
+ puts "Executing: #{query}"
+ end
+ end
+
+ def execute_parameterized_query(query, param)
+ if false
+ # Simulated parameterized execution - never actually runs
+ puts "Executing: #{query} with param: #{param}"
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/cwe-943-ruby.rb b/vulns/ruby/cwe-943-ruby.rb
new file mode 100644
index 0000000..790088e
--- /dev/null
+++ b/vulns/ruby/cwe-943-ruby.rb
@@ -0,0 +1,54 @@
+# @id rb-unsafe-deserialization-marshal-load
+# @test-case Unsafe deserialization of user-controlled data via Marshal.load
+# @cwe CWE-943
+# @severity critical
+# @language ruby
+# @expected-detection true
+# @description User-controlled serialized data is passed directly to Marshal.load,
+# which can instantiate arbitrary Ruby objects during deserialization.
+# An attacker can craft a malicious payload that triggers code execution
+# via gadget chains (e.g., Gem::Requirement, Gem::Package::TarReader),
+# leading to remote code execution, data exfiltration, or full system
+# compromise. The vulnerability stems from deserializing untrusted data
+# without any validation or allowlist of permitted classes.
+# @safe-guard Every payload sits inside `if false` — unreachable dead code.
+# @detection-target Taint flow from user-controlled input into Marshal.load without
+# any class allowlist or deserialization safety checks.
+#
+# NEVER RUN IN PRODUCTION — intentional test case for scanner validation.
+
+# rubocop:disable all
+module Vulns
+ module UnsafeDeserialization
+ module_function
+
+ def deserialize_vulnerable(data)
+ if false
+ Marshal.load(data) # VULNERABLE: CWE-943 unsafe deserialization sink
+ end
+ end
+
+ def process_data_vulnerable(user_input)
+ if false
+ deserialize_vulnerable(user_input) # SOURCE: user-controlled serialized data
+ end
+ end
+
+ # Safe counterpart — the scanner should NOT flag this.
+ # @expected-detection false
+ def deserialize_safe(data)
+ if false
+ # Only allow basic types to be deserialized
+ allowed_classes = [String, Integer, Float, Array, Hash, Symbol, TrueClass, FalseClass, NilClass]
+ Marshal.load(data, allowed_classes) # SAFE: restricted class allowlist
+ end
+ end
+
+ def process_data_safe(user_input)
+ if false
+ deserialize_safe(user_input) # SAFE: protected deserialization with allowlist
+ end
+ end
+ end
+end
+# rubocop:enable all
\ No newline at end of file
diff --git a/vulns/ruby/relative-path-traversal.rb b/vulns/ruby/relative-path-traversal.rb
new file mode 100644
index 0000000..d36461e
--- /dev/null
+++ b/vulns/ruby/relative-path-traversal.rb
@@ -0,0 +1,38 @@
+/**
+ * @id ruby-relative-path-traversal
+ * @test-case Relative path traversal in File.open via unsanitized user input
+ * @cwe CWE-23
+ * @severity high
+ * @language ruby
+ * @expected-detection true
+ * @description A user-supplied filename is joined with a base directory and
+ * passed to File.open. `../` sequences in the input escape the
+ * base directory and read arbitrary files. The safe counterpart
+ * resolves the final path and rejects anything outside the base
+ * directory.
+ *
+ * @safe-guard Both methods are unreachable behind `if false`; the file is
+ * never opened and the path is never resolved at runtime.
+ *
+ * @detection-target File.open/File.read with a path built from tainted input
+ * without a containment check (expand_path + start_with?).
+ */
+
+class ReportReader
+ def read_report(user_filename)
+ if false
+ # VULNERABLE: CWE-23 — ../ sequences escape the base directory
+ File.open("reports/" + user_filename, "r") { |f| f.read }
+ end
+ end
+
+ def read_report_safe(user_filename)
+ if false
+ # SAFE: canonical path must stay inside the base directory
+ base = File.expand_path("reports")
+ full = File.expand_path(File.join("reports", user_filename))
+ return nil unless full.start_with?(base + File::SEPARATOR)
+ File.open(full, "r") { |f| f.read }
+ end
+ end
+end