OWASP PyGoat
Django app demonstrating OWASP Top 10 vulnerabilities in Python.
- Upstream: https://github.com/adeyosemanputra/pygoat
- Pinned commit:
c11e8429349cc05ff38564d3bf7ef09fb2411874 - Reference: v2.0.1 release tag
- Baseline scan date: 2026-05-17
- Re-verified: 2026-09-16 against BrassCoders 2.0.16 — all 4 previously-documented gaps below are now caught (see “Closed since baseline”). No new gaps found in this pass, though this pass didn’t attempt a fresh line-by-line audit of PyGoat’s full documented vulnerability set beyond the 11 entries already tracked here.
Vulnerabilities brass detects
These are the specific lines brass catches in this codebase. Re-running brass at the pinned commit reproduces each one. 11 required findings:
| File | Line | Category | Detected by | CWE / Bandit ID |
|---|---|---|---|---|
introduction/views.py | 857 | hardcoded_credential | auth_pattern_analyzer | Hardcoded Credentials (CWE-798) |
introduction/views.py | 859 | hardcoded_credential | auth_pattern_analyzer | Hardcoded Credentials (CWE-798) |
introduction/views.py | 861 | hardcoded_credential | auth_pattern_analyzer | Hardcoded Credentials (CWE-798) |
introduction/views.py | 863 | hardcoded_credential | auth_pattern_analyzer | Hardcoded Credentials (CWE-798) |
introduction/views.py | 529 | hardcoded_credential | SecretsScanner | Hardcoded secret keyword in source (CWE-798) |
introduction/views.py | 423 | command_injection | bandit | OS Command Injection via subprocess shell=True (CWE-78, Bandit B602) |
introduction/views.py | 1017 | weak_crypto | bandit | Weak Hash: MD5 (CWE-327, Bandit B324) |
introduction/views.py | 421 | command_injection | SemgrepTaintScanner | Tainted dataflow: command injection (CWE-78) |
introduction/views.py | 155 | sql_injection | bandit | Possible SQL injection vector via string-based query construction (CWE-89) |
introduction/views.py | 211 | deserialization | bandit | Unsafe pickle deserialization of untrusted data (CWE-502) |
introduction/views.py | 451 | code_injection | bandit | Use of eval() — consider ast.literal_eval (CWE-95) |
Closed since baseline (2026-05-17 → 2026-09-16)
The four rows above detected by SemgrepTaintScanner/bandit at lines 421, 155, 211, and 451 were published as gaps in the original 2026-05-17 baseline — documented vulnerabilities BrassCoders didn’t yet catch. A re-scan against the same pinned commit on 2026-09-16 (BrassCoders 2.0.16) found all four now detected, three at high severity and the taint-tracked command injection at critical. The SQL-injection catch carries LOW-to-medium confidence (bandit confidence 0.65) — worth a second look before triage, not a certainty on the label alone.
Reproduce locally
git clone https://github.com/adeyosemanputra/pygoat.git project
cd project && git checkout c11e8429349cc05ff38564d3bf7ef09fb2411874
brasscoders --offline scan .
Then check .brass/detailed_analysis.yaml for the listed findings.