Skip to content

Commit a2b875b

Browse files
committed
Streamline README, move technical details to ARCHITECTURE.md
1 parent b7ffa5d commit a2b875b

File tree

2 files changed

+280
-341
lines changed

2 files changed

+280
-341
lines changed

ARCHITECTURE.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# ClawEDR Architecture
2+
3+
## Project Layout
4+
5+
```
6+
clawedr/
7+
├── builder/ # THE FORGE — private build tools
8+
│ ├── threat_aggregator.py # Fetches ClawSec advisory feed
9+
│ ├── compiler.py # Compiles rules into kernel policies
10+
│ ├── master_rules.yaml # Manual overrides (source of truth, Rule IDs)
11+
│ ├── config.yaml # Forge environment config (VM host, etc.)
12+
│ └── tests/
13+
│ ├── test_mac_sb.py # macOS Seatbelt enforcement tests
14+
│ └── test_linux_bpf.py # Linux eBPF tests via OrbStack VM
15+
16+
├── deploy/ # THE REGISTRY — public artifacts
17+
│ ├── install.sh # One-liner OS-detecting dispatcher
18+
│ ├── compiled_policy.json # Universal policy (Rule IDs for both OSes)
19+
│ ├── linux/
20+
│ │ ├── bpf_hooks.c # eBPF tracepoint hooks (execve interception)
21+
│ │ ├── monitor.py # Shield daemon — hot-reloads BPF maps
22+
│ │ └── shield_linux.sh # Linux setup script (systemd integration)
23+
│ ├── macos/
24+
│ │ ├── clawedr.sb # Compiled Seatbelt LISP profile
25+
│ │ ├── log_tailer.py # Sandbox log monitor + alert dispatcher
26+
│ │ ├── apply_macos_policy.py # Runtime Seatbelt generator (applies exemptions)
27+
│ │ └── shield_mac.sh # macOS setup script
28+
│ ├── shared/
29+
│ │ ├── user_rules.py # Reads/writes ~/.clawedr/user_rules.yaml
30+
│ │ └── alert_dispatcher.py # Pushes alerts to OpenClaw chat
31+
│ └── dashboard/
32+
│ ├── app.py # FastAPI backend (alerts, rules, exemptions)
33+
│ └── templates/index.html # Browser-based dashboard UI
34+
35+
├── main.py # Forge CLI (sync / compile / test / publish)
36+
├── requirements-dev.txt # Forge-only Python dependencies
37+
└── .github/workflows/ci.yml # CI validation on push
38+
```
39+
40+
## Three-Component Architecture
41+
42+
### 1. The Forge (`builder/` + `main.py`)
43+
44+
The Forge runs on the developer's machine. It fetches threat intelligence, compiles kernel policies, validates them, and publishes to the Registry.
45+
46+
**`sync`** pulls the [ClawSec advisory feed](https://clawsec.prompt.security/advisories/feed.json), extracts `affected_skills`, `malicious_hashes`, and `blocked_domains`, and merges them with manual overrides in `builder/master_rules.yaml`. The result is cached at `builder/.merged_rules.json`.
47+
48+
**`compile`** reads the merged rules and produces:
49+
- `deploy/compiled_policy.json` — universal policy consumed by both platforms at runtime
50+
- `deploy/macos/clawedr.sb` — Seatbelt LISP profile with `deny` rules for every blocked path/executable
51+
52+
**`test`** runs `pytest builder/tests/` covering Seatbelt syntax validation, runtime enforcement, and Linux eBPF policy loading.
53+
54+
**`publish`** stages `deploy/`, commits, and pushes to GitHub.
55+
56+
### 2. The Registry (`deploy/`)
57+
58+
Public artifacts served over HTTPS from GitHub. End-users pull these via `install.sh`.
59+
60+
### 3. The Shield (end-user runtime)
61+
62+
Kernel-level enforcement daemon installed on end-user machines.
63+
64+
## Threat Intelligence Pipeline
65+
66+
```
67+
ClawSec Feed (community) master_rules.yaml (manual)
68+
├── affected_skills + ├── blocked_paths
69+
├── malicious_hashes + ├── blocked_domains
70+
└── blocked_domains + ├── blocked_executables
71+
└── custom_deny_rules
72+
73+
.merged_rules.json
74+
75+
┌──────────────┴──────────────┐
76+
│ │
77+
compiled_policy.json clawedr.sb
78+
(Linux) (macOS)
79+
```
80+
81+
Feed entries **add to** manual rules, never replace them.
82+
83+
## Shield: Linux (eBPF)
84+
85+
The Shield runs as a background daemon (`monitor.py`) that:
86+
87+
1. Loads `compiled_policy.json` into eBPF hash maps
88+
2. Auto-detects OpenClaw processes (gateway, agent, node) and tracks their entire process tree via BPF `fork`/`exit` hooks — only these processes are subject to policy enforcement
89+
3. Hooks `execve()` via BPF tracepoints — blocked executables spawned by OpenClaw receive `SIGKILL`
90+
4. Polls for policy file changes and **hot-reloads** BPF maps without restarting
91+
92+
Logs are written to both `/var/log/clawedr_monitor.log` and `journalctl -u clawedr-monitor`.
93+
94+
### Network Blocking
95+
96+
eBPF LSM `socket_connect` blocks connections at the kernel level (returns `-EPERM`). Requires `CONFIG_BPF_LSM=y` and `lsm=...,bpf` in the kernel cmdline. Falls back to tracepoint + SIGKILL if unavailable.
97+
98+
### Process Tracking Scope
99+
100+
ClawEDR only monitors OpenClaw (gateway, agent, node) and their descendants. Non-OpenClaw processes are never tracked. The install script sets `tools.exec.host=gateway` and `agents.defaults.sandbox.mode=off` in `~/.openclaw/openclaw.json` so that agent exec runs on the gateway host and is subject to blocking. Restart the gateway after install for the config to take effect.
101+
102+
### Anti-Tamper
103+
104+
Deny rules (LIN-030, LIN-031) block `kill`/`pkill`/`systemctl stop clawedr` when run by an OpenClaw descendant. They do not affect admin operations from a normal shell.
105+
106+
## Shield: macOS (Seatbelt)
107+
108+
1. `openclaw` wrapper runs the agent under `sandbox-exec -f clawedr.sb`
109+
2. The `.sb` profile denies file reads/writes to sensitive paths (`~/.ssh`, `~/.gnupg`, `~/.aws`, `~/Library/Keychains`)
110+
3. `log_tailer.py` monitors sandbox violation events and dispatches alerts
111+
112+
Seatbelt profiles bind at process start and cannot be hot-reloaded. Logs appear in Console.app (subsystem `com.clawedr.shield`) or `/tmp/clawedr_log_tailer.log`.
113+
114+
**macOS note:** Ensure `/usr/local/bin` comes before `/opt/homebrew/bin` in PATH. Verify with: `sandbox-exec -f /usr/local/share/clawedr/clawedr.sb -- nc -h` (should fail with "Operation not permitted").
115+
116+
## Dashboard
117+
118+
Web UI on port 8477, auto-installed as a system service on both platforms.
119+
120+
### Features
121+
122+
- **Alerts** — Real-time blocked actions with Rule IDs. Click "Exempt" to bypass a rule.
123+
- **Policy Rules** — Browse all active rules by category. Toggle exemptions inline. Add/edit/delete custom rules.
124+
- **Platform filtering** — Auto-detects OS, pill bar to switch views.
125+
- **Sessions** — Active OpenClaw instances being monitored.
126+
- **Settings** — Auto-update toggle, manual update check.
127+
- **Rule updates** — Hourly registry checks. Linux: auto-enforced via hot-reload. macOS: banner prompts restart.
128+
129+
### API Reference
130+
131+
| Method | Path | Description |
132+
|--------|------|-------------|
133+
| `GET` | `/api/status` | Shield health: OS, policy state, OpenClaw availability |
134+
| `GET` | `/api/alerts` | Recent blocked actions parsed from logs |
135+
| `GET` | `/api/rules` | Full compiled policy with Rule IDs |
136+
| `GET` | `/api/user-rules` | Current user exemptions and custom rules |
137+
| `POST` | `/api/user-rules` | Update exemptions (preserves custom rules) |
138+
| `GET` | `/api/custom-rules` | List all user-defined custom rules |
139+
| `POST` | `/api/custom-rules` | Add a custom rule (`{"type": "domain", "value": "evil.com", "platform": "both"}`) |
140+
| `PUT` | `/api/custom-rules/{id}` | Update a custom rule |
141+
| `DELETE` | `/api/custom-rules/{id}` | Delete a custom rule |
142+
| `GET` | `/api/sessions` | Active OpenClaw sessions |
143+
| `GET` | `/api/settings` | Dashboard settings |
144+
| `POST` | `/api/settings` | Update settings |
145+
| `GET` | `/api/updates` | Check for rule updates from registry |
146+
| `POST` | `/api/updates/apply` | Download and apply updates |
147+
148+
### Service Management
149+
150+
```sh
151+
# macOS
152+
sudo launchctl unload /Library/LaunchDaemons/com.clawedr.dashboard.plist # stop
153+
sudo launchctl load -w /Library/LaunchDaemons/com.clawedr.dashboard.plist # start
154+
cat /tmp/clawedr_dashboard.log
155+
156+
# Linux
157+
sudo systemctl stop clawedr-dashboard
158+
sudo systemctl start clawedr-dashboard
159+
sudo journalctl -u clawedr-dashboard -f
160+
```
161+
162+
## User Rules
163+
164+
All customizations in `~/.clawedr/user_rules.yaml` survive system updates.
165+
166+
### Exemptions
167+
168+
```yaml
169+
exempted_rule_ids:
170+
- "BIN-001" # Allow nc
171+
- "LIN-004" # Allow stratum+tcp
172+
```
173+
174+
### Custom Rules
175+
176+
```yaml
177+
custom_rules:
178+
- id: USR-BIN-001
179+
type: executable
180+
value: terraform
181+
- id: USR-DOM-001
182+
type: domain
183+
value: evil.com
184+
- id: USR-HASH-001
185+
type: hash
186+
value: "sha256:a1b2c3d4e5f6..."
187+
- id: USR-PATH-001
188+
type: path
189+
value: /var/secrets
190+
platform: linux
191+
- id: USR-ARG-001
192+
type: argument
193+
value: "--password"
194+
```
195+
196+
| Type | Blocks | Validation |
197+
|------|--------|------------|
198+
| `executable` | Binary by name | No paths, no protected binaries |
199+
| `domain` | Domain name or IP | RFC-compliant, rejects URLs |
200+
| `hash` | SHA-256 file hash | 64 hex chars, optional `sha256:` prefix |
201+
| `path` | File/directory access | Absolute or `~/`, cannot be root |
202+
| `argument` | Command-line args (regex) | Must be valid regex |
203+
204+
**Linux:** Custom rules merge into BPF maps on every policy reload (hot-reloaded).
205+
**macOS:** `apply_macos_policy.py` rebuilds `clawedr.sb` including custom rules. Requires agent restart.
206+
207+
## Testing
208+
209+
| Test | Platform | Validates |
210+
|------|----------|-----------|
211+
| Profile syntax | macOS | `.sb` file has valid Seatbelt directives |
212+
| Blocked path enforcement | macOS | `sandbox-exec` denies reads to `~/.ssh` |
213+
| Allowed commands | macOS | Benign commands work under sandbox |
214+
| VM SSH connectivity | Linux | SSH to the test VM works |
215+
| BCC availability | Linux | Python BCC bindings importable |
216+
| Policy loading | Linux | `compiled_policy.json` parses correctly |
217+
| Blocked executable | Linux | `nc` appears in blocked list |
218+
219+
Configure the Linux test VM in `builder/config.yaml`:
220+
221+
```yaml
222+
linux_vm:
223+
host: "orb"
224+
user: "ubuntu"
225+
```
226+
227+
## CI
228+
229+
GitHub Actions (`.github/workflows/ci.yml`) runs on every push to `main`:
230+
231+
1. Installs Python dependencies
232+
2. Compiles policies from `master_rules.yaml`
233+
3. Verifies `deploy/` artifacts exist
234+
4. Runs unit tests (skips platform-specific enforcement tests)

0 commit comments

Comments
 (0)