node720-rasp · in-process runtime self-protection
node720-rasp enforces at the dangerous call — inside your Node process, no sidecar, no proxy. The same detector core as the SAST engine, now deciding the moment a sink fires. Add it with one env var; every block ships with the real exploit that proves it.
node720-rasp loads before your app and wraps the dangerous sinks in-process. No diff to your source, no sidecar container, no network hop. Point Node at the bootstrap:
exec, query, deserialize — not by guessing at a proxy or WAF in front.AsyncLocalStorage to the sink, so a value slot passes and a structural span is blocked.RaspBlockError on a hit; tune or disable per detector.A RASP claim is only worth the exploit behind it. We keep two numbers apart on purpose: what is exploit-proven (a real attack fired, a block asserted) versus what is mapped in the coverage census. They are not the same thing, and blending them would hide the only one that matters: did a real exploit actually get stopped?
A · PROVEN — 27 executed gold fixtures
Each detection ships with a gold fixture that runs in CI: fire the real attack → assert it blocks → assert the benign twin passes. No fixture, no credit. This is the honest, reproducible floor of what node720-rasp stops:
B · CENSUS — coverage of the CVE landscape
A wider manifest of the Node.js CVE landscape, scored by whether an in-process RASP can reach the class at all. This is a mapped/wrapped count — broader than the 27 exploit-proven fixtures, and we label it that way:
// The two are kept separate on purpose. The census 599 is a mapped/wrapped count, not 599 executed exploits — only the 27 gold fixtures are fire-and-block proven in CI. We never credit a census block without either a gold fixture or a clean detector mapping, and 398 CVEs are fundamental (logic/design flaws with no dangerous call to intercept) — honestly out of reach for any in-process RASP. The headline is the 27; the 84% is the map. Census manifest: threat-intel/coverage-360.json; gold fixtures: test/cve-*.test.js.
Two headline blocks that a static scan can't make — a Cypher injection stopped at the graph driver, and a tar symlink-chain that only a per-archive state machine can catch — then the full ledger of detector → the real CVE it blocks in CI.
req.body.label contained per-requestRaspBlockErrorThe escape isn't in any single entry — it's the relationship between two. A file scanner sees one entry at a time and finds nothing wrong.
node720-rasp keeps a per-archive state machine (the symlink graph) and re-canonicalizes each entry through the links committed so far. Entry 2 resolves outside the root → blocked. This is a runtime-only capability — the kind of block that justifies an in-process RASP.
The full ledger — detector → the real CVE it blocks, gold-proven in CI:
169.254.169.254 cloud-metadata is blocked at the egress call, host and route.({})[k] dispatch — the prototype gadget is blocked before it dispatches.query() on mssql / Prisma $queryRaw / ClickHouse — value slot passes, keyword/operator is blocked.exec argv from request data — the tainted argument vector is blocked at the spawn.session.run — a tainted span in pattern position (label/relationship), not a parameter, is blocked as query structure...%2f..%2f segment the WHATWG parser keeps opaque but an upstream decodes — node720 decodes & normalizes, blocks the route climbing above the committed prefix.node720-rasp is the same detector core as the SAST engine, now deciding in-process at the dangerous sink. One env var, no code change, version-gated virtual patching — and every block ships with the exploit that proves it.
→ Full install & CI setup → The same core, as SAST → Watch one detector think