CGTI Lite 646 Suricata rules + cross-platform management tool for OpenClaw/AI agent threat detection (open source)

Hi everyone,

I’ve been building a Suricata based detection and response tool specifically targeting the threats going after the OpenClaw AI agent ecosystem. Since it’s built entirely on Suricata and I’ve spent significant time on rule engineering, I wanted to share it here and get feedback from people who know the engine deeply.

Why this exists

Between January and March 2026, the OpenClaw ecosystem faced a concentrated wave of attacks:

  • ClawHavoc campaign — 1,184+ malicious skills distributed via ClawHub, delivering AMOS, Vidar, and GhostSocks infostealers
  • GhostClaw/GhostLoader RAT — distributed through typosquatted npm packages (@openclaw-ai/openclawai), exfiltrating data to GoFile.io via trackpipe.dev C2 (source: JFrog Security Research)
  • AMOS Stealer — macOS-focused infostealer harvesting openclaw.json, API keys, crypto wallets, and SSH credentials
  • 135,000+ exposed instances found on the public internet, many with zero authentication
  • 25 CVEs affecting OpenClaw components, up to CVSS 9.9 (sandbox escape, pre-auth RCE, command injection)

Existing rulesets (ET Open, ET Pro) don’t cover these because the attack surface is specific to AI agent ecosystems MCP protocol exploitation, WebSocket gateway attacks, AI skill supply chain poisoning, prompt injection delivery, etc. I couldn’t find Suricata rules covering any of these, so I built a dedicated ruleset.

What CGTI Lite is

646 active Suricata rules (662 total, 16 disabled by default) across 13 specialized rule files, plus a Python-based management tool. The rules work standalone with any Suricata installation the management tool is optional.

SID range: 9200001–9204419 no conflicts with ET, Stamus, or other community rulesets.

Rule categories

# File Active Coverage
01 oc-infostealer-c2.rules 67 AMOS, Vidar, GhostClaw, GhostSocks, DigitStealer TLS C2, HTTP beacons, JA3 fingerprints
02 oc-reverse-shell.rules 59 Bash, netcat, Python, Node.js, PowerShell, Go, Java reverse shells
03 oc-websocket-attack.rules 43 CVE-2026-25253 full kill-chain (5 phases), ClawJacked, WS log poisoning
04 oc-malicious-skill-download.rules 50 Malicious skill installs, typosquatting, supply-chain indicators
05 oc-data-exfiltration.rules 57 Exfil to Telegram Bot API, Discord webhooks, Slack, cloud storage, paste sites
06 oc-gateway-exposure.rules 42 Exposed gateway detection, scanner fingerprinting, lateral movement
07 oc-cryptostealer-activity.rules 41 Wallet theft, mining, seed phrase exfil, exchange API key theft
08 oc-mcp-security.rules 24 MCP endpoint SSRF, tool injection, credential exfil via MCP channels
09 oc-exploit-cve.rules 37 CVE-specific exploit signatures (base set)
10 oc-exploit-detection.rules 89 Extended CVE coverage 25 CVEs with full kill-chain detection
11 oc-threat-intel-ioc.rules 83 Threat intel IOCs, malicious publishers, supply-chain indicators
12 oc-dns-threat-detection.rules 34 DNS C2, DNS rebinding, typosquatting domains, mDNS recon
13 oc-tls-certificate-anomaly.rules 20 TLS MITM, TOFU attacks, JA3/JARM, self-signed cert anomalies

Rule design principles

I tried to follow what I’ve seen from high-quality Suricata rulesets. Feedback on whether I’m doing this right is genuinely welcome:

Dual indicator minimum: Every rule requires at least two independent content matches. No rules fire on a single content: string alone. For example, the AMOS Stealer TLS detection combines tls.sni with a specific IP range (91.92.242.0/24), not just one or the other.

Three confidence layers:

  • Layer 1 (priority 1): Known C2 IPs/domains, CVE exploit signatures, JA3/JARM fingerprints near-zero FP
  • Layer 2 (priority 2): Behavioral patterns, protocol anomalies, threshold-based detection
  • Layer 3 (priority 3): Heuristics, scanner detection, broad pattern matching

MITRE ATT&CK metadata on every rule:

metadata:malware_family GhostClaw, mitre_attack T1071.001,
         signature_severity Critical, false_positive Zero,
         created_at 2026_03_17;

Standard variables only: All rules use $HOME_NET, $EXTERNAL_NET, and $DNS_SERVERS no custom variables needed. Works with default suricata.yaml out of the box.

Tested on Suricata 6.0+ through 8.0.4.

False positive methodology

16 rules are disabled by default. Each has a # DISABLED-FP: comment explaining exactly why it fires on legitimate traffic and under what conditions it’s safe to re-enable. Some examples:

  • SID:9200872 — Python REPL detection disabled because REPL is a core OpenClaw feature
  • SID:9202610tools/call + exec matches legitimate MCP tools like execute_query
  • SID:9201070registry.npmjs.org DNS query fires on every npm install

All active rules were tested against common OpenClaw usage patterns: Discord/Slack integrations, Telegram Bot API, MCP filesystem tools, crypto trading bots, npm workflows. The README has a full tuning guide per use case.

Management tool

The rules are the core deliverable and work with any Suricata deployment. But the project also includes a cross-platform management tool (cgti_lite.py, single file, rich as the only dependency) that wraps Suricata with some useful automation:

IDS + IPS modes:

  • IDS: standard af-packet monitoring
  • IPS on Linux: automatic iptables NFQUEUE setup, in place alert→drop rule conversion (reverts on stop), nfq: section auto configured in suricata.yaml. Uses subprocess.Popen with os.setpgrp instead of Suricata’s -D flag to avoid the fork race condition with NFQ binding.

Enhanced Autoblock (DNS aware IP blocking):

This is the feature I’m most interested in getting feedback on. When monitoring eve.json in real-time, the autoblock system:

  1. Reads each alert from EVE
  2. For non DNS alerts: blocks source IP (inbound threats) and destination IP (outbound C2/exfil) via OS native firewall iptables -I on Linux, pfctl table on macOS, netsh advfirewall on Windows
  3. For DNS alerts: the destination IP is the DNS server (private IP should never be blocked). Instead, it extracts the queried domain from the alert signature, resolves it via system DNS to get the real IP(s), and blocks those resolved IPs. This way, a DNS alert for trackpipe.dev results in blocking the actual C2 server IP, not your DNS resolver.
  4. Severity filtering: configurable threshold (default: block severity 1-3, skip severity 4)
  5. Private IP protection: RFC1918, CGNAT, loopback, multicast, link-local addresses are never auto blocked
  6. Auto whitelists configured DNS servers from suricata.dns_servers config
  7. Bidirectional: every block creates both INPUT and OUTPUT firewall rules

Boot time autostart:

  • Linux: systemd unit (Type=oneshot + RemainAfterExit=yes). Handles the case where Ubuntu’s native suricata.service starts Suricata in IDS mode before CGTI runs — if IPS is configured, CGTI stops the IDS instance and restarts in NFQUEUE mode with full IPS setup.
  • macOS: launchd LaunchDaemon plist
  • Windows: Task Scheduler with VBS silent launcher (no console flash)

Interface is read from config at runtime, not baked into service files.

Other features: Live EVE monitoring with color-coded severity, rule enable/disable/reload by SID, IP block management with reason logging, log rotation detection, automatic Suricata installation wizard.

Example rules

GhostClaw RAT TLS C2:

alert tls $HOME_NET any -> $EXTERNAL_NET any (
  msg:"CGTI-OC GHOSTCLAW - TLS Connection to trackpipe.dev C2 Panel";
  flow:to_server,established;
  tls.sni; content:"trackpipe.dev"; nocase; isdataat:!1,relative;
  classtype:trojan-activity; priority:1;
  reference:url,research.jfrog.com/post/ghostclaw-unmasked/;
  sid:9200124; rev:1;
  metadata:malware_family GhostClaw, mitre_attack T1071.001,
           signature_severity Critical, false_positive Zero;
)

CVE-2026-25253 gatewayUrl token exfiltration (phase 1 of 5-phase kill-chain):

alert http $HOME_NET any -> $EXTERNAL_NET any (
  msg:"CGTI-OC CVE-2026-25253 Phase-1 gatewayUrl Token Exfil";
  flow:established,to_server;
  http.uri; content:"gatewayUrl=";
  http.uri; content:"token="; distance:0;
  classtype:trojan-activity; priority:1;
  reference:cve,2026-25253;
  sid:9200801; rev:1;
  metadata:mitre_attack T1528, cve CVE-2026-25253,
           signature_severity Critical, false_positive Low;
)

DNS C2 detection (triggers Enhanced Autoblock domain resolution):

alert dns $HOME_NET any -> any 53 (
  msg:"OPENCLAW DNS GhostClaw C2 - trackpipe.dev";
  dns.query; content:"trackpipe.dev"; nocase;
  fast_pattern; isdataat:!1,relative;
  classtype:trojan-activity; priority:1;
  reference:url,research.jfrog.com/post/ghostclaw-unmasked/;
  sid:9203942; rev:1;
  metadata:malware_family GhostClaw, category ghostclaw-c2;
)

Threat intelligence sources

All rules are built from published research not generated or guessed:

  • JFrog Security Research — GhostClaw/GhostLoader campaign
  • Huntress — AMOS Stealer analysis, GhostSocks/OpenClaw campaign
  • DepthFirst Security — CVE-2026-25253 kill-chain discovery
  • Koi Security — ClawHavoc campaign (1,184+ malicious skills)
  • Darktrace, Trend Micro, Ontinue — Vidar/AMOS distribution research
  • Bitsight TRACE — exposed MCP servers, 135K+ instance scanning
  • Hunt io — certificate analysis of 17,470+ exposed instances
  • abuse ch SSLBL — JA3 fingerprint database
  • MITRE ATT&CK — technique classification

Full attribution with reference URLs in every rule.

Links

I’d genuinely appreciate feedback on rule quality, structure, Suricata best practices I might be missing, or anything that could be improved. FP reports from anyone running OpenClaw in production would also be very valuable.

Thanks for reading and thanks to the Suricata community and OISF team for building the engine that makes all of this possible.