Skip to content

Commit 88cb77c

Browse files
committed
feat: implement eBPF heuristics engine for Linux
- Add heuristic maps (heu_configs, heu_state, heu_binary_to_slots, etc.) to bpf_hooks.c - Implement execve argv matching + sliding window for rate-based heuristics - Add unlinkat, fchmodat, symlinkat tracepoints; fork bomb heuristic (HEU-SYS-001) - Add _apply_heuristics() in monitor.py with HEURISTIC_DEFINITIONS for 35 rules - Extend event_t with heu_slot; handle heuristic_alert/heuristic_block (action 4/5) - Comment out 15 deferred heuristics (path-based openat, write, connect, complex) - Add docs/ebpf_heuristics_implementation_plan.md Made-with: Cursor
1 parent 74c5eae commit 88cb77c

File tree

11 files changed

+2939
-407
lines changed

11 files changed

+2939
-407
lines changed

builder/compiler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def compile_linux_policy(rules: dict[str, Any]) -> dict[str, Any]:
4949
"blocked_paths": dict(rules.get("blocked_paths", {}).get("linux", {})),
5050
"deny_rules": {},
5151
"rule_metadata": dict(rules.get("rule_metadata", {})),
52+
"heuristics": dict(rules.get("heuristics", {})),
5253
}
5354

5455
for rule_id, rule in rules.get("custom_deny_rules", {}).get("linux", {}).items():
@@ -78,6 +79,7 @@ def compile_universal_policy(rules: dict[str, Any]) -> dict[str, Any]:
7879
"macos": dict(rules.get("custom_deny_rules", {}).get("macos", {})),
7980
},
8081
"rule_metadata": dict(rules.get("rule_metadata", {})),
82+
"heuristics": dict(rules.get("heuristics", {})),
8183
}
8284
return policy
8385

builder/master_rules.yaml

Lines changed: 626 additions & 156 deletions
Large diffs are not rendered by default.

builder/threat_aggregator.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ def _thrt_id(prefix: str, value: str) -> str:
3939
def fetch_feed(url: str = CLAWSEC_FEED_URL, timeout: int = 30) -> dict[str, Any]:
4040
"""Download and return the ClawSec advisory feed as a dict."""
4141
logger.info("Fetching ClawSec feed from %s", url)
42-
resp = requests.get(url, timeout=timeout)
43-
resp.raise_for_status()
44-
feed = resp.json()
45-
logger.info("Feed fetched — %d advisories", len(feed.get("advisories", [])))
46-
return feed
42+
try:
43+
resp = requests.get(url, timeout=timeout)
44+
resp.raise_for_status()
45+
feed = resp.json()
46+
logger.info("Feed fetched — %d advisories", len(feed.get("advisories", [])))
47+
return feed
48+
except Exception as e:
49+
logger.warning("Failed to fetch ClawSec feed: %s. Proceeding with local rules only.", e)
50+
return {"advisories": []}
4751

4852

4953
def parse_feed(feed: dict[str, Any]) -> dict[str, Any]:
@@ -105,6 +109,7 @@ def merge(master: dict[str, Any], feed_data: dict[str, Any]) -> dict[str, Any]:
105109
"affected_skills": list(feed_data.get("affected_skills", [])),
106110
"custom_deny_rules": master.get("custom_deny_rules", {}),
107111
"rule_metadata": dict(master.get("rule_metadata", {})),
112+
"heuristics": dict(master.get("heuristics", {})),
108113
}
109114

110115
# Merge blocked_paths per OS

0 commit comments

Comments
 (0)