Skip to content

Commit 33228a7

Browse files
author
ConnorWhelan11
committed
feat(examples): add bb-edr agentic EDR example
Adds examples/bb-edr showing audit log -> triage loop and updates hello-secure-agent to use local @hushclaw/openclaw build.
1 parent 6b8827c commit 33228a7

File tree

18 files changed

+605
-12
lines changed

18 files changed

+605
-12
lines changed

docs/src/guides/openclaw-integration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ hushclaw policy lint .hush/policy.yaml
3737

3838
- OpenClaw plugin docs: `packages/hushclaw-openclaw/docs/`
3939
- OpenClaw plugin code: `packages/hushclaw-openclaw/src/`
40+
- Example (minimal wiring): `examples/hello-secure-agent/`
41+
- Example (agentic EDR triage loop): `examples/bb-edr/`

examples/bb-edr/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.hush/
2+
reports/
3+
state/
4+
node_modules/
5+

examples/bb-edr/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# bb-edr (Agentic EDR Example)
2+
3+
This example demonstrates an **agentic EDR-style loop** for OpenClaw agents:
4+
5+
1. **Detect**: record policy decisions (allowed/denied) as audit events
6+
2. **Triage**: summarize denied activity and group by guard
7+
3. **Respond**: write an incident report and optionally emit a simple blocklist artifact
8+
9+
It uses `@hushclaw/openclaw` as the policy engine + OpenClaw integration layer.
10+
11+
> This is a teaching example. It does **not** implement OS-level telemetry or syscall interception.
12+
13+
## Quick Start (no OpenClaw required)
14+
15+
```bash
16+
cd examples/bb-edr
17+
18+
# Validate the policy schema
19+
npm run policy:lint
20+
21+
# Generate a demo audit log from scenario.json
22+
npm run simulate
23+
24+
# Triage denied events into a report
25+
npm run triage
26+
27+
# Inspect denied events
28+
npm run audit:denied
29+
```
30+
31+
## Files
32+
33+
- `policy.yaml` — policy enforced by hushclaw
34+
- `scenario.json` — a small set of simulated tool actions
35+
- `simulate.js` — writes `.hush/audit.jsonl` from the scenario
36+
- `triage.js` — reads `.hush/audit.jsonl` and writes `reports/`
37+
- `openclaw.json` — OpenClaw configuration (enables `@hushclaw/openclaw` in **audit** mode)
38+
- `skills/edr-triage/SKILL.md` — how an OpenClaw triage agent should operate
39+
40+
## Using with OpenClaw
41+
42+
If you have OpenClaw installed, you can point an agent at the same audit log and policy:
43+
44+
```bash
45+
openclaw run --config ./openclaw.json
46+
```
47+
48+
Suggested prompts:
49+
50+
- “Read `.hush/audit.jsonl` and write a short incident report to `./reports/incident.md`.”
51+
- “Explain the denied events and recommend the smallest policy changes to allow only the legitimate ones.”
52+
53+
## Adapting this to your own agentic EDR
54+
55+
- Replace `scenario.json` with events generated from your real tool boundary (or your own telemetry).
56+
- Extend `triage.js` into a responder that creates structured tickets, enriches with context, and gates actions with `policy_check`.

examples/bb-edr/openclaw.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"$schema": "https://openclaw.dev/schemas/config.json",
3+
"name": "bb-edr",
4+
"version": "0.1.0",
5+
"description": "Agentic EDR-style example (hushclaw audit log -> triage agent)",
6+
7+
"agent": {
8+
"model": "gpt-4",
9+
"system_prompt": "You are an EDR triage agent. Use the available tools to read audit events, summarize suspicious activity, and propose a minimal, safe response.",
10+
"max_tokens": 4096,
11+
"temperature": 0.2
12+
},
13+
14+
"skills": [
15+
"./skills/edr-triage"
16+
],
17+
18+
"tools": {
19+
"builtin": [
20+
"read_file",
21+
"write_file",
22+
"list_directory"
23+
]
24+
},
25+
26+
"plugins": {
27+
"entries": {
28+
"@hushclaw/openclaw": {
29+
"enabled": true,
30+
"config": {
31+
"policy": "./policy.yaml",
32+
"mode": "audit",
33+
"logLevel": "info",
34+
"guards": {
35+
"forbidden_path": true,
36+
"egress": true,
37+
"secret_leak": true,
38+
"patch_integrity": true,
39+
"mcp_tool": false
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}
46+

examples/bb-edr/package.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "bb-edr",
3+
"version": "0.1.0",
4+
"private": true,
5+
"description": "Agentic EDR-style example for OpenClaw + hushclaw",
6+
"main": "simulate.js",
7+
"scripts": {
8+
"policy:lint": "node ./tools/hushclaw.js policy lint ./policy.yaml",
9+
"simulate": "node simulate.js",
10+
"triage": "node triage.js",
11+
"audit:denied": "node ./tools/hushclaw.js audit query --denied"
12+
},
13+
"keywords": [
14+
"openclaw",
15+
"hushclaw",
16+
"edr",
17+
"agentic",
18+
"security"
19+
],
20+
"license": "MIT",
21+
"dependencies": {}
22+
}

examples/bb-edr/policy.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Hushclaw/OpenClaw policy for the bb-edr example.
2+
#
3+
# This file is consumed by the @hushclaw/openclaw plugin (not the Rust `hushclaw::Policy` type).
4+
# Validate it with:
5+
# npx hushclaw policy lint ./policy.yaml
6+
7+
version: "hushclaw-v1.0"
8+
9+
filesystem:
10+
# Keep the EDR "response" actions contained to local folders.
11+
allowed_write_roots:
12+
- "./.hush"
13+
- "./reports"
14+
- "./state"
15+
forbidden_paths:
16+
- "~/.ssh"
17+
- "~/.aws"
18+
- "~/.gnupg"
19+
- ".env"
20+
- ".env.*"
21+
22+
egress:
23+
mode: allowlist
24+
allowed_domains:
25+
- "api.github.com"
26+
- "api.openai.com"
27+
denied_domains:
28+
- "*.onion"
29+
- "localhost"
30+
- "127.*"
31+
- "10.*"
32+
- "192.168.*"
33+
34+
execution:
35+
denied_patterns:
36+
- "rm\\s+(-rf?|--recursive)\\s+[/\\\\]"
37+
- "curl\\s+[^|]*\\|\\s*(bash|sh|zsh)"
38+
- "wget\\s+[^|]*\\|\\s*(bash|sh|zsh)"
39+
40+
on_violation: cancel
41+

examples/bb-edr/scenario.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"runId": "bb-edr-demo",
3+
"actions": [
4+
{
5+
"action": "file_read",
6+
"resource": "./README.md",
7+
"note": "Read local documentation"
8+
},
9+
{
10+
"action": "file_read",
11+
"resource": "~/.ssh/id_rsa",
12+
"note": "Simulated credential theft attempt"
13+
},
14+
{
15+
"action": "network",
16+
"resource": "https://api.github.com",
17+
"note": "Allowed egress to GitHub API"
18+
},
19+
{
20+
"action": "network",
21+
"resource": "https://evil.com/exfil",
22+
"note": "Simulated data exfiltration attempt"
23+
},
24+
{
25+
"action": "command",
26+
"resource": "ps aux",
27+
"note": "Process inventory (policy-only check)"
28+
},
29+
{
30+
"action": "command",
31+
"resource": "rm -rf /",
32+
"note": "Simulated destructive command"
33+
},
34+
{
35+
"action": "file_write",
36+
"resource": "./state/quarantine/evil.bin",
37+
"note": "Simulated quarantine action"
38+
}
39+
]
40+
}
41+

examples/bb-edr/simulate.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* bb-edr (simulation)
5+
*
6+
* Generates an example `.hush/audit.jsonl` log by simulating a handful of tool actions
7+
* (file reads/writes, egress, and commands), gating each one with hushclaw policy checks.
8+
*
9+
* This does NOT run OpenClaw. It demonstrates the data you can feed into an agentic EDR loop.
10+
*/
11+
12+
const fs = require('fs');
13+
const path = require('path');
14+
15+
const { importOpenclawSdk } = require('./tools/openclaw');
16+
17+
function loadScenario() {
18+
const raw = fs.readFileSync('./scenario.json', 'utf8');
19+
const parsed = JSON.parse(raw);
20+
21+
if (!parsed || typeof parsed !== 'object') {
22+
throw new Error('Invalid scenario.json');
23+
}
24+
if (!Array.isArray(parsed.actions)) {
25+
throw new Error('scenario.json must contain an "actions" array');
26+
}
27+
28+
return parsed;
29+
}
30+
31+
async function main() {
32+
const { checkPolicy, AuditStore } = await importOpenclawSdk();
33+
34+
const config = {
35+
policy: './policy.yaml',
36+
mode: 'deterministic',
37+
logLevel: 'error',
38+
};
39+
40+
const scenario = loadScenario();
41+
const runId = typeof scenario.runId === 'string' ? scenario.runId : 'bb-edr-demo';
42+
43+
const store = new AuditStore('.hush/audit.jsonl');
44+
store.clear();
45+
46+
console.log('bb-edr (Simulated Agent Activity)');
47+
console.log('================================\n');
48+
49+
for (const item of scenario.actions) {
50+
const action = item.action;
51+
const resource = item.resource;
52+
const note = typeof item.note === 'string' ? item.note : '';
53+
54+
if (typeof action !== 'string' || typeof resource !== 'string') {
55+
console.log(`[skip] invalid action entry: ${JSON.stringify(item)}`);
56+
continue;
57+
}
58+
59+
const decision = await checkPolicy(config, action, resource);
60+
61+
const status = decision.denied ? 'DENY' : decision.warn ? 'WARN' : 'ALLOW';
62+
const guard = decision.guard ? ` (${decision.guard})` : '';
63+
const reason = decision.reason ? ` - ${decision.reason}` : '';
64+
const noteSuffix = note ? ` # ${note}` : '';
65+
66+
console.log(`[hushclaw] ${status}: ${action} ${JSON.stringify(resource)}${guard}${reason}${noteSuffix}`);
67+
68+
store.append({
69+
type: action,
70+
resource,
71+
decision: decision.denied ? 'denied' : 'allowed',
72+
guard: decision.guard,
73+
reason: decision.reason,
74+
runId,
75+
});
76+
77+
// Optional side effect for the demo: create the "quarantine" file if policy allows it.
78+
if (action === 'file_write' && !decision.denied) {
79+
const absolute = path.resolve(resource);
80+
fs.mkdirSync(path.dirname(absolute), { recursive: true });
81+
fs.writeFileSync(absolute, `bb-edr quarantine artifact (${new Date().toISOString()})\n`);
82+
}
83+
}
84+
85+
console.log('\nWrote audit log: .hush/audit.jsonl');
86+
console.log('Next: npm run triage');
87+
}
88+
89+
main().catch((err) => {
90+
console.error(err);
91+
process.exit(1);
92+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# bb-edr: Triage Skill
2+
3+
Use this skill to turn hushclaw audit logs into an incident report and a minimal response plan.
4+
5+
## Inputs
6+
7+
- `.hush/audit.jsonl` (JSONL) — hushclaw audit events (allowed/denied, guard, reason).
8+
- `policy.yaml` — the active security policy.
9+
10+
## Task
11+
12+
1. Read and summarize the last ~50 audit events.
13+
2. Focus on **denied** events first:
14+
- Group by `guard` (e.g., `forbidden_path`, `egress`, `patch_integrity`)
15+
- Identify likely intent (misconfiguration vs. suspicious)
16+
3. Produce a short incident report:
17+
- What happened (timeline + key indicators)
18+
- Impact assessment (what was attempted, what was blocked)
19+
- Recommended response (least-privilege)
20+
4. If you propose any response action (writing files, changing config), **use `policy_check` first** and keep changes scoped to this project directory.
21+
22+
## Output
23+
24+
- Write `./reports/incident.md` containing the final report.
25+
26+
## Notes (important)
27+
28+
- hushclaw enforces at the **tool boundary**. It is not an OS sandbox.
29+
- If an operation is denied, treat it as a strong indicator of suspicious behavior or incorrect policy assumptions.
30+

examples/bb-edr/tools/hushclaw.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env node
2+
3+
const { runHushclawCli } = require('./openclaw');
4+
5+
function main() {
6+
const args = process.argv.slice(2);
7+
if (args.length === 0) {
8+
console.error('usage: node ./tools/hushclaw.js <command> [...args]');
9+
process.exit(2);
10+
}
11+
runHushclawCli(args);
12+
}
13+
14+
main();
15+

0 commit comments

Comments
 (0)