Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/VULNERABILITY_CATALOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ from each file's header comment, so this page cannot drift from the source.

## Totals

- **Test cases:** 113
- **Expected detections:** 113
- **`VULNERABLE:` markers:** 207 (individual lines a scanner should flag)
- **`SAFE:` markers:** 125 (lines a scanner must not flag — the false-positive control group)
- **Test cases:** 114
- **Expected detections:** 114
- **`VULNERABLE:` markers:** 210 (individual lines a scanner should flag)
- **`SAFE:` markers:** 127 (lines a scanner must not flag — the false-positive control group)
- **Languages:** 8 — dotenv, go, java, javascript, json, python, ruby, text
- **CWE categories:** 83 — CWE-20, CWE-22, CWE-78, CWE-79, CWE-89, CWE-90, CWE-94, CWE-95, CWE-113, CWE-117, CWE-129, CWE-190, CWE-201, CWE-203, CWE-208, CWE-209, CWE-256, CWE-287, CWE-288, CWE-291, CWE-295, CWE-306, CWE-307, CWE-319, CWE-321, CWE-326, CWE-327, CWE-329, CWE-330, CWE-338, CWE-345, CWE-346, CWE-347, CWE-352, CWE-362, CWE-377, CWE-384, CWE-400, CWE-434, CWE-441, CWE-460, CWE-472, CWE-475, CWE-480, CWE-488, CWE-489, CWE-502, CWE-506, CWE-509, CWE-512, CWE-521, CWE-525, CWE-532, CWE-598, CWE-601, CWE-602, CWE-611, CWE-613, CWE-614, CWE-620, CWE-639, CWE-640, CWE-643, CWE-681, CWE-693, CWE-759, CWE-776, CWE-798, CWE-835, CWE-862, CWE-863, CWE-915, CWE-916, CWE-918, CWE-922, CWE-942, CWE-943, CWE-1021, CWE-1236, CWE-1321, CWE-1333, CWE-1336, CWE-1357

Expand Down Expand Up @@ -104,6 +104,7 @@ counts as a detection. See `docs/SCANNER_INTEGRATION.md`.
| Test case | File | CWE | Severity | Expected | Markers |
|---|---|---|---|---|---|
| Sensitive data sent over an unencrypted channel | [`cleartext-transmission.py`](../vulns/python/cleartext-transmission.py) | CWE-319 | high | yes | 5 vuln / 1 safe |
| Session cookie missing Secure flag over HTTPS | [`cookie-without-secure.py`](../vulns/python/cookie-without-secure.py) | CWE-614 | medium | yes | 3 vuln / 2 safe |
| CSRF via missing anti-CSRF token on state-changing POST | [`csrf-missing-token.py`](../vulns/python/csrf-missing-token.py) | CWE-352 | high | yes | 3 vuln / 1 safe |
| 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 |
| Code injection via eval() on attacker-controlled input | [`eval-code-injection.py`](../vulns/python/eval-code-injection.py) | CWE-94 | critical | yes | 3 vuln / 1 safe |
Expand Down
34 changes: 30 additions & 4 deletions vulns/VULNERABILITY_CATALOG.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": 113,
"expected_detections": 113,
"vulnerable_markers": 207,
"safe_markers": 125,
"test_cases": 114,
"expected_detections": 114,
"vulnerable_markers": 210,
"safe_markers": 127,
"languages": [
"dotenv",
"go",
Expand Down Expand Up @@ -1593,6 +1593,32 @@
43
]
},
{
"id": "py-cookie-without-secure-flag",
"file": "vulns/python/cookie-without-secure.py",
"title": "Session cookie missing Secure flag over HTTPS",
"category": "python",
"language": "python",
"cwe": "CWE-614",
"cwes": [
"CWE-614"
],
"severity": "medium",
"expected_detection": true,
"description": "An application sets a session/auth cookie without the Secure",
"detection_target": "Flask response.set_cookie / starlette Response.set_cookie /",
"safe_guard": "All response construction wrapped in `if False:` (unreachable",
"attribution": "line",
"vulnerable_lines": [
29,
36,
43
],
"safe_lines": [
54,
65
]
},
{
"id": "py-csrf-missing-token",
"file": "vulns/python/csrf-missing-token.py",
Expand Down
67 changes: 67 additions & 0 deletions vulns/python/cookie-without-secure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
@id py-cookie-without-secure-flag
@test-case Session cookie missing Secure flag over HTTPS
@cwe CWE-614
@severity medium
@language python
@expected-detection true
@description An application sets a session/auth cookie without the Secure
attribute while running on HTTPS. A MITM on a downgraded or
mixed-content connection can read the cookie. The safe counterpart
always sets Secure (and HttpOnly, SameSite) on auth cookies.
Detection target is a Set-Cookie header where the name matches
session/auth patterns and Secure is absent.
@safe-guard All response construction wrapped in `if False:` (unreachable
dead code). No HTTP response is sent.
@detection-target Flask response.set_cookie / starlette Response.set_cookie /
django HttpResponse.set_cookie / fastapi Response.set_cookie
with a name like session*, auth*, token*, jwt*, sid, csrf*
AND secure=False (or omitted on an HTTPS-only app).

NEVER RUN IN PRODUCTION - intentional test case for scanner validation.
"""

from flask import Flask, make_response


def set_session_cookie_insecure(resp, session_id: str):
if False:
# VULNERABLE: CWE-614 - session cookie without Secure
resp.set_cookie("session_id", session_id, httponly=True, secure=False)
return resp


def set_auth_cookie_insecure(resp, token: str):
if False:
# VULNERABLE: CWE-614 - auth token cookie without Secure
resp.set_cookie("auth_token", token, httponly=True) # secure defaults False
return resp


def set_csrf_cookie_insecure(resp, csrf_token: str):
if False:
# VULNERABLE: CWE-614 - csrf cookie without Secure
resp.set_cookie("csrf_token", csrf_token, secure=False)
return resp


def set_session_cookie_secure(resp, session_id: str):
"""Safe counterpart - the scanner should NOT flag this.

@expected-detection false
"""
if False:
# SAFE: Secure + HttpOnly + SameSite
resp.set_cookie("session_id", session_id, httponly=True, secure=True, samesite="Lax")
return resp


def set_auth_cookie_secure(resp, token: str):
"""Safe counterpart - the scanner should NOT flag this.

@expected-detection false
"""
if False:
# SAFE: all hardening flags
resp.set_cookie("auth_token", token, httponly=True, secure=True, samesite="Strict")
return resp
Loading