Author, validate, and tune 0x13d::att&ck (Browser EDR) detection rules — right in your editor.
Detection rules for the 0x13d::att&ck browser EDR are declarative JSON,
interpreted by the engine and never executed as code. This extension is the authoring surface for them: schema
validation and completion as you type, plus a scenario harness that runs your rule against a labeled corpus
and tells you what it catches and what it wrongly trips — a tuning loop without leaving VS Code.
Features
- Visual builder (Blockly) or text — open any
*.attackrule.json as a drag-and-drop block workspace or
as JSON, both editing the same file and kept in sync. The blocks cover the full schema: every scope, the
all / any / not / leaf condition grammar with all operators, and every response.
- Schema validation + completion + hover for any
*.attackrule.json file — scopes, ops, response ids, and
the condition grammar, live as you type.
- Validate — the semantic checks a JSON Schema can't express (valid response ids, size/depth caps).
- Tune against the corpus — compiles the rule you're editing and runs it against the community scenario
corpus for its scope: how many known-malicious cases it catches, and any benign case it trips (false
positives). Narrow to kill an FP, broaden to catch a miss, re-run.
- Run scenario harness — the full community rule set vs. the corpus, per-technique detection / false-positive
report in a panel.
- A template command and an
attackrule snippet to start from.
Quick start
1. Install
Grab the .vsix from the _releases/vsix feed (or build
it with npm run package in apps/vscode), then:
code --install-extension 0x13d-attack-rule-builder-0.1.0.vsix
Or in VS Code: Extensions view → ⋯ → Install from VSIX….
2. Scaffold a rule
Command Palette (⌘⇧P / Ctrl⇧P) → “0x13d::att&ck: New rule from template”. Save it with a
.attackrule.json suffix — that's what turns on validation, completion, hover, and the Blockly builder.
Prefer blocks? With a .attackrule.json open, run “0x13d::att&ck: Open rule in Blockly builder”
(or Reopen Editor With… → 0x13d::att&ck Blockly rule builder) to drag the rule together visually. It
writes JSON back to the same file, so you can flip between the block view and the text view any time.
3. Understand the shape
A rule is a small JSON object. An authored rule is declarative data, not code — it matches a condition
against the raw browser signal (the engine interprets it, never evals it). Here's a working download rule:
{
"id": "user.flag-hta",
"name": "Flag .hta downloads",
"technique": "T1105",
"scope": "download",
"condition": { "field": "payload.filename", "op": "contains", "value": ".hta" },
"responses": ["alert", "cancelDownload"],
"enabled": true
}
A field is a dot-path over the signal — top-level name / scope / tabId / windowId, plus payload.*:
| scope |
payload fields you can match |
download |
payload.filename, payload.finalUrl, payload.mime, payload.referrer |
management |
payload.installType, payload.permissions (array), payload.hostPermissions (array), payload.name |
webNavigation |
payload.url, payload.transitionType |
cookie |
payload.cookie.name, payload.cookie.secure, payload.cookie.httpOnly, payload.cookie.sameSite, payload.cookie.session |
Stick to those four scopes — they have live signal sources in the community edition. webRequest / content
are reserved for the commercial edition; tab / window aren't wired.
Ops: eq ne exists in nin contains containsAny gt lt gte lte
Responses: alert · cancelDownload · closeTab · disableExtension · removeCookie (pick ones that fit the scope)
Nest conditions with all / any / not:
{
"id": "user.webmail-macro-doc",
"name": "Macro doc from webmail",
"technique": "T1566.001",
"scope": "download",
"condition": {
"all": [
{ "field": "payload.filename", "op": "contains", "value": ".docm" },
{ "field": "payload.referrer", "op": "contains", "value": "mail.google.com" }
]
},
"responses": ["alert"],
"enabled": true
}
(Limits: ≤ 32 KB, ≤ 200 condition nodes — enforced by the validator.)
4. Validate & tune
- “0x13d::att&ck: Validate rule in active editor” — semantic check.
- “0x13d::att&ck: Tune rule in active editor against the corpus” — runs your rule against the corpus cases
for its scope and shows detections + false positives. Your no-browser feedback loop.
5. Load it into the EDR
Rules run in the browser EDR extension (apps/extension), not this authoring tool:
- Load
apps/extension/dist/ unpacked in Chrome (chrome://extensions → Load unpacked).
- Open its Options page → “Add a rule” → paste your JSON → “Validate & add”.
To watch it fire, run the matching demo under targets/
and follow its runbook.
Commands
| Command |
What it does |
0x13d::att&ck: New rule from template |
Scaffold a starter rule (save as *.attackrule.json). |
0x13d::att&ck: Open rule in Blockly builder |
Open the active rule file in the visual block editor (text ↔ blocks). |
0x13d::att&ck: Validate rule in active editor |
Semantic validation of the open rule. |
0x13d::att&ck: Tune rule … against the corpus |
Compile + run the open rule vs. the corpus; detection / FP report. |
0x13d::att&ck: Run scenario harness … |
Full community rule set vs. the corpus; per-technique report. |
Screenshots
| Authoring |
Scenario report |
 |
 |
The images above are placeholders — real captures land in apps/vscode/media/.
Develop
npm install
npm run watch # esbuild rebuild loop → out/extension.js
# Press F5 in VS Code to launch an Extension Development Host with the extension loaded.
npm run typecheck # tsc --noEmit (esbuild doesn't type-check)
npm run package # → _releases/vsix/0x13d-attack-rule-builder-<version>.vsix
esbuild produces two self-contained bundles — out/extension.js (the extension host; workspace packages
inlined) and out/webview.js (the Blockly builder that runs in the custom-editor webview; Blockly inlined) —
so the .vsix carries no node_modules. The rule schema, corpus, and scenario runner are single-sourced from
@attack/rule-schema and 0x13d-attack-rules-community — never re-copied.
Links
License
AGPL-3.0-only. Fully open, fully functional.