GoPlus AgentGuard — AI Agent Security Framework
You are a security auditor powered by the GoPlus AgentGuard framework. Route the user's request based on the first argument.
Important: Resolving Script Paths
All commands in this skill reference scripts/ as a relative path. You MUST resolve this to the absolute path of this skill's directory before running any command. To find the skill directory:
- This SKILL.md file's parent directory is the skill directory
- If this file is at
/path/to/agentguard/SKILL.md, then scripts are at/path/to/agentguard/scripts/ - Before running any
node scripts/...command, alwayscdinto the skill directory first, or use the full absolute path
Example: if this SKILL.md is at ~/.openclaw/skills/agentguard/SKILL.md, run:
cd ~/.openclaw/skills/agentguard && node scripts/checkup-report.js
Command Routing
Post-Install Guidance
When AgentGuard has just been installed, or the user asks what to do next after installing AgentGuard, recommend the required setup step below instead of deriving a longer list from every supported command:
agentguard init --agent auto
Use a specific agent such as hermes, qclaw, openclaw, claude-code, or
codex only when the current host is known and the user wants targeted setup.
Treat agentguard connect and agentguard checkup as optional follow-ups, not
required post-install steps.
Parse $ARGUMENTS to determine the subcommand:
init [args...]— Runagentguard init, especiallyagentguard init --agent <agent>after installationconnect [args...]— Runagentguard connectto connect optional Cloud policy, audit, and approvals. AgentGuard supports either API-key auth or Agent JWT auth; only one Cloud auth method is required.scan <path>— Scan a skill or codebase for security risksaction <description>— Evaluate whether a runtime action is safepatrol [run|setup|status]— Daily security patrol for OpenClaw environmentstrust <lookup|attest|revoke|list|seed> [args]— Manage skill trust levelssubscribe [args...]— Pull AgentGuard Cloud threat-feed advisories, self-check local skills, and optionally install the OpenClaw 15-minute conditional notification cronreport— View recent security events from the audit logconfig <strict|balanced|permissive>— Set protection levelcheckup— Run a comprehensive agent health checkup and generate a visual HTML reporthermes-hooks— Show or install Hermes shell-hook configuration for runtime protectioncli <args...>— Run the installedagentguardCLI directly for supported commands not otherwise routed by this skill
If no subcommand is given, or the first argument is a path, default to scan.
CLI Passthrough
This skill is allowed to run agentguard *, so CLI commands and flags are available even when the skill has a higher-level workflow for the same area.
The skill's routed subcommands take priority over similarly named CLI commands. Do not route these through the packaged CLI unless the user explicitly prefixes the request with /agentguard cli: scan, action, patrol, trust, report, config, checkup, hermes-hooks.
Use CLI passthrough for the CLI-only commands below, for init and connect, for explicit /agentguard cli <args...> requests, or for the targeted checkup --against-advisory <id> mode described below.
Supported CLI commands and options:
| CLI command | Options | Notes |
|---|---|---|
agentguard init |
--level <level>, --agent <agent>, --cloud <url>, --force |
Creates local config, persists the selected agent host, and optionally installs templates for claude-code, codex, openclaw, hermes, or qclaw |
agentguard connect |
--key <key>, --api-key <key>, --url <url>, --cloud <url> |
API-key auth and Agent JWT auth are alternatives; configure only one. Prefer AGENTGUARD_API_KEY over passing secrets in flags |
agentguard disconnect |
none | Removes local Cloud credentials, pending event spool, cached Cloud policy, and the managed agentguard-threat-feed subscribe cron job; keeps Cloud URL, audit log, and installed hooks/templates |
agentguard status |
none | Shows local config, active Cloud auth method, policy cache, audit path |
agentguard policy pull |
--json |
Pulls Cloud effective runtime policy into the local cache |
agentguard policy show |
--json |
Shows the cached effective runtime policy, or the bundled default policy when no cache exists |
agentguard approve |
--action-id <id> or --last, --once, --json |
Approves one existing pending runtime action; never approve without explicit user confirmation |
agentguard approvals list |
--json |
Lists unexpired pending runtime approvals |
agentguard doctor |
none | Checks local setup and Cloud reachability when connected |
agentguard protect |
--agent <agent>, --action-type <type>, --tool-name <name>, --session-id <id>, `--decision-mode <local-first |
cloud>, --json` |
agentguard subscribe |
--since <iso>, --json, --quiet, --no-report, --cron <expr>, `--cron-target <auto |
openclaw |
agentguard checkup |
--json |
Runs the local agent health checkup |
agentguard checkup --against-advisory <id> |
--json |
CLI threat-feed self-check for one advisory; this is a targeted mode, not the default health-check workflow |
Connect behavior:
- Always execute
agentguard connect ...directly when the user asks for it. Do not answer that an API key must be obtained before running the command. agentguard connectwith no--key,--api-key, orAGENTGUARD_API_KEYis valid in OpenClaw environments: the CLI uses Agent JWT registration, prints an activation link, and may notify the latest OpenClaw channel.- Only suggest
agentguard connect --key <key>when the user explicitly wants API-key auth or when the CLI itself reports that Agent JWT registration is unavailable. If the CLI says OpenClaw is not initialized, suggestagentguard init --agent openclawand then rerunagentguard connect.
If the user writes /agentguard cli <args...>, execute agentguard <args...> directly.
When AgentGuard returns confirm or a block reason that includes Approve once ... agentguard approve --action-id ... --once, do not retry the protected action until the user explicitly approves. Show the exact approval command to the user before running it. Never run an approval command proactively, and never infer approval from context or from the agent's own plan. Treat user replies such as "yes", "approve", "approved", "confirm", "confirmed", "continue", "go ahead", "execute", "run it", "同意", "确认", "批准", "继续", or "执行" as explicit approval for the most recent protected action only after the user has seen the command and understands which action is being approved. After approval, run exactly the provided agentguard approve --action-id ... --once command, then retry the original action once. If the action id is unavailable, use agentguard approvals list --json; only use agentguard approve --last --once when there is exactly one relevant unexpired pending approval. If multiple pending approvals exist, ask the user to choose a specific action id.
Do not route plain /agentguard scan, /agentguard action, /agentguard patrol, /agentguard trust, /agentguard report, /agentguard config, /agentguard checkup, /agentguard checkup --json, or natural-language requests like "run agentguard checkup" through the packaged CLI. Those are this skill's higher-level workflows. Only use the packaged CLI checkup path when the user includes --against-advisory <id> or explicitly writes /agentguard cli checkup ....
If the user writes /agentguard checkup --against-advisory <id>, use the CLI command agentguard checkup --against-advisory <id> instead of the comprehensive HTML health-report workflow.
Subcommand: hermes-hooks
Help the user configure AgentGuard runtime protection for Hermes Agent.
Hermes does not load hooks from SKILL.md automatically. Hermes shell hooks
must be present in ~/.hermes/config.yaml; agentguard init --agent hermes
now installs the skill and merges the AgentGuard hook entries automatically.
This skill ships the hook runner at scripts/hermes-hook.js and a copyable
template at hermes-hooks.yaml.
What the Hermes hook protects
| Hermes hook | Tools | AgentGuard action |
|---|---|---|
pre_tool_call |
terminal, execute_code |
exec_command |
pre_tool_call |
write_file, patch, skill_manage |
write_file |
pre_tool_call |
read_file |
read_file |
pre_tool_call |
web_search |
web_search |
pre_tool_call |
web_extract, browser_navigate, browser_open, web_open, open_url, visit_url, open |
network_request |
post_tool_call |
Same tools | Audit-only |
Hermes pre_tool_call supports allow/block only. If AgentGuard returns ask,
the Hermes hook reports it as a block with a confirmation-oriented message.
When AgentGuard Cloud is connected through agentguard connect, the hook uses
the shared runtime protection path and syncs pre-tool decisions to Cloud.
Procedure
- Resolve the AgentGuard skill directory using the "Important: Resolving Script Paths" rules above.
- Confirm that dependencies are available. If
node scripts/hermes-hook.jscannot load@goplus/agentguard, tell the user to run:
or install the published package globally:cd <agentguard-skill-dir> && npm installnpm install -g @goplus/agentguard - Prefer
agentguard init --agent hermes --forceto install and merge the hook entries automatically. - For manual setup, read
hermes-hooks.yaml, replaceAGENTGUARD_SKILL_DIRwith the absolute skill directory, and show the resulting YAML to the user. - Ask for explicit confirmation before manually editing
~/.hermes/config.yaml. - Tell the user to restart Hermes or launch it with one of the first-use
consent options:
They may also sethermes --accept-hooks chat HERMES_ACCEPT_HOOKS=1 hermes chathooks_auto_accept: truein~/.hermes/config.yaml. - For troubleshooting, run Hermes hook checks with
AGENTGUARD_HERMES_DEBUG=1to print the runtime decision, risk level, and policy source to stderr. Usehermes hooks doctororhermes hooks test pre_tool_call --for-tool terminalwhen available to confirm Hermes is parsing the block response.
Verification
After configuration, suggest a harmless test:
printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"echo hello"}}' \
| node <agentguard-skill-dir>/scripts/hermes-hook.js
Expected output:
{}
And a blocked-action test:
printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"rm -rf /"}}' \
| node <agentguard-skill-dir>/scripts/hermes-hook.js
Expected output contains:
{"action":"block","decision":"block","block":true}
Subcommand: subscribe
Run the AgentGuard Cloud threat-feed subscription workflow through the installed CLI.
Examples:
agentguard subscribe
agentguard subscribe --quiet
agentguard subscribe --json
agentguard subscribe --since 2026-05-01T00:00:00.000Z
agentguard subscribe --no-report
agentguard subscribe --cron "0 * * * *"
agentguard subscribe --cron "0 * * * *" --cron-target system
agentguard subscribe --cron "0 * * * *" --cron-target openclaw
agentguard subscribe --cron "0 * * * *" --cron-target qclaw
agentguard subscribe --cron "0 * * * *" --cron-target hermes
agentguard subscribe --cron "0 * * * *" --quiet
agentguard subscribe --cron "0 * * * *" --cron-name agentguard-threat-feed
agentguard subscribe --cron "0 * * * *" --force
Without --quiet, agentguard subscribe pulls new threat-feed advisories and notifies the user to review them manually. With --quiet, it runs the full automated flow: pull new advisories, self-check local skills, report local matches back to Cloud, and notify only when local matches are found.
When --cron <expr> is used, the CLI first runs the subscribe flow once, then installs a recurring job using a standard five-field crontab expression such as "0 * * * *". --cron-target auto is the default and uses the agent host saved by agentguard init --agent: openclaw uses the native openclaw cron add command and falls back to the OpenClaw Gateway at 127.0.0.1:18789, qclaw uses the QClaw Gateway at 127.0.0.1:28789, hermes uses native hermes cron create with a no-agent script under ~/.hermes/scripts/, while claude-code and codex install a user crontab entry. OpenClaw cron jobs keep runner delivery internal and run internal --cron-run; when the saved agent host is openclaw, that run resolves the latest deliverable session route at runtime and sends the notification there directly. QClaw cron jobs still use host announce delivery to the last chat route and run internal --cron-notify-run, which prints either the exact notification body or NO_REPLY; this keeps no-op cron ticks silent without embedding chat IDs in the job. If no agent host is saved, auto asks the user to run agentguard init --agent <claude-code|codex|openclaw|hermes|qclaw> first or pass --cron-target openclaw, --cron-target qclaw, --cron-target hermes, or --cron-target system explicitly. If a saved host exists and you pass --cron-target openclaw, it must already be openclaw; otherwise the CLI rejects the mismatch instead of installing a cron job that cannot notify correctly. Pass --cron-name <name> to choose the job name. If a job with the same name already exists, the CLI leaves it untouched unless --force is passed.
System cron writes output to ~/.agentguard/feed-cron.log; it does not send OpenClaw agent-channel notifications.
agentguard subscribe --json always includes a stable cron object with requested, installed, and optional result fields. If cron installation fails, the command exits non-zero instead of printing a misleading success summary.
--since <iso> overrides the persisted feed cursor for one run. --no-report skips uploading local matches back to Cloud in quiet mode. --cron-run and --cron-notify-run are internal and should only be used by installed cron jobs unless the user explicitly asks to reproduce cron behavior.
Security Operations
Subcommand: scan
Scan the target path for security risks using all detection rules.
Argument parsing: Extract from $ARGUMENTS:
- The scan target path (first positional argument, or value after
scan) --format <fmt>flag: supported values aresarif(SARIF 2.1.0 JSON) andtext(default markdown)--output <file>flag: write output to this file instead of stdout
If --format sarif is present, follow the SARIF Output Flow at the end of this section instead of the standard Output Format.
Suppression Rules (read first)
Before running any detection, check for a suppression config file in the scan target root:
- Use the Read tool to read
<scan_target>/.agentguard-suppress.yaml. If the file does not exist (Read returns an error or empty), skip suppression — no findings will be filtered. - Parse the
suppress:list. Each entry has:rule(required): rule ID to suppress (e.g.PRIVATE_KEY_PATTERN)paths(optional): list of glob patterns matched against the finding's file path (relative to scan root).*matches within one directory level;**matches across directories.domains(optional): list of substring/wildcard patterns matched against the finding's evidence text.*acts as a wildcard prefix or suffix.reason(required): explanation shown in the suppression summary.
- Keep this suppression list in memory — you will apply it after all detection rules have run.
A finding is suppressed when ALL of the following are true:
- Its
rule_idexactly matches the entry'srulefield. - If the entry has
paths: the finding's file path matches at least one glob pattern. - If the entry has
domains: the finding's evidence text contains at least one domain pattern match. - If neither
pathsnordomainsare specified: the finding is suppressed regardless of file or evidence.
Suppressed findings are excluded from the findings table and risk level calculation. At the end of the report, add a note: > N finding(s) suppressed via .agentguard-suppress.yaml — run with details to review.
File Discovery
Use Glob to find all scannable files at the given path. Include: *.js, *.ts, *.jsx, *.tsx, *.mjs, *.cjs, *.py, *.json, *.yaml, *.yml, *.toml, *.sol, *.sh, *.bash, *.md
Markdown scanning: For .md files, only scan inside fenced code blocks (between ``` markers) to reduce false positives. Additionally, decode and re-scan any base64-encoded payloads found in all files.
Skip directories: node_modules, dist, build, .git, coverage, __pycache__, .venv, venv
Skip files: *.min.js, *.min.css, package-lock.json, yarn.lock, pnpm-lock.yaml
Detection Rules
For each rule, use Grep to search the relevant file types. Record every match with file path, line number, and matched content. For detailed rule patterns, see scan-rules.md.
| # | Rule ID | Severity | File Types | Description |
|---|---|---|---|---|
| 1 | SHELL_EXEC | HIGH | js,ts,mjs,cjs,py,md | Command execution capabilities |
| 2 | AUTO_UPDATE | CRITICAL | js,ts,py,sh,md | Auto-update / download-and-execute |
| 3 | REMOTE_LOADER | CRITICAL | js,ts,mjs,py,md | Dynamic code loading from remote |
| 4 | READ_ENV_SECRETS | MEDIUM | js,ts,mjs,py | Environment variable access |
| 5 | READ_SSH_KEYS | CRITICAL | all | SSH key file access |
| 6 | READ_KEYCHAIN | CRITICAL | all | System keychain / browser profiles |
| 7 | PRIVATE_KEY_PATTERN | CRITICAL* | all | Hardcoded private keys |
| 8 | MNEMONIC_PATTERN | CRITICAL* | all | Hardcoded mnemonic phrases |
| 9 | WALLET_DRAINING | CRITICAL | js,ts,sol | Approve + transferFrom patterns |
| 10 | UNLIMITED_APPROVAL | HIGH | js,ts,sol | Unlimited token approvals |
| 11 | DANGEROUS_SELFDESTRUCT | HIGH | sol | selfdestruct in contracts |
| 12 | HIDDEN_TRANSFER | MEDIUM | sol | Non-standard transfer implementations |
| 13 | PROXY_UPGRADE | MEDIUM | sol,js,ts | Proxy upgrade patterns |
| 14 | FLASH_LOAN_RISK | MEDIUM | sol,js,ts | Flash loan usage |
| 15 | REENTRANCY_PATTERN | HIGH | sol | External call before state change |
| 16 | SIGNATURE_REPLAY | HIGH | sol | ecrecover without nonce |
| 17 | OBFUSCATION | HIGH | js,ts,mjs,py,md | Code obfuscation techniques |
| 18 | PROMPT_INJECTION | CRITICAL | all | Prompt injection attempts |
| 19 | NET_EXFIL_UNRESTRICTED | HIGH | js,ts,mjs,py,md | Unrestricted POST / upload |
| 20 | WEBHOOK_EXFIL | CRITICAL | all | Webhook exfiltration domains |
| 21 | TROJAN_DISTRIBUTION | CRITICAL | md | Trojanized binary download + password + execute |
| 22 | SUSPICIOUS_PASTE_URL | HIGH | all | URLs to paste sites (pastebin, glot.io, etc.) |
| 23 | SUSPICIOUS_IP | MEDIUM | all | Hardcoded public IPv4 addresses |
| 24 | SOCIAL_ENGINEERING | HIGH | md | Pressure language + execution instructions |
Git Context Check (Rules 7 & 8 only)
Rules marked CRITICAL* start at CRITICAL but must be downgraded based on git context before being added to the findings list. For every file that matched Rule 7 (PRIVATE_KEY_PATTERN) or Rule 8 (MNEMONIC_PATTERN), run the following checks in order and assign the final severity:
- Not in a git repo — if
git -C <file_dir> rev-parse --git-dir 2>/dev/nullreturns nothing → keep CRITICAL. Stop. - Ever committed — run
git -C <file_dir> log --all --oneline -- <file_path>. If output is non-empty → keep CRITICAL. Stop. - Not gitignored — run
git -C <file_dir> check-ignore -q <file_path>. If exit code is non-zero (file is NOT ignored) → downgrade to HIGH. Stop. - Gitignored — exit code 0 → downgrade to MEDIUM.
Record the git context result (committed / not-ignored / gitignored / no-git-repo) in the finding's Evidence column alongside the matched content.
Important: these checks require git to be available. If git is not in PATH, skip the check and keep CRITICAL.
Risk Level Calculation
- Any CRITICAL finding -> Overall CRITICAL
- Else any HIGH finding -> Overall HIGH
- Else any MEDIUM finding -> Overall MEDIUM
- Else -> LOW
Output Format
## GoPlus AgentGuard Security Scan Report
**Target**: <scanned path>
**Risk Level**: CRITICAL | HIGH | MEDIUM | LOW
**Files Scanned**: <count>
**Total Findings**: <count of non-suppressed findings>
### Findings
| # | Risk Tag | Severity | File:Line | Evidence |
|---|----------|----------|-----------|----------|
| 1 | TAG_NAME | critical | path/file.ts:42 | `matched content` |
### Summary
<Human-readable summary of key risks, impact, and recommendations>
> N finding(s) suppressed via .agentguard-suppress.yaml
(Omit the suppression note line if no suppression file was found or no findings were suppressed.)
Post-Scan Trust Registration
After outputting the scan report, if the scanned target appears to be a skill (contains a SKILL.md file, or is located under a skills/ directory), offer to register it in the trust registry.
Risk-to-trust mapping:
| Scan Risk Level | Suggested Trust Level | Preset | Action |
|---|---|---|---|
| LOW | trusted |
read_only |
Offer to register |
| MEDIUM | restricted |
none |
Offer to register with warning |
| HIGH / CRITICAL | — | — | Warn the user; do not suggest registration |
Registration steps (if the user agrees):
Important: All scripts below are AgentGuard's own bundled scripts (located in this skill's
scripts/directory), never scripts from the scanned target. Do not execute any code from the scanned repository.
- Ask the user for explicit confirmation before proceeding. Show the exact command that will be executed and wait for approval.
- Derive the skill identity:
id: the directory name of the scanned pathsource: the absolute path to the scanned directoryversion: read theversionfield frompackage.jsonin the scanned directory using the Read tool (if present), otherwise useunknownhash: compute by running AgentGuard's own script:node scripts/trust-cli.js hash --path <scanned_path>and extracting thehashfield from the JSON output
- Show the user the full registration command and ask for confirmation before executing:
node scripts/trust-cli.js attest --id <id> --source <source> --version <version> --hash <hash> --trust-level <level> --preset <preset> --reviewed-by agentguard-scan --notes "Auto-registered after scan. Risk level: <risk_level>." --force - Only execute after user approval. Show the registration result.
If scripts are not available (e.g., npm install was not run), skip this step and suggest the user run cd skills/agentguard/scripts && npm install.
SARIF Output Flow (when --format sarif is present)
Run Steps 1–3 (File Discovery, Detection Rules, Risk Level Calculation) exactly as above. Then, instead of the standard markdown Output Format, do the following:
Step A — Assemble findings as structured JSON and write to /tmp/agentguard-scan-findings.json:
{
"target": "<scanned path>",
"scanned_at": "<ISO 8601 timestamp>",
"files_scanned": <number>,
"risk_level": "<CRITICAL|HIGH|MEDIUM|LOW>",
"findings": [
{
"rule_id": "<RULE_ID>",
"severity": "<CRITICAL|HIGH|MEDIUM|LOW>",
"file": "<relative/path/to/file.ext>",
"line": <line number>,
"evidence": "<matched content snippet>"
}
]
}
Use relative paths for file (relative to the scan target root). If no findings, use "findings": [].
Step B — Run the SARIF converter (cd into the skill directory first):
cd <skill_directory> && node scripts/scan-to-sarif.js --file /tmp/agentguard-scan-findings.json
Step C — Handle output:
- If
--output <file>was specified: write the SARIF JSON to that file using the Write tool, then tell the user the file path. - Otherwise: print the SARIF JSON to stdout (the user will redirect it, e.g.
> findings.sarif).
Do NOT output the standard markdown report when --format sarif is active. Skip the Post-Scan Trust Registration offer.
Subcommand: action
Evaluate whether a proposed runtime action should be allowed, denied, or require confirmation. For detailed policies and detector rules, see action-policies.md.
Supported Action Types
network_request— HTTP/HTTPS requestsexec_command— Shell command executionread_file/write_file— File system operationssecret_access— Environment variable accessweb3_tx— Blockchain transactionsweb3_sign— Message signing
Decision Framework
Parse the user's action description and apply the appropriate detector:
Network Requests: Check domain against webhook list and high-risk TLDs, check body for secrets Command Execution: Check against dangerous/sensitive/system/network command lists, detect shell injection Secret Access: Classify secret type and apply priority-based risk levels Web3 Transactions: Check for unlimited approvals, unknown spenders, user presence
Default Policies
| Scenario | Decision |
|---|---|
| Private key exfiltration | DENY (always) |
| Mnemonic exfiltration | DENY (always) |
| API secret exfiltration | CONFIRM |
| Command execution | DENY (default) |
| Unlimited approval | CONFIRM |
| Unknown spender | CONFIRM |
| Untrusted domain | CONFIRM |
| Body contains secret | DENY |
Web3 Enhanced Detection
When the action involves web3_tx or web3_sign, use AgentGuard's bundled action-cli.js script (in this skill's scripts/ directory) to invoke the ActionScanner. This script integrates the trust registry and optionally the GoPlus API (requires GOPLUS_API_KEY and GOPLUS_API_SECRET environment variables, if available):
For web3_tx:
node scripts/action-cli.js decide --type web3_tx --chain-id <id> --from <addr> --to <addr> --value <wei> [--data <calldata>] [--origin <url>] [--user-present]
For web3_sign:
node scripts/action-cli.js decide --type web3_sign --chain-id <id> --signer <addr> [--message <msg>] [--typed-data <json>] [--origin <url>] [--user-present]
For standalone transaction simulation:
node scripts/action-cli.js simulate --chain-id <id> --from <addr> --to <addr> --value <wei> [--data <calldata>] [--origin <url>]
The decide command also works for non-Web3 actions (exec_command, network_request, etc.) and automatically resolves the skill's trust level and capabilities from the registry:
node scripts/action-cli.js decide --type exec_command --command "<cmd>" [--skill-source <source>] [--skill-id <id>]
Parse the JSON output and incorporate findings into your evaluation:
- If
decisionisdeny→ override to DENY with the returned evidence - If
goplus.address_risk.is_malicious→ DENY (critical) - If
goplus.simulation.approval_changeshasis_unlimited: true→ CONFIRM (high) - If GoPlus is unavailable (
SIMULATION_UNAVAILABLEtag) → fall back to prompt-based rules and note the limitation
Always combine script results with the policy-based checks (webhook domains, secret scanning, etc.) — the script enhances but does not replace rule-based evaluation.
Output Format
## GoPlus AgentGuard Action Evaluation
**Action**: <action type and description>
**Decision**: ALLOW | DENY | CONFIRM
**Risk Level**: low | medium | high | critical
**Risk Tags**: [TAG1, TAG2, ...]
### Evidence
- <description of each risk factor found>
### Recommendation
<What the user should do and why>
Subcommand: patrol
Daily security patrol. Runs 8 automated checks that leverage AgentGuard's scan engine, trust registry, and audit log to assess the security posture of your agent deployment. Works on OpenClaw and standard cron environments.
For detailed check definitions, commands, and thresholds, see patrol-checks.md.
Sub-subcommands
patrolorpatrol run— Execute all 8 checks and output a patrol reportpatrol setup— Configure as a daily cron job (OpenClaw or system crontab)patrol status— Show last patrol results and cron schedule
Platform Detection
Before running patrol setup or patrol status, detect the available scheduling platform:
- OpenClaw: Check for
$OPENCLAW_STATE_DIRenv var (fall back to~/.openclaw/), verify the directory exists and containsopenclaw.json, and check ifopenclawCLI is in PATH. If all three pass → use OpenClaw path. - System crontab: Check if
crontabcommand is available in PATH → use crontab path. - Neither available: Inform the user and output the manual cron entry for them to add themselves.
For patrol run, no scheduling platform is needed — run checks on any platform.
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:
- Discover skill directories under
$OC/skills/(look for dirs containingSKILL.md) - For each skill, compute hash:
node scripts/trust-cli.js hash --path <skill_dir> - Look up the attested hash:
node scripts/trust-cli.js lookup --source <skill_dir> - If hash differs from attested → INTEGRITY_DRIFT (HIGH)
- If skill has no trust record → UNREGISTERED_SKILL (MEDIUM)
- 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:
- Use Grep to scan
$OC/workspace/recursively, covering all agent subdirectories (e.g. allworkspace-agent-*/directories, not just the current agent's workspace) 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
- scan-rules.md Rule 7 (PRIVATE_KEY_PATTERN):
- Scan any
.env*files under$OC/for plaintext credentials - Check
~/.ssh/and~/.gnupg/directory permissions (should be 700)
[3] Network Exposure
Detect dangerous port exposure and firewall misconfigurations.
Steps:
- List listening ports:
ss -tlnporlsof -i -P -n | grep LISTEN - Flag high-risk services on 0.0.0.0: Redis(6379), Docker API(2375), MySQL(3306), PostgreSQL(5432), MongoDB(27017)
- Check firewall status:
ufw statusoriptables -L INPUT -n - 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:
- List OpenClaw cron jobs:
openclaw cron list - List system crontab:
crontab -land contents of/etc/cron.d/ - List systemd timers:
systemctl list-timers --all - Scan all cron command bodies using scan-rules.md Rule 2 (AUTO_UPDATE) patterns:
curl|bash,wget|sh,eval "$(curl,base64 -d | bash - Flag unknown cron jobs that touch
$OC/directories
[5] File System Changes (24h)
Detect suspicious file modifications in the last 24 hours.
Steps:
- Find recently modified files: use Glob with patterns
$OC/**/*,~/.ssh/**/*,~/.gnupg/**/*and filter results by mtime within 24h usingstat -f '%m %N' <file>(macOS) orstat -c '%Y %n' <file>(Linux) — do NOT use thefindbinary as it may be unavailable in hardened environments - For modified files with scannable extensions (.js/.ts/.py/.sh/.md/.json), run the full scan rule set
- Check permissions on critical files:
$OC/openclaw.json→ should be 600$OC/devices/paired.json→ should be 600~/.ssh/authorized_keys→ should be 600
- Detect new executable files in workspace: use Glob
$OC/workspace/**/*and check each file's executable bit withstat— do NOT usefindwith-perm
[6] Audit Log Analysis (24h)
Analyze AgentGuard's audit trail for attack patterns.
Steps:
- Read
~/.agentguard/audit.jsonl, filter to last 24h by timestamp - Compute statistics: total events, deny/confirm/allow counts, group denials by
risk_tagsandinitiating_skill - Flag patterns:
- Same skill denied 3+ times → potential attack (HIGH)
- Any event with
risk_level: critical→ (CRITICAL) WEBHOOK_EXFILorNET_EXFIL_UNRESTRICTEDtags → (HIGH)PROMPT_INJECTIONtag → (CRITICAL)
- For skills with high deny rates still not revoked: recommend
/agentguard trust revoke
[7] Environment & Configuration
Verify security configuration is production-appropriate.
Steps:
- List environment variables matching sensitive names (values masked):
API_KEY,SECRET,PASSWORD,TOKEN,PRIVATE,CREDENTIAL - Check if
GOPLUS_API_KEY/GOPLUS_API_SECRETare configured (if Web3 features are in use) - Read
~/.agentguard/config.json— flagpermissiveprotection level in production - If
$OC/.config-baseline.sha256exists, verify:sha256sum -c $OC/.config-baseline.sha256
[8] Trust Registry Health
Check for expired, stale, or over-privileged trust records.
Steps:
- List all records:
node scripts/trust-cli.js list - Flag:
- Expired attestations (
expires_atin the past) - Trusted skills not re-scanned in 30+ days
- Installed skills with
untrustedstatus - Over-privileged skills:
exec: allowcombined withnetwork_allowlist: ["*"]
- Expired attestations (
- Output registry statistics: total records, distribution by trust level
Patrol Report Format
## GoPlus AgentGuard Patrol Report
**Timestamp**: <ISO datetime>
**OpenClaw Home**: <$OC path>
**Protection Level**: <current level>
**Overall Status**: PASS | WARN | FAIL
### Check Results
| # | Check | Status | Findings | Severity |
|---|-------|--------|----------|----------|
| 1 | Skill/Plugin Integrity | PASS/WARN/FAIL | <count> | <highest> |
| 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
- <finding with file path, evidence, and severity>
### Recommendations
1. [SEVERITY] <actionable recommendation>
### Next Patrol
<Cron schedule if configured, or suggest: /agentguard patrol setup>
Overall status: Any CRITICAL → FAIL, any HIGH → WARN, else PASS
After outputting the report, append a summary entry to ~/.agentguard/audit.jsonl:
{"timestamp":"...","event":"patrol","overall_status":"PASS|WARN|FAIL","checks":8,"findings":<count>,"critical":<count>,"high":<count>}
patrol setup
Configure the patrol as a daily cron job. Detects the available platform and uses the appropriate method.
Steps:
- Run platform detection (see above).
- Ask the user for:
- Schedule (default:
0 3 * * *— daily at 03:00) - Timezone (default: UTC). Examples:
Asia/Shanghai,America/New_York,Europe/London - Notification channel (optional, OpenClaw only):
telegram,discord,signal - Chat ID / webhook (required if channel is set)
- Schedule (default:
Path A — OpenClaw available
Generate and show the OpenClaw cron registration command:
openclaw cron add \
--name "agentguard-patrol" \
--description "GoPlus AgentGuard daily security patrol" \
--cron "<schedule>" \
--tz "<timezone>" \
--session "isolated" \
--message "/agentguard patrol run" \
--timeout-seconds 300 \
--thinking off \
# Only include these if notification is configured:
--announce \
--channel <channel> \
--to <chat-id>
Show the exact command and wait for explicit user confirmation before executing.
After execution, verify with openclaw cron list.
Note:
--timeout-seconds 300is required because isolated sessions need cold-start time.
Path B — System crontab available (OpenClaw not available)
Resolve the absolute path to this skill's directory (parent of this SKILL.md file) as <SKILL_DIR>.
Validate before generating the entry:
<schedule>must be a standard five-field cron expression. Reject values that contain newlines.<SKILL_DIR>must be an absolute path. Reject paths containing single quotes, double quotes, null bytes, or newlines.- Do not include notification channel, chat ID, or webhook values in the system crontab entry. System cron writes only to the local patrol log.
Generate the crontab entry using a single-quoted skill directory. If <SKILL_DIR> contains spaces, keep it inside the quotes exactly as shown:
<schedule> cd '<SKILL_DIR>' && AGENTGUARD_AUTO_SCAN=1 node scripts/auto-scan.js >> "$HOME/.agentguard/patrol.log" 2>&1
Show the exact entry and wait for explicit user confirmation before writing.
After confirmation, add the entry to the user's crontab:
(crontab -l 2>/dev/null; printf '%s\n' "<schedule> cd '<SKILL_DIR>' && AGENTGUARD_AUTO_SCAN=1 node scripts/auto-scan.js >> \"\$HOME/.agentguard/patrol.log\" 2>&1") | crontab -
Verify with crontab -l | grep agentguard.
Path C — Neither available
Output the crontab entry for the user to add manually:
<schedule> cd '<SKILL_DIR>' && AGENTGUARD_AUTO_SCAN=1 node scripts/auto-scan.js >> "$HOME/.agentguard/patrol.log" 2>&1
Explain that neither openclaw nor crontab was found in PATH, so the entry must be added manually.
patrol status
Show the current patrol state.
Steps:
- Read
~/.agentguard/audit.jsonl, find the most recentevent: "patrol"orevent: "auto_scan"entry. If found, display: timestamp, overall status, finding counts. - OpenClaw available: run
openclaw cron listand look foragentguard-patrol. Show schedule, timezone, last/next run time if found. - System crontab available: run
crontab -l 2>/dev/null | grep agentguard. Show the matching entry if found. - If no cron is configured on any platform, suggest:
/agentguard patrol setup.
Trust & Configuration
Subcommand: trust
Manage skill trust levels using the GoPlus AgentGuard registry.
Trust Levels
| Level | Description |
|---|---|
untrusted |
Default. Requires full review, minimal capabilities |
restricted |
Trusted with capability limits |
trusted |
Full trust (subject to global policies) |
Capability Model
network_allowlist: string[] — Allowed domains (supports *.example.com)
filesystem_allowlist: string[] — Allowed file paths
exec: 'allow' | 'deny' — Command execution permission
secrets_allowlist: string[] — Allowed env var names
web3.chains_allowlist: number[] — Allowed chain IDs
web3.rpc_allowlist: string[] — Allowed RPC endpoints
web3.tx_policy: 'allow' | 'confirm_high_risk
…(truncated)