From f149cc248a09f575be71f3077a4638cfc6076b70 Mon Sep 17 00:00:00 2001 From: 0xbeekeeper Date: Sat, 7 Mar 2026 15:02:18 +0900 Subject: [PATCH] feat: add patrol subcommand for OpenClaw daily security patrol - Add `patrol` (run/setup/status) subcommand to SKILL.md for OpenClaw-specific daily security patrols covering 8 automated checks: skill integrity, secrets exposure, network exposure, cron audit, filesystem changes, audit log analysis, environment config, and trust registry health - Create patrol-checks.md with detailed check definitions, commands, and thresholds - Restructure SKILL.md into logical sections (Security Operations / Trust & Config / Reporting) - Add workspacePaths option to OpenClawPluginOptions so host platforms can declare workspace boundaries without manual registry edits - Extend createAgentGuard() to accept defaultCapabilities parameter - Update CLAUDE.md with patrol subcommand documentation Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 3 +- skills/agentguard/SKILL.md | 290 ++++++++++++++++++++++--- skills/agentguard/patrol-checks.md | 334 +++++++++++++++++++++++++++++ src/adapters/openclaw-plugin.ts | 26 ++- src/index.ts | 8 +- 5 files changed, 620 insertions(+), 41 deletions(-) create mode 100644 skills/agentguard/patrol-checks.md diff --git a/CLAUDE.md b/CLAUDE.md index f5c2b94..c4c1810 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,8 +7,9 @@ Security framework for AI agents. Provides code scanning, runtime action evaluat This project provides a unified Claude Code skill: `/agentguard` ``` -/agentguard scan — Scan code for security risks (20 detection rules) +/agentguard scan — Scan code for security risks (24 detection rules) /agentguard action — Evaluate runtime action safety (allow/deny/confirm) +/agentguard patrol [run|setup|status] — Daily security patrol for OpenClaw environments /agentguard trust — Manage skill trust levels (lookup/attest/revoke/list) /agentguard report — View security event audit log /agentguard config — Set protection level (strict/balanced/permissive) diff --git a/skills/agentguard/SKILL.md b/skills/agentguard/SKILL.md index acdfd62..144602e 100644 --- a/skills/agentguard/SKILL.md +++ b/skills/agentguard/SKILL.md @@ -1,15 +1,15 @@ --- name: agentguard -description: GoPlus AgentGuard — AI agent security guard. Automatically blocks dangerous commands, prevents data leaks, and protects secrets. Use when reviewing third-party code, auditing skills, checking for vulnerabilities, evaluating action safety, or viewing security logs. +description: GoPlus AgentGuard — AI agent security guard. Automatically blocks dangerous commands, prevents data leaks, and protects secrets. Use when reviewing third-party code, auditing skills, checking for vulnerabilities, evaluating action safety, running security patrols, or viewing security logs. license: MIT compatibility: Requires Node.js 18+. Optional GoPlus API credentials for enhanced Web3 simulation. metadata: author: GoPlusSecurity - version: "1.0" + version: "1.1" optional_env: "GOPLUS_API_KEY, GOPLUS_API_SECRET (for Web3 transaction simulation only)" user-invocable: true -allowed-tools: Read, Grep, Glob, Bash(node scripts/trust-cli.ts *) Bash(node scripts/action-cli.ts *) -argument-hint: "[scan|action|trust|report|config] [args...]" +allowed-tools: Read, Grep, Glob, Bash(node scripts/trust-cli.ts *) Bash(node scripts/action-cli.ts *) Bash(openclaw *) Bash(ss *) Bash(lsof *) Bash(ufw *) Bash(iptables *) Bash(crontab *) Bash(systemctl list-timers *) Bash(find *) Bash(stat *) Bash(env) Bash(sha256sum *) +argument-hint: "[scan|action|patrol|trust|report|config] [args...]" --- # GoPlus AgentGuard — AI Agent Security Framework @@ -22,6 +22,7 @@ Parse `$ARGUMENTS` to determine the subcommand: - **`scan `** — Scan a skill or codebase for security risks - **`action `** — Evaluate whether a runtime action is safe +- **`patrol [run|setup|status]`** — Daily security patrol for OpenClaw environments - **`trust [args]`** — Manage skill trust levels - **`report`** — View recent security events from the audit log - **`config `** — Set protection level @@ -30,6 +31,8 @@ If no subcommand is given, or the first argument is a path, default to **scan**. --- +# Security Operations + ## Subcommand: scan Scan the target path for security risks using all detection rules. @@ -220,6 +223,227 @@ Always combine script results with the policy-based checks (webhook domains, sec --- +## Subcommand: patrol + +**OpenClaw-specific daily security patrol.** Runs 8 automated checks that leverage AgentGuard's scan engine, trust registry, and audit log to assess the security posture of an OpenClaw deployment. + +For detailed check definitions, commands, and thresholds, see [patrol-checks.md](patrol-checks.md). + +### Sub-subcommands + +- **`patrol`** or **`patrol run`** — Execute all 8 checks and output a patrol report +- **`patrol setup`** — Configure as an OpenClaw daily cron job +- **`patrol status`** — Show last patrol results and cron schedule + +### Pre-flight: OpenClaw Detection + +Before running any checks, verify the OpenClaw environment: + +1. Check for `$OPENCLAW_STATE_DIR` env var, fall back to `~/.openclaw/` +2. Verify the directory exists and contains `openclaw.json` +3. Check if `openclaw` CLI is available in PATH + +If OpenClaw is not detected, output: +``` +This command requires an OpenClaw environment. Detected: +For non-OpenClaw environments, use /agentguard scan and /agentguard report instead. +``` + +Set `$OC` to the resolved OpenClaw state directory for all subsequent checks. + +### The 8 Patrol Checks + +#### [1] Skill/Plugin Integrity + +Detect tampered or unregistered skill packages by comparing file hashes against the trust registry. + +**Steps**: +1. Discover skill directories under `$OC/skills/` (look for dirs containing `SKILL.md`) +2. For each skill, compute hash: `node scripts/trust-cli.ts hash --path ` +3. Look up the attested hash: `node scripts/trust-cli.ts lookup --source ` +4. If hash differs from attested → **INTEGRITY_DRIFT** (HIGH) +5. If skill has no trust record → **UNREGISTERED_SKILL** (MEDIUM) +6. For drifted skills, run the scan rules against the changed files to detect new threats + +#### [2] Secrets Exposure + +Scan workspace files for leaked secrets using AgentGuard's own detection patterns. + +**Steps**: +1. Use Grep to scan `$OC/workspace/` (especially `memory/` and `logs/`) with patterns from: + - scan-rules.md Rule 7 (PRIVATE_KEY_PATTERN): `0x[a-fA-F0-9]{64}` in quotes + - scan-rules.md Rule 8 (MNEMONIC_PATTERN): BIP-39 word sequences, `seed_phrase`, `mnemonic` + - scan-rules.md Rule 5 (READ_SSH_KEYS): SSH key file references in workspace + - action-policies.md secret patterns: AWS keys (`AKIA...`), GitHub tokens (`gh[pousr]_...`), DB connection strings +2. Scan any `.env*` files under `$OC/` for plaintext credentials +3. Check `~/.ssh/` and `~/.gnupg/` directory permissions (should be 700) + +#### [3] Network Exposure + +Detect dangerous port exposure and firewall misconfigurations. + +**Steps**: +1. List listening ports: `ss -tlnp` or `lsof -i -P -n | grep LISTEN` +2. Flag high-risk services on 0.0.0.0: Redis(6379), Docker API(2375), MySQL(3306), PostgreSQL(5432), MongoDB(27017) +3. Check firewall status: `ufw status` or `iptables -L INPUT -n` +4. Check outbound connections (`ss -tnp state established`) and cross-reference against action-policies.md webhook/exfil domain list and high-risk TLDs + +#### [4] Cron & Scheduled Tasks + +Audit all cron jobs for download-and-execute patterns. + +**Steps**: +1. List OpenClaw cron jobs: `openclaw cron list` +2. List system crontab: `crontab -l` and contents of `/etc/cron.d/` +3. List systemd timers: `systemctl list-timers --all` +4. Scan all cron command bodies using scan-rules.md Rule 2 (AUTO_UPDATE) patterns: `curl|bash`, `wget|sh`, `eval "$(curl`, `base64 -d | bash` +5. Flag unknown cron jobs that touch `$OC/` directories + +#### [5] File System Changes (24h) + +Detect suspicious file modifications in the last 24 hours. + +**Steps**: +1. Find recently modified files: `find $OC/ ~/.ssh/ ~/.gnupg/ /etc/cron.d/ -type f -mtime -1` +2. For modified files with scannable extensions (.js/.ts/.py/.sh/.md/.json), run the full scan rule set +3. Check permissions on critical files: + - `$OC/openclaw.json` → should be 600 + - `$OC/devices/paired.json` → should be 600 + - `~/.ssh/authorized_keys` → should be 600 +4. Detect new executable files in workspace: `find $OC/workspace/ -type f -perm +111 -mtime -1` + +#### [6] Audit Log Analysis (24h) + +Analyze AgentGuard's audit trail for attack patterns. + +**Steps**: +1. Read `~/.agentguard/audit.jsonl`, filter to last 24h by timestamp +2. Compute statistics: total events, deny/confirm/allow counts, group denials by `risk_tags` and `initiating_skill` +3. Flag patterns: + - Same skill denied 3+ times → potential attack (HIGH) + - Any event with `risk_level: critical` → (CRITICAL) + - `WEBHOOK_EXFIL` or `NET_EXFIL_UNRESTRICTED` tags → (HIGH) + - `PROMPT_INJECTION` tag → (CRITICAL) +4. For skills with high deny rates still not revoked: recommend `/agentguard trust revoke` + +#### [7] Environment & Configuration + +Verify security configuration is production-appropriate. + +**Steps**: +1. List environment variables matching sensitive names (values masked): `API_KEY`, `SECRET`, `PASSWORD`, `TOKEN`, `PRIVATE`, `CREDENTIAL` +2. Check if `GOPLUS_API_KEY`/`GOPLUS_API_SECRET` are configured (if Web3 features are in use) +3. Read `~/.agentguard/config.json` — flag `permissive` protection level in production +4. If `$OC/.config-baseline.sha256` exists, verify: `sha256sum -c $OC/.config-baseline.sha256` + +#### [8] Trust Registry Health + +Check for expired, stale, or over-privileged trust records. + +**Steps**: +1. List all records: `node scripts/trust-cli.ts list` +2. Flag: + - Expired attestations (`expires_at` in the past) + - Trusted skills not re-scanned in 30+ days + - Installed skills with `untrusted` status + - Over-privileged skills: `exec: allow` combined with `network_allowlist: ["*"]` +3. Output registry statistics: total records, distribution by trust level + +### Patrol Report Format + +``` +## GoPlus AgentGuard Patrol Report + +**Timestamp**: +**OpenClaw Home**: <$OC path> +**Protection Level**: +**Overall Status**: PASS | WARN | FAIL + +### Check Results + +| # | Check | Status | Findings | Severity | +|---|-------|--------|----------|----------| +| 1 | Skill/Plugin Integrity | PASS/WARN/FAIL | | | +| 2 | Secrets Exposure | ... | ... | ... | +| 3 | Network Exposure | ... | ... | ... | +| 4 | Cron & Scheduled Tasks | ... | ... | ... | +| 5 | File System Changes | ... | ... | ... | +| 6 | Audit Log Analysis | ... | ... | ... | +| 7 | Environment & Config | ... | ... | ... | +| 8 | Trust Registry Health | ... | ... | ... | + +### Findings Detail +(only checks with findings are shown) + +#### [N] Check Name +- + +### Recommendations +1. [SEVERITY] + +### Next Patrol + +``` + +**Overall status**: Any CRITICAL → **FAIL**, any HIGH → **WARN**, else **PASS** + +After outputting the report, append a summary entry to `~/.agentguard/audit.jsonl`: +```json +{"timestamp":"...","event":"patrol","overall_status":"PASS|WARN|FAIL","checks":8,"findings":,"critical":,"high":} +``` + +### patrol setup + +Configure the patrol as an OpenClaw daily cron job. + +**Steps**: + +1. Verify OpenClaw environment (same pre-flight as `patrol run`) +2. Ask the user for: + - **Timezone** (default: UTC). Examples: `Asia/Shanghai`, `America/New_York`, `Europe/London` + - **Schedule** (default: `0 3 * * *` — daily at 03:00) + - **Notification channel** (optional): `telegram`, `discord`, `signal` + - **Chat ID / webhook** (required if channel is set) +3. Generate the cron registration command: + +```bash +openclaw cron add \ + --name "agentguard-patrol" \ + --description "GoPlus AgentGuard daily security patrol" \ + --cron "" \ + --tz "" \ + --session "isolated" \ + --message "/agentguard patrol run" \ + --timeout-seconds 300 \ + --thinking off \ + # Only include these if notification is configured: + --announce \ + --channel \ + --to +``` + +4. **Show the exact command to the user and wait for explicit confirmation** before executing +5. After execution, verify with `openclaw cron list` +6. Output confirmation with the cron schedule + +> **Note**: `--timeout-seconds 300` is required because isolated sessions need cold-start time. The default 120s is not enough. + +### patrol status + +Show the current patrol state. + +**Steps**: + +1. Read `~/.agentguard/audit.jsonl`, find the most recent `event: "patrol"` entry +2. If found, display: timestamp, overall status, finding counts +3. Run `openclaw cron list` and look for `agentguard-patrol` job +4. If cron is configured, show: schedule, timezone, last run time, next run time +5. If cron is not configured, suggest: `/agentguard patrol setup` + +--- + +# Trust & Configuration + ## Subcommand: trust Manage skill trust levels using the GoPlus AgentGuard registry. @@ -280,6 +504,35 @@ If scripts are not available, help the user inspect `data/registry.json` directl --- +## Subcommand: config + +Set the GoPlus AgentGuard protection level. + +### Protection Levels + +| Level | Behavior | +|-------|----------| +| `strict` | Block all risky actions — every dangerous or suspicious command is denied | +| `balanced` | Block dangerous, confirm risky — default level, good for daily use | +| `permissive` | Only block critical threats — for experienced users who want minimal friction | + +### How to Set + +1. Read `$ARGUMENTS` to get the desired level +2. Write the config to `~/.agentguard/config.json`: + +```json +{"level": "balanced"} +``` + +3. Confirm the change to the user + +If no level is specified, read and display the current config. + +--- + +# Reporting + ## Subcommand: report Display recent security events from the GoPlus AgentGuard audit log. @@ -335,34 +588,7 @@ If the log file doesn't exist, inform the user that no security events have been --- -## Subcommand: config - -Set the GoPlus AgentGuard protection level. - -### Protection Levels - -| Level | Behavior | -|-------|----------| -| `strict` | Block all risky actions — every dangerous or suspicious command is denied | -| `balanced` | Block dangerous, confirm risky — default level, good for daily use | -| `permissive` | Only block critical threats — for experienced users who want minimal friction | - -### How to Set - -1. Read `$ARGUMENTS` to get the desired level -2. Write the config to `~/.agentguard/config.json`: - -```json -{"level": "balanced"} -``` - -3. Confirm the change to the user - -If no level is specified, read and display the current config. - ---- - -## Auto-Scan on Session Start (Opt-In) +# Auto-Scan on Session Start (Opt-In) AgentGuard can optionally scan installed skills at session startup. **This is disabled by default** and must be explicitly enabled: diff --git a/skills/agentguard/patrol-checks.md b/skills/agentguard/patrol-checks.md new file mode 100644 index 0000000..ac2c1f6 --- /dev/null +++ b/skills/agentguard/patrol-checks.md @@ -0,0 +1,334 @@ +# Patrol Check Reference — OpenClaw Daily Security Patrol + +Detailed commands, patterns, and thresholds for the 8 patrol checks. This document is the reference for the `patrol` subcommand. + +**Path convention**: `$OC` = `${OPENCLAW_STATE_DIR:-$HOME/.openclaw}` + +--- + +## Check 1: Skill/Plugin Integrity + +**Purpose**: Detect tampered, unregistered, or drifted skill packages. + +### Steps + +1. Discover skill directories: + ```bash + ls -d $OC/skills/*/ ~/.openclaw/skills/*/ 2>/dev/null + ``` + Each directory containing a `SKILL.md` is a skill. + +2. For each skill, compute hash: + ```bash + node scripts/trust-cli.ts hash --path + ``` + +3. Look up attested hash in trust registry: + ```bash + node scripts/trust-cli.ts lookup --source --version + ``` + +4. Compare hashes. If mismatch, run quick re-scan: + ```bash + # Use Grep + scan rules on the skill directory (same as /agentguard scan) + ``` + +### Findings + +| Tag | Severity | Condition | +|-----|----------|-----------| +| `INTEGRITY_DRIFT` | HIGH | Computed hash differs from attested hash | +| `UNREGISTERED_SKILL` | MEDIUM | Skill directory exists but has no trust record | +| `NEWLY_CRITICAL` | CRITICAL | Re-scan of drifted skill finds CRITICAL findings | + +--- + +## Check 2: Secrets Exposure + +**Purpose**: Detect plaintext secrets leaked in workspace files, memory logs, and sensitive directories. + +### Scan Targets + +| Path | Scope | +|------|-------| +| `$OC/workspace/` | Full recursive (especially `memory/`, `logs/`) | +| `$OC/.env*` | Any dotenv files in OC root | +| `~/.ssh/` | Permission check only | +| `~/.gnupg/` | Permission check only | + +### Patterns (cross-ref scan-rules.md) + +| Rule ID | Tag | Pattern Summary | +|---------|-----|-----------------| +| Rule 7 | PRIVATE_KEY_PATTERN | `['"\x60]0x[a-fA-F0-9]{64}['"\x60]`, `private[_\s]?key\s*[:=]` | +| Rule 8 | MNEMONIC_PATTERN | 12/24 BIP-39 words, `seed[_\s]?phrase`, `mnemonic\s*[:=]` | +| Rule 5 | READ_SSH_KEYS | `\.ssh/id_rsa`, `\.ssh/id_ed25519` in workspace files | + +### Additional Patterns (cross-ref action-policies.md) + +| Type | Pattern | Severity | +|------|---------|----------| +| AWS Secret Key | `[A-Za-z0-9/+=]{40}` near AWS context | HIGH | +| AWS Access Key | `AKIA[0-9A-Z]{16}` | HIGH | +| GitHub Token | `gh[pousr]_[A-Za-z0-9_]{36,}` | HIGH | +| DB Connection String | `(postgres\|mysql\|mongodb)://` | MEDIUM | + +### Permission Checks + +```bash +# SSH directory — should be 700 +stat -f "%Lp" ~/.ssh/ 2>/dev/null || stat -c "%a" ~/.ssh/ 2>/dev/null +# GnuPG — should be 700 +stat -f "%Lp" ~/.gnupg/ 2>/dev/null || stat -c "%a" ~/.gnupg/ 2>/dev/null +``` + +| Condition | Severity | +|-----------|----------| +| `~/.ssh/` permissions > 700 | HIGH | +| `~/.gnupg/` permissions > 700 | MEDIUM | + +--- + +## Check 3: Network Exposure + +**Purpose**: Detect dangerous port exposure, missing firewall, and suspicious connections. + +### Listening Ports + +```bash +# Linux +ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null +# macOS +lsof -i -P -n | grep LISTEN 2>/dev/null +``` + +### High-Risk Default Ports + +Flag if bound to `0.0.0.0` or `*` (not `127.0.0.1`): + +| Port | Service | Severity | +|------|---------|----------| +| 22 | SSH (default port) | MEDIUM | +| 3306 | MySQL | HIGH | +| 5432 | PostgreSQL | HIGH | +| 6379 | Redis | CRITICAL | +| 27017 | MongoDB | HIGH | +| 9200 | Elasticsearch | HIGH | +| 2375/2376 | Docker API | CRITICAL | +| 8080 | Generic HTTP | LOW | + +### Firewall Status + +```bash +# Linux (UFW) +ufw status 2>/dev/null +# Linux (iptables) — check for ACCEPT all on INPUT +iptables -L INPUT -n 2>/dev/null | head -20 +# macOS +/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null +``` + +| Condition | Severity | +|-----------|----------| +| Firewall disabled / inactive | HIGH | +| Redis/Docker API on 0.0.0.0 | CRITICAL | +| Database on 0.0.0.0 without auth | HIGH | +| SSH on default port 22 | MEDIUM (informational) | + +### Outbound Connection Check + +```bash +# Established outbound connections +ss -tnp state established 2>/dev/null || netstat -tnp 2>/dev/null | grep ESTABLISHED +``` + +Cross-reference remote IPs/domains against: +- action-policies.md webhook/exfil domain list (Discord, Telegram, ngrok, webhook.site, etc.) +- scan-rules.md Rule 23 SUSPICIOUS_IP validation (exclude private ranges) +- action-policies.md high-risk TLDs (`.xyz`, `.top`, `.tk`, `.ml`, `.ga`, `.cf`, `.gq`) + +--- + +## Check 4: Cron & Scheduled Tasks + +**Purpose**: Detect malicious or unauthorized scheduled tasks, especially download-and-execute patterns. + +### Data Collection + +```bash +# OpenClaw cron jobs +openclaw cron list 2>/dev/null + +# System crontab +crontab -l 2>/dev/null + +# System cron directories +ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ 2>/dev/null + +# Systemd timers +systemctl list-timers --all 2>/dev/null + +# User systemd units +ls -la ~/.config/systemd/user/ 2>/dev/null +``` + +### Scan Patterns (cross-ref scan-rules.md Rule 2: AUTO_UPDATE) + +Scan cron command bodies for: + +| Pattern | Description | Severity | +|---------|-------------|----------| +| `curl.*\|\s*(bash\|sh)` | curl pipe to shell | CRITICAL | +| `wget.*\|\s*(bash\|sh)` | wget pipe to shell | CRITICAL | +| `fetch.*then.*eval` | Fetch and eval | CRITICAL | +| `download.*execute` (i) | Download-and-execute | HIGH | +| `base64 -d \| bash` | Decode and execute | CRITICAL | +| `eval "$(curl` | eval curl output | CRITICAL | + +### Additional Checks + +| Condition | Severity | +|-----------|----------| +| Unknown cron job touching `$OC/` as root | HIGH | +| Cron job downloading from external URL | HIGH | +| Cron job not present in `openclaw cron list` but touches `$OC/` | MEDIUM | + +--- + +## Check 5: File System Changes + +**Purpose**: Detect suspicious file modifications in the last 24 hours. + +### Scan Targets + +```bash +# Files modified in last 24h +find $OC/ -type f -mtime -1 2>/dev/null +find ~/.ssh/ -type f -mtime -1 2>/dev/null +find ~/.gnupg/ -type f -mtime -1 2>/dev/null +find /etc/cron.d/ -type f -mtime -1 2>/dev/null +``` + +### Analysis + +1. **Count and list** all modified files +2. For files matching scannable extensions (`.js`, `.ts`, `.py`, `.sh`, `.md`, `.json`, `.yaml`): + - Run the full scan rule set against each file (same rules as `/agentguard scan`) + - Report any findings with the relevant rule IDs +3. **Permission check** on critical files: + +| File | Expected Permission | +|------|-------------------| +| `$OC/openclaw.json` | 600 | +| `$OC/devices/paired.json` | 600 | +| `~/.ssh/authorized_keys` | 600 | +| `/etc/ssh/sshd_config` | 644 | + +4. **New executable detection**: + ```bash + find $OC/workspace/ -type f -perm +111 -mtime -1 2>/dev/null + ``` + +--- + +## Check 6: Audit Log Analysis + +**Purpose**: Analyze AgentGuard's own audit trail for attack patterns and anomalies. + +### Data Source + +``` +~/.agentguard/audit.jsonl +``` + +Each line: `{"timestamp":"...","tool_name":"...","decision":"...","risk_level":"...","risk_tags":[...],"initiating_skill":"..."}` + +### Analysis (last 24h) + +1. **Aggregate statistics**: + - Total events, deny count, confirm count, allow count + - Group denials by `risk_tags` + - Group denials by `initiating_skill` + +2. **Pattern detection**: + +| Pattern | Condition | Severity | +|---------|-----------|----------| +| Repeated denial | Same skill denied 3+ times | HIGH | +| Critical event | Any event with `risk_level: critical` | CRITICAL | +| Exfiltration attempt | `WEBHOOK_EXFIL` or `NET_EXFIL_UNRESTRICTED` tag | HIGH | +| Prompt injection | `PROMPT_INJECTION` tag in events | CRITICAL | +| Unrevoked violator | Skill with 5+ denials still not revoked in registry | MEDIUM | + +3. **Recommendation generation**: + - For skills with high deny rates: suggest `/agentguard trust revoke` + - For critical events: suggest immediate investigation + +--- + +## Check 7: Environment & Configuration + +**Purpose**: Verify OpenClaw and AgentGuard configuration security. + +### Environment Variable Scan + +```bash +# List env vars with sensitive names (names only, values masked) +env | grep -iE 'API_KEY|SECRET|PASSWORD|TOKEN|PRIVATE|CREDENTIAL' | awk -F= '{print $1 "=(masked)"}' +``` + +### Configuration Checks + +| Check | Command | Expected | +|-------|---------|----------| +| AgentGuard protection level | Read `~/.agentguard/config.json` | Not `permissive` for production | +| GoPlus API configured | Check `GOPLUS_API_KEY` exists | Set if Web3 features used | +| Config baseline hash | `sha256sum -c $OC/.config-baseline.sha256` | All OK (if baseline exists) | + +### Severity + +| Condition | Severity | +|-----------|----------| +| Protection level = `permissive` | MEDIUM | +| Sensitive env var with `PRIVATE_KEY` or `MNEMONIC` in name | HIGH | +| Config baseline hash mismatch | HIGH | +| Config baseline missing | LOW (informational) | + +--- + +## Check 8: Trust Registry Health + +**Purpose**: Verify the trust registry is well-maintained and no over-privileged skills exist. + +### Data Collection + +```bash +node scripts/trust-cli.ts list +``` + +### Analysis + +| Check | Condition | Severity | +|-------|-----------|----------| +| Expired attestation | `expires_at` < now | MEDIUM | +| Stale trusted skill | `trust_level: trusted` + `updated_at` > 30 days ago | LOW | +| Installed but untrusted | Skill directory exists + `trust_level: untrusted` | MEDIUM | +| Over-privileged | `exec: allow` AND `network_allowlist: ["*"]` | HIGH | +| Empty registry | No records at all despite installed skills | MEDIUM | + +### Statistics Output + +- Total trust records +- Distribution: trusted / restricted / untrusted / revoked +- Skills with Web3 capabilities enabled + +--- + +## Overall Status Calculation + +| Condition | Status | +|-----------|--------| +| Any check has CRITICAL findings | **FAIL** | +| Any check has HIGH findings | **WARN** | +| Only MEDIUM/LOW findings | **PASS** (with notes) | +| No findings | **PASS** | diff --git a/src/adapters/openclaw-plugin.ts b/src/adapters/openclaw-plugin.ts index cc236d8..5e34667 100644 --- a/src/adapters/openclaw-plugin.ts +++ b/src/adapters/openclaw-plugin.ts @@ -30,6 +30,8 @@ import { loadConfig, writeAuditLog } from './common.js'; import type { AgentGuardInstance } from './types.js'; import { SkillScanner } from '../scanner/index.js'; import { SkillRegistry } from '../registry/index.js'; +import { ActionScanner } from '../action/index.js'; +import { DEFAULT_CAPABILITY } from '../types/skill.js'; // --------------------------------------------------------------------------- // OpenClaw Types (subset we use) @@ -176,6 +178,8 @@ export interface OpenClawPluginOptions { scanner?: SkillScanner; /** Custom registry instance */ registry?: SkillRegistry; + /** Workspace paths the session is allowed to access (e.g., ['~/.openclaw/workspace/**']) */ + workspacePaths?: string[]; } // --------------------------------------------------------------------------- @@ -337,18 +341,26 @@ export function registerOpenClawPlugin( // Lazy-initialize agentguard instance let agentguard: AgentGuardInstance | null = null; + // Build default capabilities from workspacePaths so the core session + // can access its own workspace files without a manual registry entry. + const defaultCapabilities = options.workspacePaths + ? { ...DEFAULT_CAPABILITY, filesystem_allowlist: options.workspacePaths } + : undefined; + function getAgentGuard(): AgentGuardInstance { if (!agentguard) { if (options.agentguardFactory) { agentguard = options.agentguardFactory(); } else { - try { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { createAgentGuard } = require('@goplus/agentguard'); - agentguard = createAgentGuard(); - } catch { - throw new Error('AgentGuard: unable to load engine. Install @goplus/agentguard.'); - } + // Build inline — avoids require() and passes workspace defaults + const actionScanner = new ActionScanner({ + registry: trustRegistry, + ...(defaultCapabilities ? { defaultCapabilities } : {}), + }); + agentguard = { + registry: trustRegistry as unknown as AgentGuardInstance['registry'], + actionScanner, + }; } } return agentguard!; diff --git a/src/index.ts b/src/index.ts index 6d26f80..bc23df2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -61,6 +61,7 @@ export { import { SkillScanner } from './scanner/index.js'; import { SkillRegistry } from './registry/index.js'; import { ActionScanner } from './action/index.js'; +import type { CapabilityModel } from './types/skill.js'; /** * Create a complete AgentGuard instance with all modules @@ -68,6 +69,8 @@ import { ActionScanner } from './action/index.js'; export function createAgentGuard(options?: { registryPath?: string; useExternalScanner?: boolean; + /** Default capabilities used when no registry record is found for an actor */ + defaultCapabilities?: CapabilityModel; }) { const registry = new SkillRegistry({ filePath: options?.registryPath, @@ -77,7 +80,10 @@ export function createAgentGuard(options?: { useExternalScanner: options?.useExternalScanner ?? true, }); - const actionScanner = new ActionScanner({ registry }); + const actionScanner = new ActionScanner({ + registry, + defaultCapabilities: options?.defaultCapabilities, + }); return { scanner,