Skip to content

Commit 5cc27fb

Browse files
feat(protect): refresh the scaffold fallback rules (high-precision, block-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>
1 parent 6f1daa8 commit 5cc27fb

1 file changed

Lines changed: 34 additions & 7 deletions

File tree

src/protect/templates/rules.json

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,44 @@
11
{
2-
"_comment": "Demo fallback rules — used only when PATCHSTACK_WAF_TOKEN is unset. In production the guard fetches per-site rules from the Patchstack API (api.patchstack.com/api/get-rules/3, cached to disk). CVE id is representative until aligned with the real corpus.",
2+
"_comment": "Starter fallback rules — used ONLY when PATCHSTACK_WAF_TOKEN is unset. The guard blocks by default, so these are deliberately HIGH-PRECISION signatures (structural markers legitimate traffic doesn't carry) to avoid false positives before a token is configured. Once a token is set the guard fetches the per-site, version-scoped corpus from the Patchstack API (api.patchstack.com/api/get-rules/3, cached to disk) and this file is no longer used. For a broad, many-class DEMONSTRATION (SQLi/XSS/XXE/SSRF/PII/…), seed this file from examples/protect/demo-rules.json — see that folder's README.",
33
"firewall": [
44
{
5-
"id": "rm-npm-0001",
6-
"title": "Block stored XSS via vulnerable markdown renderer (marked)",
7-
"vulnerability_id": "CVE-2022-21681",
5+
"id": "ps-fallback-proto-pollution",
6+
"title": "Prototype pollution in request body",
7+
"category": "prototype-pollution",
88
"rule_v2": [
9+
{ "parameter": "raw", "mutations": ["urldecode"], "match": { "type": "contains", "value": "__proto__" } },
910
{
10-
"parameter": "post.title",
11-
"mutations": ["urldecode"],
12-
"match": { "type": "inline_xss" }
11+
"parameter": "rules",
12+
"rules": [
13+
{ "parameter": "raw", "mutations": ["urldecode"], "match": { "type": "contains", "value": "constructor" }, "inclusive": true },
14+
{ "parameter": "raw", "mutations": ["urldecode"], "match": { "type": "contains", "value": "prototype" }, "inclusive": true }
15+
]
1316
}
1417
]
18+
},
19+
{
20+
"id": "ps-fallback-path-traversal",
21+
"title": "Path traversal in a file/path parameter",
22+
"category": "lfi",
23+
"rule_v2": [
24+
{ "parameter": ["get.file", "post.file", "raw.file", "get.path", "post.path"], "mutations": ["urldecode"], "match": { "type": "contains", "value": ".." } }
25+
]
26+
},
27+
{
28+
"id": "ps-fallback-ssrf-internal",
29+
"title": "SSRF via a url parameter pointing at an internal/metadata address",
30+
"category": "ssrf",
31+
"rule_v2": [
32+
{ "parameter": ["get.url", "post.url", "raw.url"], "mutations": ["urldecode"], "match": { "type": "regex", "value": "/localhost|127\\.0\\.0\\.1|169\\.254\\.169\\.254|::1|metadata\\.google/i" } }
33+
]
34+
},
35+
{
36+
"id": "ps-fallback-xss",
37+
"title": "Stored/reflected XSS in a text field",
38+
"category": "xss",
39+
"rule_v2": [
40+
{ "parameter": ["post.title", "post.comment", "post.body"], "mutations": ["urldecode", "htmlentitydecode"], "match": { "type": "regex", "value": "/<script\\b|onerror\\s*=|javascript:/i" } }
41+
]
1542
}
1643
],
1744
"whitelists": [],

0 commit comments

Comments
 (0)