feat(protect): comprehensive demo/test rule gallery + pack-safety guard#66
Merged
Conversation
examples/protect/ — a runnable Verified Vulnerability Shielding demo against a REAL vulnerable dependency (lodash@4.17.11, CVE-2019-10744): exploit works unprotected → dry-run detects → block rejects the request before the sink → benign still served → response AWS-key redaction → egress SSRF block → proof line. No app redeploy, no token. rules.demo.json holds EXAMPLE rules for public CVEs only (clearly labeled) — NOT the production corpus, which is fetched per-site from the API at runtime. No secrets in-repo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…guard
Extend Tier-3 response-phase screening (secret-leak redaction / withhold)
beyond the fetch() path to the remaining server surfaces:
- runtime: expose `screenResponse(response)`; wire `{ screenResponses: true }`
into node() and express() (buffers the outgoing body, then redacts spans or
withholds via the response rules). Opt-in — buffering can delay a stream, and
bodies over 512 KiB pass through unscanned. fetch() now shares the same
screenResp() closure.
- supabase-guard: screen the forwarded upstream response through
protection.screenResponse (query results can leak secrets/PII). Fails open.
- types: add screenResponse + the screenResponses option; +8 tests
(tests/protect/response-guards.test.ts) covering node/express/Supabase
redact, block-withhold, non-text passthrough, dry-run, and opt-in gating.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ash) Pins lodash@4.17.11 so the end-to-end demo reproducibly installs the exact version CVE-2019-10744 targets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A loadable, self-validating showcase rule set for demo environments, plus a
hard guarantee that the demo's vulnerable dependency never ships to consumers.
- examples/protect/demo-rules.json: one bundle spanning all three phases —
request WAF (prototype pollution, path traversal, SQLi, XSS, command
injection, NoSQL injection, XXE, request-side SSRF), response leak (PII
email / credit-card redaction on top of the built-in secret rules), and
egress SSRF (blocklisted exfil host). Each rule carries an `_demo` block
{ exploit, benign } — generic PUBLIC signatures, NOT the production corpus.
- examples/protect/gallery.mjs + demo-runner.mjs: run the bundle live, one row
per rule (exploit blocked/redacted, benign allowed), grouped by phase. No
vulnerable dependency needed — runs anywhere with zero install.
- tests/protect/demo-rules.test.ts: asserts every demo rule blocks its exploit
and passes its benign (via the same runner, so gallery + test never drift).
- tests/pack-safety.test.ts + .npmignore: enforce that `npm pack` never ships
examples/ (or any lodash artifact). The package.json "files" allowlist
already excludes it; this makes the invariant fail CI if it's ever loosened.
370 tests pass, typecheck + build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Comprehensive demo and safety tests integrated with clear structure and comments. 🎯 Quality: 100% Elite · 📦 Size: Large — consider splitting if possible 📈 This month: Your 26th PR — above team average · Averaging Excellent |
Don't touch npmignore for field-test, outside my zone.
Do not touch field-test.
Document seeding the scaffolded src/integrations/patchstack/rules.json (the token-less guard fallback) with examples/protect/demo-rules.json via `patchstack-connect protect`, plus an honest what-fires-where matrix (write-path + response rows fire on a tasks app; path/cmd/SSRF need matching routes; egress needs egress:true in guard.ts). No change to the shipped CLI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lock-safe) The token-less fallback shipped a single stale placeholder rule (marked XSS, tied to a specific CVE id). Replace it with a small curated starter set that is safe to block by default — prototype pollution (structural), path traversal, internal/metadata SSRF, and XSS (<script>/onerror=/javascript:). Deliberately NOT the broad demo bundle: SQLi/command-injection/XXE regexes false-positive and this fallback blocks by default. For a many-class demonstration, seed the file from examples/protect/demo-rules.json (documented in that README). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lery # Conflicts: # examples/protect/README.md # examples/protect/package.json
…caffold guard - tests/pack-safety: stop shelling `npm pack --json` (its stdout format varies across npm 9/10/11 → node 18/20/22 in CI, which broke JSON.parse). Assert the authoritative inputs instead — the package.json "files" allowlist can't sweep in examples/, and .npmignore lists examples/ as a backstop. Deterministic, no subprocess, identical on every Node version. - scaffold guard.ts: enable `egress: true` so a real install screens the app's outbound calls for SSRF (blocks internal / cloud-metadata addresses; allows the app's own Supabase host via allowHosts). Previously dormant. - examples README: the egress-SSRF row now fires on a real install (no longer "add egress:true yourself"). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Author
|
/review |
ejntaylor
approved these changes
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #64.
Two things: a loadable demo rule set that showcases many vulnerability classes at once (for demo environments), and a hard guarantee that the demo's real vulnerable dependency never ships to consumers.
Demo gallery
examples/protect/demo-rules.json— one bundle spanning all three phases, each rule carrying an_demo{ exploit, benign }vector. Generic public signatures, clearly labeled NOT the production corpus.gallery.mjs+demo-runner.mjs— run it live (npm run gallery), one row per rule (exploit blocked/redacted, benign allowed), grouped by phase. No vulnerable dependency needed — runs anywhere, zero install.Never ships the vulnerable dep
The deep demo (
demo.mjs, #61) installs a reallodash@4.17.11(CVE-2019-10744). This PR makes sure that never reaches consumers:tests/pack-safety.test.tsasserts whatnpm packwould actually publish — fails CI ifexamples/(or any lodash artifact) ever enters the tarball..npmignoreexcludesexamples/as a backstop beneath the existingfilesallowlist.Confirmed today: the tarball is
dist/+ 3 docs +package.json— 0 examples/lodash files. No workspaces, andnode_modulesis gitignored, so a clone/install never pulls the vulnerable code either.Tests
Full suite 370 pass (+4: demo-rules ×2, pack-safety ×2), typecheck + build clean. The gallery and the test share one runner, so they can't drift.
🤖 Generated with Claude Code