A tax form that runs any JavaScript you type
- Target
- OWASP NodeGoat
- Duration
- 6m 05s
- Steps
- 10
- Agents
- Recon, Triage, Exploit, Fix
Sample runs against public, intentionally vulnerable apps. The vulnerabilities are real; timings and traces are illustrative.
Review this repo for anything exploitable. Trace user input end to end and ignore findings in tests and dead code.
- 00:03Recon
Indexed the repository
$ enforster scan ./NodeGoat --sast --sca
› Output
61 source files · Express 4 · MongoDB driver 58 raw findings from pattern rules
- 00:47Triage
Following request bodies into the contributions handler
preTax, afterTax and roth come straight from req.body and are passed to eval() in app/routes/contributions.js.
- 01:36Exploit
Confirmed code execution on the running app
POST /contributions preTax=res.end(require('fs').readdirSync('.').toString())› Output
Response body lists the app’s working directory
- 01:48TriageVerified
Verified: server-side JavaScript injection
Any logged-in user can run arbitrary code as the server process.
- 03:10Triage
Allocations filter is built with $where
The threshold parameter is concatenated into a MongoDB $where clause in app/data/allocations-dao.js.
- 03:34Exploit
Dumped every user’s allocations
GET /allocations/2?threshold=1';return 1 == '1
› Output
Allocations for all users returned
- 03:46TriageVerified
Verified: NoSQL injection exposes all users’ data
- 04:30TriageDismissed
Dismissed 52 findings
Unreachable helpers, test fixtures with fake keys, and dependency CVEs whose vulnerable functions are never called.
- 05:40Fix
Replaced eval with parseInt
- const preTax = eval(req.body.preTax);+ const preTax = parseInt(req.body.preTax, 10);
- 06:05Triage
Run complete: 2 verified, 52 dismissed
What it proved
- Critical
Server-side JavaScript injection via eval()
app/routes/contributions.js
- Proof
- preTax payload reads the server’s file system
- Fix
- Parse numbers with parseInt and validate the range
- High
NoSQL injection in allocations threshold
app/data/allocations-dao.js
- Proof
- threshold payload returns every user’s allocations
- Fix
- Replace $where with a typed query: { stocks: { $gt: Number(threshold) } }
A 30-minute demo with zero slides. Bring a repo, a domain or a cloud account and we’ll show you what’s actually exploitable, live.
Book a demo