@goplus/agentguard 1.1.9 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -8
- package/dist/adapters/common.d.ts.map +1 -1
- package/dist/adapters/common.js +3 -1
- package/dist/adapters/common.js.map +1 -1
- package/dist/adapters/openclaw-plugin.d.ts.map +1 -1
- package/dist/adapters/openclaw-plugin.js +17 -3
- package/dist/adapters/openclaw-plugin.js.map +1 -1
- package/dist/cli.js +170 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -0
- package/dist/config.js.map +1 -1
- package/dist/feed/cron.d.ts +27 -0
- package/dist/feed/cron.d.ts.map +1 -1
- package/dist/feed/cron.js +721 -54
- package/dist/feed/cron.js.map +1 -1
- package/dist/installers.d.ts +1 -1
- package/dist/installers.d.ts.map +1 -1
- package/dist/installers.js +164 -13
- package/dist/installers.js.map +1 -1
- package/dist/postinstall.js +29 -0
- package/dist/postinstall.js.map +1 -1
- package/dist/registry/storage.d.ts.map +1 -1
- package/dist/registry/storage.js +5 -1
- package/dist/registry/storage.js.map +1 -1
- package/dist/runtime/types.d.ts +1 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/tests/cli-init.test.d.ts +2 -0
- package/dist/tests/cli-init.test.d.ts.map +1 -0
- package/dist/tests/cli-init.test.js +130 -0
- package/dist/tests/cli-init.test.js.map +1 -0
- package/dist/tests/cli-policy.test.js +47 -0
- package/dist/tests/cli-policy.test.js.map +1 -1
- package/dist/tests/cli-subscribe.test.js +33 -0
- package/dist/tests/cli-subscribe.test.js.map +1 -1
- package/dist/tests/feed-cron.test.js +441 -13
- package/dist/tests/feed-cron.test.js.map +1 -1
- package/dist/tests/installer.test.js +37 -2
- package/dist/tests/installer.test.js.map +1 -1
- package/dist/tests/integration.test.js +9 -5
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/postinstall.test.d.ts +2 -0
- package/dist/tests/postinstall.test.d.ts.map +1 -0
- package/dist/tests/postinstall.test.js +31 -0
- package/dist/tests/postinstall.test.js.map +1 -0
- package/dist/tests/setup-script.test.d.ts +2 -0
- package/dist/tests/setup-script.test.d.ts.map +1 -0
- package/dist/tests/setup-script.test.js +63 -0
- package/dist/tests/setup-script.test.js.map +1 -0
- package/dist/tests/smoke.test.js +88 -1
- package/dist/tests/smoke.test.js.map +1 -1
- package/docs/codex.md +1 -1
- package/docs/hermes.md +3 -3
- package/package.json +1 -1
- package/skills/agentguard/SKILL.md +424 -194
- package/skills/agentguard/hermes-hooks.yaml +2 -2
- package/skills/agentguard/scan-rules.md +13 -2
- package/skills/agentguard/scripts/{action-cli.ts → action-cli.js} +13 -18
- package/skills/agentguard/scripts/auto-scan.js +3 -1
- package/skills/agentguard/scripts/checkup-score.js +369 -0
- package/skills/agentguard/scripts/hermes-hook.js +103 -16
- package/skills/agentguard/scripts/scan-to-sarif.js +195 -0
- package/skills/agentguard/scripts/{trust-cli.ts → trust-cli.js} +12 -16
- package/skills/agentguard/suppress.example.yaml +67 -0
|
@@ -30,8 +30,8 @@ filesystem-access:
|
|
|
30
30
|
access: read-write
|
|
31
31
|
reason: "Read/write audit log (audit.jsonl) and protection level config (config.json)"
|
|
32
32
|
user-invocable: true
|
|
33
|
-
allowed-tools: Read, Write, Grep, Glob, Bash(node *trust-cli.
|
|
34
|
-
argument-hint: "[scan|action|patrol|subscribe|trust|report|config|checkup|cli] [args...]"
|
|
33
|
+
allowed-tools: Read, Write, Grep, Glob, Bash(node *trust-cli.js *) Bash(node *action-cli.js *) Bash(*checkup-report.js) Bash(*checkup-score.js) Bash(*scan-to-sarif.js) Bash(echo *checkup-report.js) Bash(cat *checkup-report.js) Bash(agentguard *) Bash(openclaw *) Bash(ss *) Bash(lsof *) Bash(ufw *) Bash(iptables *) Bash(crontab *) Bash(systemctl list-timers *) Bash(find *) Bash(stat *) Bash(env) Bash(sha256sum *) Bash(node *) Bash(cd *)
|
|
34
|
+
argument-hint: "[scan|action|patrol|subscribe|trust|report|config|checkup|cli] [args...] [--format sarif|json] [--output <file>]"
|
|
35
35
|
---
|
|
36
36
|
|
|
37
37
|
# GoPlus AgentGuard — AI Agent Security Framework
|
|
@@ -53,13 +53,30 @@ cd ~/.openclaw/skills/agentguard && node scripts/checkup-report.js
|
|
|
53
53
|
|
|
54
54
|
## Command Routing
|
|
55
55
|
|
|
56
|
+
### Post-Install Guidance
|
|
57
|
+
|
|
58
|
+
When AgentGuard has just been installed, or the user asks what to do next after
|
|
59
|
+
installing AgentGuard, recommend the required setup step below instead of
|
|
60
|
+
deriving a longer list from every supported command:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
agentguard init --agent auto
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use a specific agent such as `hermes`, `qclaw`, `openclaw`, `claude-code`, or
|
|
67
|
+
`codex` only when the current host is known and the user wants targeted setup.
|
|
68
|
+
Treat `agentguard connect` and `agentguard checkup` as optional follow-ups, not
|
|
69
|
+
required post-install steps.
|
|
70
|
+
|
|
56
71
|
Parse `$ARGUMENTS` to determine the subcommand:
|
|
57
72
|
|
|
73
|
+
- **`init [args...]`** — Run `agentguard init`, especially `agentguard init --agent <agent>` after installation
|
|
74
|
+
- **`connect [args...]`** — Run `agentguard connect` to connect optional Cloud policy, audit, and approvals
|
|
58
75
|
- **`scan <path>`** — Scan a skill or codebase for security risks
|
|
59
76
|
- **`action <description>`** — Evaluate whether a runtime action is safe
|
|
60
77
|
- **`patrol [run|setup|status]`** — Daily security patrol for OpenClaw environments
|
|
78
|
+
- **`trust <lookup|attest|revoke|list|seed> [args]`** — Manage skill trust levels
|
|
61
79
|
- **`subscribe [args...]`** — Pull AgentGuard Cloud threat-feed advisories, self-check local skills, and optionally install the OpenClaw 15-minute conditional notification cron
|
|
62
|
-
- **`trust <lookup|attest|revoke|list> [args]`** — Manage skill trust levels
|
|
63
80
|
- **`report`** — View recent security events from the audit log
|
|
64
81
|
- **`config <strict|balanced|permissive>`** — Set protection level
|
|
65
82
|
- **`checkup`** — Run a comprehensive agent health checkup and generate a visual HTML report
|
|
@@ -74,20 +91,22 @@ This skill is allowed to run `agentguard *`, so CLI commands and flags are avail
|
|
|
74
91
|
|
|
75
92
|
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`.
|
|
76
93
|
|
|
77
|
-
Use CLI passthrough for the CLI-only commands below, for explicit `/agentguard cli <args...>` requests, or for the targeted `checkup --against-advisory <id>` mode described below.
|
|
94
|
+
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.
|
|
78
95
|
|
|
79
96
|
Supported CLI commands and options:
|
|
80
97
|
|
|
81
98
|
| CLI command | Options | Notes |
|
|
82
99
|
|---|---|---|
|
|
83
|
-
| `agentguard init` | `--level <level>`, `--agent <agent>`, `--cloud <url>`, `--force` | Creates local config and optionally installs
|
|
100
|
+
| `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` |
|
|
84
101
|
| `agentguard connect` | `--key <key>`, `--api-key <key>`, `--url <url>`, `--cloud <url>` | Prefer `AGENTGUARD_API_KEY` over passing secrets in flags |
|
|
85
102
|
| `agentguard disconnect` | none | Removes local Cloud API key, connection timestamp, pending event spool, and cached Cloud policy; keeps Cloud URL, audit log, and installed hooks/templates |
|
|
86
103
|
| `agentguard status` | none | Shows local config, Cloud URL/API key status, policy cache, audit path |
|
|
87
104
|
| `agentguard policy pull` | `--json` | Pulls Cloud effective runtime policy into the local cache |
|
|
105
|
+
| `agentguard policy show` | `--json` | Shows the cached effective runtime policy, or the bundled default policy when no cache exists |
|
|
88
106
|
| `agentguard doctor` | none | Checks local setup and Cloud reachability when connected |
|
|
89
107
|
| `agentguard protect` | `--agent <agent>`, `--action-type <type>`, `--tool-name <name>`, `--session-id <id>`, `--decision-mode <local-first|cloud>`, `--json` | Evaluates one runtime action from stdin or hook environment |
|
|
90
|
-
| `agentguard subscribe` | `--since <iso>`, `--json`, `--quiet`, `--no-report`, `--cron <expr>`, `--cron-name <name>`, `--force`, `--cron-run` | Pulls Cloud threat advisories and optionally self-checks local skills |
|
|
108
|
+
| `agentguard subscribe` | `--since <iso>`, `--json`, `--quiet`, `--no-report`, `--cron <expr>`, `--cron-target <auto|openclaw|qclaw|hermes|system>`, `--cron-name <name>`, `--force`, `--cron-run`, `--cron-notify-run` | Pulls Cloud threat advisories and optionally self-checks local skills |
|
|
109
|
+
| `agentguard checkup` | `--json` | Runs the local agent health checkup |
|
|
91
110
|
| `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 |
|
|
92
111
|
|
|
93
112
|
If the user writes `/agentguard cli <args...>`, execute `agentguard <args...>` directly.
|
|
@@ -101,8 +120,10 @@ If the user writes `/agentguard checkup --against-advisory <id>`, use the CLI co
|
|
|
101
120
|
Help the user configure AgentGuard runtime protection for Hermes Agent.
|
|
102
121
|
|
|
103
122
|
Hermes does **not** load hooks from `SKILL.md` automatically. Hermes shell hooks
|
|
104
|
-
must be present in `~/.hermes/config.yaml
|
|
105
|
-
|
|
123
|
+
must be present in `~/.hermes/config.yaml`; `agentguard init --agent hermes`
|
|
124
|
+
now installs the skill and merges the AgentGuard hook entries automatically.
|
|
125
|
+
This skill ships the hook runner at `scripts/hermes-hook.js` and a copyable
|
|
126
|
+
template at `hermes-hooks.yaml`.
|
|
106
127
|
|
|
107
128
|
### What the Hermes hook protects
|
|
108
129
|
|
|
@@ -111,11 +132,13 @@ must be present in `~/.hermes/config.yaml`. This skill ships the hook runner at
|
|
|
111
132
|
| `pre_tool_call` | `terminal`, `execute_code` | `exec_command` |
|
|
112
133
|
| `pre_tool_call` | `write_file`, `patch`, `skill_manage` | `write_file` |
|
|
113
134
|
| `pre_tool_call` | `read_file` | `read_file` |
|
|
114
|
-
| `pre_tool_call` | `web_search`, `web_extract`, `browser_navigate` | `network_request` |
|
|
135
|
+
| `pre_tool_call` | `web_search`, `web_extract`, `browser_navigate`, `browser_open`, `web_open`, `open_url`, `visit_url`, `open` | `network_request` |
|
|
115
136
|
| `post_tool_call` | Same tools | Audit-only |
|
|
116
137
|
|
|
117
138
|
Hermes `pre_tool_call` supports allow/block only. If AgentGuard returns `ask`,
|
|
118
139
|
the Hermes hook reports it as a block with a confirmation-oriented message.
|
|
140
|
+
When AgentGuard Cloud is connected through `agentguard connect`, the hook uses
|
|
141
|
+
the shared runtime protection path and syncs pre-tool decisions to Cloud.
|
|
119
142
|
|
|
120
143
|
### Procedure
|
|
121
144
|
|
|
@@ -130,12 +153,13 @@ the Hermes hook reports it as a block with a confirmation-oriented message.
|
|
|
130
153
|
```bash
|
|
131
154
|
npm install -g @goplus/agentguard
|
|
132
155
|
```
|
|
133
|
-
3.
|
|
134
|
-
|
|
135
|
-
4.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
156
|
+
3. Prefer `agentguard init --agent hermes --force` to install and merge the
|
|
157
|
+
hook entries automatically.
|
|
158
|
+
4. For manual setup, read `hermes-hooks.yaml`, replace
|
|
159
|
+
`AGENTGUARD_SKILL_DIR` with the absolute skill directory, and show the
|
|
160
|
+
resulting YAML to the user.
|
|
161
|
+
5. Ask for explicit confirmation before manually editing
|
|
162
|
+
`~/.hermes/config.yaml`.
|
|
139
163
|
6. Tell the user to restart Hermes or launch it with one of the first-use
|
|
140
164
|
consent options:
|
|
141
165
|
```bash
|
|
@@ -143,6 +167,11 @@ the Hermes hook reports it as a block with a confirmation-oriented message.
|
|
|
143
167
|
HERMES_ACCEPT_HOOKS=1 hermes chat
|
|
144
168
|
```
|
|
145
169
|
They may also set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.
|
|
170
|
+
7. For troubleshooting, run Hermes hook checks with
|
|
171
|
+
`AGENTGUARD_HERMES_DEBUG=1` to print the runtime decision, risk level, and
|
|
172
|
+
policy source to stderr. Use `hermes hooks doctor` or
|
|
173
|
+
`hermes hooks test pre_tool_call --for-tool terminal` when available to
|
|
174
|
+
confirm Hermes is parsing the block response.
|
|
146
175
|
|
|
147
176
|
### Verification
|
|
148
177
|
|
|
@@ -169,7 +198,7 @@ printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{
|
|
|
169
198
|
Expected output contains:
|
|
170
199
|
|
|
171
200
|
```json
|
|
172
|
-
{"action":"block"}
|
|
201
|
+
{"action":"block","decision":"block","block":true}
|
|
173
202
|
```
|
|
174
203
|
|
|
175
204
|
## Subcommand: subscribe
|
|
@@ -185,6 +214,10 @@ agentguard subscribe --json
|
|
|
185
214
|
agentguard subscribe --since 2026-05-01T00:00:00.000Z
|
|
186
215
|
agentguard subscribe --no-report
|
|
187
216
|
agentguard subscribe --cron "0 * * * *"
|
|
217
|
+
agentguard subscribe --cron "0 * * * *" --cron-target system
|
|
218
|
+
agentguard subscribe --cron "0 * * * *" --cron-target openclaw
|
|
219
|
+
agentguard subscribe --cron "0 * * * *" --cron-target qclaw
|
|
220
|
+
agentguard subscribe --cron "0 * * * *" --cron-target hermes
|
|
188
221
|
agentguard subscribe --cron "0 * * * *" --quiet
|
|
189
222
|
agentguard subscribe --cron "0 * * * *" --cron-name agentguard-threat-feed
|
|
190
223
|
agentguard subscribe --cron "0 * * * *" --force
|
|
@@ -192,11 +225,13 @@ agentguard subscribe --cron "0 * * * *" --force
|
|
|
192
225
|
|
|
193
226
|
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.
|
|
194
227
|
|
|
195
|
-
When `--cron <expr>` is used, the CLI
|
|
228
|
+
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/QClaw cron jobs 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. 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.
|
|
229
|
+
|
|
230
|
+
System cron writes output to `~/.agentguard/feed-cron.log`; it does not send OpenClaw agent-channel notifications.
|
|
196
231
|
|
|
197
232
|
`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.
|
|
198
233
|
|
|
199
|
-
`--since <iso>` overrides the persisted feed cursor for one run. `--no-report` skips uploading local matches back to Cloud in quiet mode. `--cron-run`
|
|
234
|
+
`--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.
|
|
200
235
|
|
|
201
236
|
---
|
|
202
237
|
|
|
@@ -206,6 +241,33 @@ When `--cron <expr>` is used, the CLI registers an OpenClaw isolated cron job th
|
|
|
206
241
|
|
|
207
242
|
Scan the target path for security risks using all detection rules.
|
|
208
243
|
|
|
244
|
+
**Argument parsing**: Extract from `$ARGUMENTS`:
|
|
245
|
+
- The scan target path (first positional argument, or value after `scan`)
|
|
246
|
+
- `--format <fmt>` flag: supported values are `sarif` (SARIF 2.1.0 JSON) and `text` (default markdown)
|
|
247
|
+
- `--output <file>` flag: write output to this file instead of stdout
|
|
248
|
+
|
|
249
|
+
If `--format sarif` is present, follow the **SARIF Output Flow** at the end of this section instead of the standard Output Format.
|
|
250
|
+
|
|
251
|
+
### Suppression Rules (read first)
|
|
252
|
+
|
|
253
|
+
Before running any detection, check for a suppression config file in the scan target root:
|
|
254
|
+
|
|
255
|
+
1. 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.
|
|
256
|
+
2. Parse the `suppress:` list. Each entry has:
|
|
257
|
+
- `rule` (required): rule ID to suppress (e.g. `PRIVATE_KEY_PATTERN`)
|
|
258
|
+
- `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.
|
|
259
|
+
- `domains` (optional): list of substring/wildcard patterns matched against the finding's evidence text. `*` acts as a wildcard prefix or suffix.
|
|
260
|
+
- `reason` (required): explanation shown in the suppression summary.
|
|
261
|
+
3. Keep this suppression list in memory — you will apply it after all detection rules have run.
|
|
262
|
+
|
|
263
|
+
**A finding is suppressed when ALL of the following are true:**
|
|
264
|
+
- Its `rule_id` exactly matches the entry's `rule` field.
|
|
265
|
+
- If the entry has `paths`: the finding's file path matches at least one glob pattern.
|
|
266
|
+
- If the entry has `domains`: the finding's evidence text contains at least one domain pattern match.
|
|
267
|
+
- If neither `paths` nor `domains` are specified: the finding is suppressed regardless of file or evidence.
|
|
268
|
+
|
|
269
|
+
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.`
|
|
270
|
+
|
|
209
271
|
### File Discovery
|
|
210
272
|
|
|
211
273
|
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`
|
|
@@ -227,8 +289,8 @@ For each rule, use Grep to search the relevant file types. Record every match wi
|
|
|
227
289
|
| 4 | READ_ENV_SECRETS | MEDIUM | js,ts,mjs,py | Environment variable access |
|
|
228
290
|
| 5 | READ_SSH_KEYS | CRITICAL | all | SSH key file access |
|
|
229
291
|
| 6 | READ_KEYCHAIN | CRITICAL | all | System keychain / browser profiles |
|
|
230
|
-
| 7 | PRIVATE_KEY_PATTERN | CRITICAL | all | Hardcoded private keys |
|
|
231
|
-
| 8 | MNEMONIC_PATTERN | CRITICAL | all | Hardcoded mnemonic phrases |
|
|
292
|
+
| 7 | PRIVATE_KEY_PATTERN | CRITICAL* | all | Hardcoded private keys |
|
|
293
|
+
| 8 | MNEMONIC_PATTERN | CRITICAL* | all | Hardcoded mnemonic phrases |
|
|
232
294
|
| 9 | WALLET_DRAINING | CRITICAL | js,ts,sol | Approve + transferFrom patterns |
|
|
233
295
|
| 10 | UNLIMITED_APPROVAL | HIGH | js,ts,sol | Unlimited token approvals |
|
|
234
296
|
| 11 | DANGEROUS_SELFDESTRUCT | HIGH | sol | selfdestruct in contracts |
|
|
@@ -246,6 +308,19 @@ For each rule, use Grep to search the relevant file types. Record every match wi
|
|
|
246
308
|
| 23 | SUSPICIOUS_IP | MEDIUM | all | Hardcoded public IPv4 addresses |
|
|
247
309
|
| 24 | SOCIAL_ENGINEERING | HIGH | md | Pressure language + execution instructions |
|
|
248
310
|
|
|
311
|
+
### Git Context Check (Rules 7 & 8 only)
|
|
312
|
+
|
|
313
|
+
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:
|
|
314
|
+
|
|
315
|
+
1. **Not in a git repo** — if `git -C <file_dir> rev-parse --git-dir 2>/dev/null` returns nothing → keep **CRITICAL**. Stop.
|
|
316
|
+
2. **Ever committed** — run `git -C <file_dir> log --all --oneline -- <file_path>`. If output is non-empty → keep **CRITICAL**. Stop.
|
|
317
|
+
3. **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.
|
|
318
|
+
4. **Gitignored** — exit code 0 → downgrade to **MEDIUM**.
|
|
319
|
+
|
|
320
|
+
Record the git context result (`committed` / `not-ignored` / `gitignored` / `no-git-repo`) in the finding's Evidence column alongside the matched content.
|
|
321
|
+
|
|
322
|
+
**Important**: these checks require `git` to be available. If `git` is not in PATH, skip the check and keep **CRITICAL**.
|
|
323
|
+
|
|
249
324
|
### Risk Level Calculation
|
|
250
325
|
|
|
251
326
|
- Any **CRITICAL** finding -> Overall **CRITICAL**
|
|
@@ -261,7 +336,7 @@ For each rule, use Grep to search the relevant file types. Record every match wi
|
|
|
261
336
|
**Target**: <scanned path>
|
|
262
337
|
**Risk Level**: CRITICAL | HIGH | MEDIUM | LOW
|
|
263
338
|
**Files Scanned**: <count>
|
|
264
|
-
**Total Findings**: <count>
|
|
339
|
+
**Total Findings**: <count of non-suppressed findings>
|
|
265
340
|
|
|
266
341
|
### Findings
|
|
267
342
|
|
|
@@ -271,7 +346,10 @@ For each rule, use Grep to search the relevant file types. Record every match wi
|
|
|
271
346
|
|
|
272
347
|
### Summary
|
|
273
348
|
<Human-readable summary of key risks, impact, and recommendations>
|
|
349
|
+
|
|
350
|
+
> N finding(s) suppressed via .agentguard-suppress.yaml
|
|
274
351
|
```
|
|
352
|
+
(Omit the suppression note line if no suppression file was found or no findings were suppressed.)
|
|
275
353
|
|
|
276
354
|
### Post-Scan Trust Registration
|
|
277
355
|
|
|
@@ -294,15 +372,53 @@ After outputting the scan report, if the scanned target appears to be a skill (c
|
|
|
294
372
|
- `id`: the directory name of the scanned path
|
|
295
373
|
- `source`: the absolute path to the scanned directory
|
|
296
374
|
- `version`: read the `version` field from `package.json` in the scanned directory using the Read tool (if present), otherwise use `unknown`
|
|
297
|
-
- `hash`: compute by running AgentGuard's own script: `node scripts/trust-cli.
|
|
375
|
+
- `hash`: compute by running AgentGuard's own script: `node scripts/trust-cli.js hash --path <scanned_path>` and extracting the `hash` field from the JSON output
|
|
298
376
|
3. Show the user the full registration command and ask for confirmation before executing:
|
|
299
377
|
```
|
|
300
|
-
node scripts/trust-cli.
|
|
378
|
+
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
|
|
301
379
|
```
|
|
302
380
|
4. Only execute after user approval. Show the registration result.
|
|
303
381
|
|
|
304
382
|
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`.
|
|
305
383
|
|
|
384
|
+
### SARIF Output Flow (when `--format sarif` is present)
|
|
385
|
+
|
|
386
|
+
**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:
|
|
387
|
+
|
|
388
|
+
**Step A — Assemble findings as structured JSON** and write to `/tmp/agentguard-scan-findings.json`:
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"target": "<scanned path>",
|
|
393
|
+
"scanned_at": "<ISO 8601 timestamp>",
|
|
394
|
+
"files_scanned": <number>,
|
|
395
|
+
"risk_level": "<CRITICAL|HIGH|MEDIUM|LOW>",
|
|
396
|
+
"findings": [
|
|
397
|
+
{
|
|
398
|
+
"rule_id": "<RULE_ID>",
|
|
399
|
+
"severity": "<CRITICAL|HIGH|MEDIUM|LOW>",
|
|
400
|
+
"file": "<relative/path/to/file.ext>",
|
|
401
|
+
"line": <line number>,
|
|
402
|
+
"evidence": "<matched content snippet>"
|
|
403
|
+
}
|
|
404
|
+
]
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Use relative paths for `file` (relative to the scan target root). If no findings, use `"findings": []`.
|
|
409
|
+
|
|
410
|
+
**Step B — Run the SARIF converter** (cd into the skill directory first):
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
cd <skill_directory> && node scripts/scan-to-sarif.js --file /tmp/agentguard-scan-findings.json
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Step C — Handle output**:
|
|
417
|
+
- If `--output <file>` was specified: write the SARIF JSON to that file using the Write tool, then tell the user the file path.
|
|
418
|
+
- Otherwise: print the SARIF JSON to stdout (the user will redirect it, e.g. `> findings.sarif`).
|
|
419
|
+
|
|
420
|
+
**Do NOT** output the standard markdown report when `--format sarif` is active. Skip the Post-Scan Trust Registration offer.
|
|
421
|
+
|
|
306
422
|
---
|
|
307
423
|
|
|
308
424
|
## Subcommand: action
|
|
@@ -342,27 +458,27 @@ Parse the user's action description and apply the appropriate detector:
|
|
|
342
458
|
|
|
343
459
|
### Web3 Enhanced Detection
|
|
344
460
|
|
|
345
|
-
When the action involves **web3_tx** or **web3_sign**, use AgentGuard's bundled `action-cli.
|
|
461
|
+
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):
|
|
346
462
|
|
|
347
463
|
For web3_tx:
|
|
348
464
|
```
|
|
349
|
-
node scripts/action-cli.
|
|
465
|
+
node scripts/action-cli.js decide --type web3_tx --chain-id <id> --from <addr> --to <addr> --value <wei> [--data <calldata>] [--origin <url>] [--user-present]
|
|
350
466
|
```
|
|
351
467
|
|
|
352
468
|
For web3_sign:
|
|
353
469
|
```
|
|
354
|
-
node scripts/action-cli.
|
|
470
|
+
node scripts/action-cli.js decide --type web3_sign --chain-id <id> --signer <addr> [--message <msg>] [--typed-data <json>] [--origin <url>] [--user-present]
|
|
355
471
|
```
|
|
356
472
|
|
|
357
473
|
For standalone transaction simulation:
|
|
358
474
|
```
|
|
359
|
-
node scripts/action-cli.
|
|
475
|
+
node scripts/action-cli.js simulate --chain-id <id> --from <addr> --to <addr> --value <wei> [--data <calldata>] [--origin <url>]
|
|
360
476
|
```
|
|
361
477
|
|
|
362
478
|
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:
|
|
363
479
|
|
|
364
480
|
```
|
|
365
|
-
node scripts/action-cli.
|
|
481
|
+
node scripts/action-cli.js decide --type exec_command --command "<cmd>" [--skill-source <source>] [--skill-id <id>]
|
|
366
482
|
```
|
|
367
483
|
|
|
368
484
|
Parse the JSON output and incorporate findings into your evaluation:
|
|
@@ -394,29 +510,25 @@ Always combine script results with the policy-based checks (webhook domains, sec
|
|
|
394
510
|
|
|
395
511
|
## Subcommand: patrol
|
|
396
512
|
|
|
397
|
-
**
|
|
513
|
+
**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.
|
|
398
514
|
|
|
399
515
|
For detailed check definitions, commands, and thresholds, see [patrol-checks.md](patrol-checks.md).
|
|
400
516
|
|
|
401
517
|
### Sub-subcommands
|
|
402
518
|
|
|
403
519
|
- **`patrol`** or **`patrol run`** — Execute all 8 checks and output a patrol report
|
|
404
|
-
- **`patrol setup`** — Configure as
|
|
520
|
+
- **`patrol setup`** — Configure as a daily cron job (OpenClaw or system crontab)
|
|
405
521
|
- **`patrol status`** — Show last patrol results and cron schedule
|
|
406
522
|
|
|
407
|
-
###
|
|
523
|
+
### Platform Detection
|
|
408
524
|
|
|
409
|
-
Before running
|
|
525
|
+
Before running `patrol setup` or `patrol status`, detect the available scheduling platform:
|
|
410
526
|
|
|
411
|
-
1. Check for `$OPENCLAW_STATE_DIR` env var
|
|
412
|
-
2.
|
|
413
|
-
3.
|
|
527
|
+
1. **OpenClaw**: Check for `$OPENCLAW_STATE_DIR` env var (fall back to `~/.openclaw/`), verify the directory exists and contains `openclaw.json`, and check if `openclaw` CLI is in PATH. If all three pass → use OpenClaw path.
|
|
528
|
+
2. **System crontab**: Check if `crontab` command is available in PATH → use crontab path.
|
|
529
|
+
3. **Neither available**: Inform the user and output the manual cron entry for them to add themselves.
|
|
414
530
|
|
|
415
|
-
|
|
416
|
-
```
|
|
417
|
-
This command requires an OpenClaw environment. Detected: <what was found/missing>
|
|
418
|
-
For non-OpenClaw environments, use /agentguard scan and /agentguard report instead.
|
|
419
|
-
```
|
|
531
|
+
For `patrol run`, no scheduling platform is needed — run checks on any platform.
|
|
420
532
|
|
|
421
533
|
Set `$OC` to the resolved OpenClaw state directory for all subsequent checks.
|
|
422
534
|
|
|
@@ -428,8 +540,8 @@ Detect tampered or unregistered skill packages by comparing file hashes against
|
|
|
428
540
|
|
|
429
541
|
**Steps**:
|
|
430
542
|
1. Discover skill directories under `$OC/skills/` (look for dirs containing `SKILL.md`)
|
|
431
|
-
2. For each skill, compute hash: `node scripts/trust-cli.
|
|
432
|
-
3. Look up the attested hash: `node scripts/trust-cli.
|
|
543
|
+
2. For each skill, compute hash: `node scripts/trust-cli.js hash --path <skill_dir>`
|
|
544
|
+
3. Look up the attested hash: `node scripts/trust-cli.js lookup --source <skill_dir>`
|
|
433
545
|
4. If hash differs from attested → **INTEGRITY_DRIFT** (HIGH)
|
|
434
546
|
5. If skill has no trust record → **UNREGISTERED_SKILL** (MEDIUM)
|
|
435
547
|
6. For drifted skills, run the scan rules against the changed files to detect new threats
|
|
@@ -473,13 +585,13 @@ Audit all cron jobs for download-and-execute patterns.
|
|
|
473
585
|
Detect suspicious file modifications in the last 24 hours.
|
|
474
586
|
|
|
475
587
|
**Steps**:
|
|
476
|
-
1. Find recently modified files:
|
|
588
|
+
1. Find recently modified files: use Glob with patterns `$OC/**/*`, `~/.ssh/**/*`, `~/.gnupg/**/*` and filter results by mtime within 24h using `stat -f '%m %N' <file>` (macOS) or `stat -c '%Y %n' <file>` (Linux) — do NOT use the `find` binary as it may be unavailable in hardened environments
|
|
477
589
|
2. For modified files with scannable extensions (.js/.ts/.py/.sh/.md/.json), run the full scan rule set
|
|
478
590
|
3. Check permissions on critical files:
|
|
479
591
|
- `$OC/openclaw.json` → should be 600
|
|
480
592
|
- `$OC/devices/paired.json` → should be 600
|
|
481
593
|
- `~/.ssh/authorized_keys` → should be 600
|
|
482
|
-
4. Detect new executable files in workspace:
|
|
594
|
+
4. Detect new executable files in workspace: use Glob `$OC/workspace/**/*` and check each file's executable bit with `stat` — do NOT use `find` with `-perm`
|
|
483
595
|
|
|
484
596
|
#### [6] Audit Log Analysis (24h)
|
|
485
597
|
|
|
@@ -510,7 +622,7 @@ Verify security configuration is production-appropriate.
|
|
|
510
622
|
Check for expired, stale, or over-privileged trust records.
|
|
511
623
|
|
|
512
624
|
**Steps**:
|
|
513
|
-
1. List all records: `node scripts/trust-cli.
|
|
625
|
+
1. List all records: `node scripts/trust-cli.js list`
|
|
514
626
|
2. Flag:
|
|
515
627
|
- Expired attestations (`expires_at` in the past)
|
|
516
628
|
- Trusted skills not re-scanned in 30+ days
|
|
@@ -563,17 +675,20 @@ After outputting the report, append a summary entry to `~/.agentguard/audit.json
|
|
|
563
675
|
|
|
564
676
|
### patrol setup
|
|
565
677
|
|
|
566
|
-
Configure the patrol as
|
|
678
|
+
Configure the patrol as a daily cron job. Detects the available platform and uses the appropriate method.
|
|
567
679
|
|
|
568
680
|
**Steps**:
|
|
569
681
|
|
|
570
|
-
1.
|
|
682
|
+
1. Run platform detection (see above).
|
|
571
683
|
2. Ask the user for:
|
|
572
|
-
- **Timezone** (default: UTC). Examples: `Asia/Shanghai`, `America/New_York`, `Europe/London`
|
|
573
684
|
- **Schedule** (default: `0 3 * * *` — daily at 03:00)
|
|
574
|
-
- **
|
|
685
|
+
- **Timezone** (default: UTC). Examples: `Asia/Shanghai`, `America/New_York`, `Europe/London`
|
|
686
|
+
- **Notification channel** (optional, OpenClaw only): `telegram`, `discord`, `signal`
|
|
575
687
|
- **Chat ID / webhook** (required if channel is set)
|
|
576
|
-
|
|
688
|
+
|
|
689
|
+
#### Path A — OpenClaw available
|
|
690
|
+
|
|
691
|
+
Generate and show the OpenClaw cron registration command:
|
|
577
692
|
|
|
578
693
|
```bash
|
|
579
694
|
openclaw cron add \
|
|
@@ -591,11 +706,41 @@ openclaw cron add \
|
|
|
591
706
|
--to <chat-id>
|
|
592
707
|
```
|
|
593
708
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
709
|
+
**Show the exact command and wait for explicit user confirmation before executing.**
|
|
710
|
+
After execution, verify with `openclaw cron list`.
|
|
711
|
+
|
|
712
|
+
> **Note**: `--timeout-seconds 300` is required because isolated sessions need cold-start time.
|
|
713
|
+
|
|
714
|
+
#### Path B — System crontab available (OpenClaw not available)
|
|
715
|
+
|
|
716
|
+
Resolve the absolute path to this skill's directory (parent of this SKILL.md file) as `<SKILL_DIR>`.
|
|
717
|
+
|
|
718
|
+
Validate before generating the entry:
|
|
719
|
+
- `<schedule>` must be a standard five-field cron expression. Reject values that contain newlines.
|
|
720
|
+
- `<SKILL_DIR>` must be an absolute path. Reject paths containing single quotes, double quotes, null bytes, or newlines.
|
|
721
|
+
- Do not include notification channel, chat ID, or webhook values in the system crontab entry. System cron writes only to the local patrol log.
|
|
722
|
+
|
|
723
|
+
Generate the crontab entry using a single-quoted skill directory. If `<SKILL_DIR>` contains spaces, keep it inside the quotes exactly as shown:
|
|
724
|
+
```
|
|
725
|
+
<schedule> cd '<SKILL_DIR>' && AGENTGUARD_AUTO_SCAN=1 node scripts/auto-scan.js >> "$HOME/.agentguard/patrol.log" 2>&1
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**Show the exact entry and wait for explicit user confirmation before writing.**
|
|
729
|
+
|
|
730
|
+
After confirmation, add the entry to the user's crontab:
|
|
731
|
+
```bash
|
|
732
|
+
(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 -
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
Verify with `crontab -l | grep agentguard`.
|
|
597
736
|
|
|
598
|
-
|
|
737
|
+
#### Path C — Neither available
|
|
738
|
+
|
|
739
|
+
Output the crontab entry for the user to add manually:
|
|
740
|
+
```
|
|
741
|
+
<schedule> cd '<SKILL_DIR>' && AGENTGUARD_AUTO_SCAN=1 node scripts/auto-scan.js >> "$HOME/.agentguard/patrol.log" 2>&1
|
|
742
|
+
```
|
|
743
|
+
Explain that neither `openclaw` nor `crontab` was found in PATH, so the entry must be added manually.
|
|
599
744
|
|
|
600
745
|
### patrol status
|
|
601
746
|
|
|
@@ -603,11 +748,10 @@ Show the current patrol state.
|
|
|
603
748
|
|
|
604
749
|
**Steps**:
|
|
605
750
|
|
|
606
|
-
1. Read `~/.agentguard/audit.jsonl`, find the most recent `event: "patrol"` entry
|
|
607
|
-
2.
|
|
608
|
-
3.
|
|
609
|
-
4. If cron is configured
|
|
610
|
-
5. If cron is not configured, suggest: `/agentguard patrol setup`
|
|
751
|
+
1. Read `~/.agentguard/audit.jsonl`, find the most recent `event: "patrol"` or `event: "auto_scan"` entry. If found, display: timestamp, overall status, finding counts.
|
|
752
|
+
2. **OpenClaw available**: run `openclaw cron list` and look for `agentguard-patrol`. Show schedule, timezone, last/next run time if found.
|
|
753
|
+
3. **System crontab available**: run `crontab -l 2>/dev/null | grep agentguard`. Show the matching entry if found.
|
|
754
|
+
4. If no cron is configured on any platform, suggest: `/agentguard patrol setup`.
|
|
611
755
|
|
|
612
756
|
---
|
|
613
757
|
|
|
@@ -648,23 +792,127 @@ web3.tx_policy: 'allow' | 'confirm_high_risk' | 'deny'
|
|
|
648
792
|
|
|
649
793
|
### Operations
|
|
650
794
|
|
|
651
|
-
**lookup** — `node scripts/trust-cli.
|
|
795
|
+
**lookup** — `node scripts/trust-cli.js lookup --source <source> --version <version>`
|
|
652
796
|
Query the registry for a skill's trust record.
|
|
653
797
|
|
|
654
|
-
**attest** — `node scripts/trust-cli.
|
|
798
|
+
**attest** — `node scripts/trust-cli.js attest --id <id> --source <source> --version <version> --hash <hash> --trust-level <level> --preset <preset> --reviewed-by <name>`
|
|
655
799
|
Create or update a trust record. Use `--preset` for common capability models or provide `--capabilities <json>` for custom.
|
|
656
800
|
|
|
657
|
-
**revoke** — `node scripts/trust-cli.
|
|
801
|
+
**revoke** — `node scripts/trust-cli.js revoke --source <source> --reason <reason>`
|
|
658
802
|
Revoke trust for a skill. Supports `--source-pattern` for wildcards.
|
|
659
803
|
|
|
660
|
-
**list** — `node scripts/trust-cli.
|
|
804
|
+
**list** — `node scripts/trust-cli.js list [--trust-level <level>] [--status <status>]`
|
|
661
805
|
List all trust records with optional filters.
|
|
662
806
|
|
|
807
|
+
**seed** — `agentguard trust seed [--auto-attest-low-risk] [--auto-attest-medium-risk] [--dry-run]`
|
|
808
|
+
Batch-scan all installed skills and auto-attest those meeting the risk threshold. Designed for initial baseline setup when many skills are already installed.
|
|
809
|
+
|
|
810
|
+
Flags:
|
|
811
|
+
- `--auto-attest-low-risk` (default when `seed` is invoked): attest LOW-risk skills as `trusted` with `read_only` preset.
|
|
812
|
+
- `--auto-attest-medium-risk`: also attest MEDIUM-risk skills as `restricted` with `none` preset.
|
|
813
|
+
- `--dry-run`: preview only — show the plan table without executing any attest commands.
|
|
814
|
+
|
|
815
|
+
**HIGH and CRITICAL risk skills are never auto-attested** regardless of flags. They must be reviewed and attested manually.
|
|
816
|
+
|
|
817
|
+
#### seed Flow
|
|
818
|
+
|
|
819
|
+
**Step 1 — Discover skills**
|
|
820
|
+
|
|
821
|
+
Glob all of the following paths for `*/SKILL.md` (same as checkup):
|
|
822
|
+
- `~/.claude/skills/*/SKILL.md`
|
|
823
|
+
- `~/.openclaw/skills/*/SKILL.md`
|
|
824
|
+
- `~/.openclaw/workspace/skills/*/SKILL.md`
|
|
825
|
+
- `~/.qclaw/skills/*/SKILL.md`
|
|
826
|
+
- `~/.qclaw/workspace/skills/*/SKILL.md`
|
|
827
|
+
|
|
828
|
+
Skip `agentguard` itself. Collect the parent directory of each found `SKILL.md` as the skill path.
|
|
829
|
+
|
|
830
|
+
**Step 2 — Filter unregistered skills**
|
|
831
|
+
|
|
832
|
+
For each discovered skill, run:
|
|
833
|
+
```
|
|
834
|
+
node scripts/trust-cli.js lookup --source <skill_path>
|
|
835
|
+
```
|
|
836
|
+
If the lookup returns a record with `status: active`, the skill is already registered — skip it and note "already registered" in the summary. Only proceed with skills that have no active trust record.
|
|
837
|
+
|
|
838
|
+
**Step 3 — Scan unregistered skills**
|
|
839
|
+
|
|
840
|
+
For each unregistered skill, run the full scan (24 detection rules, same as `/agentguard scan <skill_path>`). Record: skill name, skill path, risk level (LOW/MEDIUM/HIGH/CRITICAL), finding count.
|
|
841
|
+
|
|
842
|
+
**Step 4 — Build preview table**
|
|
843
|
+
|
|
844
|
+
Output a plan table before taking any action:
|
|
845
|
+
|
|
846
|
+
```
|
|
847
|
+
## AgentGuard Trust Seed — Plan
|
|
848
|
+
|
|
849
|
+
Scanned <N> unregistered skills. Proposed actions:
|
|
850
|
+
|
|
851
|
+
| Skill | Path | Risk | Findings | Proposed Action |
|
|
852
|
+
|-------|------|------|----------|-----------------|
|
|
853
|
+
| foo | ~/.claude/skills/foo | LOW | 0 | ✅ attest trusted/read_only |
|
|
854
|
+
| bar | ~/.claude/skills/bar | MEDIUM | 2 | ⚠️ attest restricted/none (requires --auto-attest-medium-risk) |
|
|
855
|
+
| baz | ~/.claude/skills/baz | HIGH | 5 | 🚫 SKIP — manual review required |
|
|
856
|
+
| qux | ~/.claude/skills/qux | CRITICAL | 8 | 🚫 SKIP — manual review required |
|
|
857
|
+
|
|
858
|
+
Already registered (skipped): <M> skills
|
|
859
|
+
Will attest: <K> skills
|
|
860
|
+
Will skip (HIGH/CRITICAL): <J> skills
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
If `--dry-run` is present: output this table and stop. Add: `Dry run complete — no changes made. Remove --dry-run to execute.`
|
|
864
|
+
|
|
865
|
+
**Step 5 — User confirmation (REQUIRED)**
|
|
866
|
+
|
|
867
|
+
After showing the plan table, **always ask for explicit user confirmation** before executing any attest commands:
|
|
868
|
+
|
|
869
|
+
> "Ready to attest <K> skill(s). Confirm? (yes/no)"
|
|
870
|
+
|
|
871
|
+
Do NOT proceed without a clear affirmative response. If the user declines, stop and suggest `--dry-run` for future previews.
|
|
872
|
+
|
|
873
|
+
**Step 6 — Batch attest**
|
|
874
|
+
|
|
875
|
+
For each skill approved for attestation, compute its hash and run attest:
|
|
876
|
+
|
|
877
|
+
```bash
|
|
878
|
+
# Compute hash
|
|
879
|
+
node scripts/trust-cli.js hash --path <skill_path>
|
|
880
|
+
|
|
881
|
+
# Attest
|
|
882
|
+
node scripts/trust-cli.js attest \
|
|
883
|
+
--id <skill_dir_name> \
|
|
884
|
+
--source <skill_path> \
|
|
885
|
+
--version <version_from_package.json_or_unknown> \
|
|
886
|
+
--hash <computed_hash> \
|
|
887
|
+
--trust-level <trusted|restricted> \
|
|
888
|
+
--preset <read_only|none> \
|
|
889
|
+
--reviewed-by agentguard-seed \
|
|
890
|
+
--notes "Auto-attested by trust seed. Scan risk: <risk_level>. Findings: <count>." \
|
|
891
|
+
--force
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
Run these sequentially (not in parallel) to avoid registry write conflicts.
|
|
895
|
+
|
|
896
|
+
**Step 7 — Result summary**
|
|
897
|
+
|
|
898
|
+
```
|
|
899
|
+
## Trust Seed Complete
|
|
900
|
+
|
|
901
|
+
✅ Attested: <N> skills
|
|
902
|
+
⚠️ Skipped (already registered): <M> skills
|
|
903
|
+
🚫 Skipped (HIGH/CRITICAL risk — manual review required): <J> skills
|
|
904
|
+
❌ Failed: <K> skills (list errors)
|
|
905
|
+
|
|
906
|
+
Skills requiring manual review:
|
|
907
|
+
- <skill_name> (<path>) — Risk: HIGH/CRITICAL, <N> findings
|
|
908
|
+
Run: /agentguard scan <path> then /agentguard trust attest ...
|
|
909
|
+
```
|
|
910
|
+
|
|
663
911
|
### Script Execution
|
|
664
912
|
|
|
665
913
|
If the agentguard package is installed, execute trust operations via AgentGuard's own bundled script:
|
|
666
914
|
```
|
|
667
|
-
node scripts/trust-cli.
|
|
915
|
+
node scripts/trust-cli.js <subcommand> [args]
|
|
668
916
|
```
|
|
669
917
|
|
|
670
918
|
For operations that modify the trust registry (`attest`, `revoke`), always show the user the exact command and ask for explicit confirmation before executing.
|
|
@@ -761,7 +1009,15 @@ If the log file doesn't exist, inform the user that no security events have been
|
|
|
761
1009
|
|
|
762
1010
|
## Subcommand: checkup
|
|
763
1011
|
|
|
764
|
-
Run a comprehensive agent health checkup across
|
|
1012
|
+
Run a comprehensive agent health checkup across 5 security dimensions. Generates a visual HTML report with a lobster mascot and opens it in the browser. The lobster's appearance reflects the agent's health: muscular bodybuilder (score 90+), healthy with shield (70–89), tired with coffee (50–69), or sick with bandages (0–49).
|
|
1013
|
+
|
|
1014
|
+
**Scoring is handled by `checkup-score.js` — you MUST NOT calculate scores yourself. Your role is to collect raw facts, assemble them into structured JSON, and pass to the script.**
|
|
1015
|
+
|
|
1016
|
+
**Argument parsing**: Extract from `$ARGUMENTS`:
|
|
1017
|
+
- `--format json` flag: skip HTML generation and write the checkup JSON to a file instead
|
|
1018
|
+
- `--output <file>` flag: path for the JSON output file (required when `--format json` is used; defaults to `/tmp/agentguard-checkup-data.json` if omitted)
|
|
1019
|
+
|
|
1020
|
+
If `--format json` is present, follow the modified flow noted in Step 4 below.
|
|
765
1021
|
|
|
766
1022
|
Plain `checkup` must always run this comprehensive workflow, even if the user phrases it as `agentguard checkup`. Do not answer that an advisory ID is required. Advisory IDs are optional and only switch to the targeted threat-feed self-check mode described below.
|
|
767
1023
|
|
|
@@ -778,6 +1034,8 @@ That CLI path fetches the current Cloud advisory feed and checks local skills ag
|
|
|
778
1034
|
|
|
779
1035
|
**IMPORTANT: You MUST run ALL 7 checks below — not just the skill scan. The checkup covers 5 security dimensions, not just code scanning. Do NOT skip checks 2–7.**
|
|
780
1036
|
|
|
1037
|
+
**EVIDENCE RULE: Every finding you report MUST be backed by actual tool output collected in this step. You MUST quote the exact command output (or "no output" if the command returned nothing) in the finding's evidence field. Findings without concrete evidence from tool execution are FORBIDDEN — do not infer, assume, or fabricate results.**
|
|
1038
|
+
|
|
781
1039
|
Run these checks in parallel where possible. These are **universal agent security checks** — they apply to any Claude Code or OpenClaw environment, regardless of whether AgentGuard is installed.
|
|
782
1040
|
|
|
783
1041
|
1. **[REQUIRED] Discover & scan installed skills** (→ feeds Dimension 1: Code Safety): Glob ALL of the following paths for `*/SKILL.md`:
|
|
@@ -787,164 +1045,131 @@ Run these checks in parallel where possible. These are **universal agent securit
|
|
|
787
1045
|
- `~/.qclaw/skills/*/SKILL.md`
|
|
788
1046
|
- `~/.qclaw/workspace/skills/*/SKILL.md`
|
|
789
1047
|
|
|
790
|
-
For **every** discovered skill, **run `/agentguard scan <skill_path>`** using the scan subcommand logic (24 detection rules). Do NOT skip any skill regardless of how many are found.
|
|
1048
|
+
For **every** discovered skill, **run `/agentguard scan <skill_path>`** using the scan subcommand logic (24 detection rules). Do NOT skip any skill regardless of how many are found. Record for each skill: name, risk_level, and exact findings list (rule, severity, file, line).
|
|
791
1049
|
2. **[REQUIRED] Credential file permissions** (→ feeds Dimension 2: Credential Safety): Platform-aware check — behavior differs by OS:
|
|
792
|
-
- **macOS/Linux**: Run `stat -f '%Lp' <path> 2>/dev/null || stat -c '%a' <path> 2>/dev/null` on `~/.ssh/`, `~/.gnupg
|
|
793
|
-
- **Windows**: `stat` is not available. Use `icacls <path>` to check ACLs instead. If
|
|
1050
|
+
- **macOS/Linux**: Run `stat -f '%Lp' <path> 2>/dev/null || stat -c '%a' <path> 2>/dev/null` on `~/.ssh/`, `~/.gnupg/`. **If the command returns empty output, the directory does not exist — record `exists: false`.**
|
|
1051
|
+
- **Windows**: `stat` is not available. Use `icacls <path>` to check ACLs instead. If directory doesn't exist, record `exists: false`. If it exists, record whether the ACL grants access to `Everyone`, `Users`, or `Authenticated Users`.
|
|
1052
|
+
- Also check OpenClaw config files if applicable (`$OC/openclaw.json`, `$OC/devices/paired.json`).
|
|
794
1053
|
3. **[REQUIRED] Sensitive credential scan / DLP** (→ feeds Dimension 2: Credential Safety): Use Grep to scan **all** agent workspace directories for leaked secrets. This MUST cover the entire workspace root, not just the current agent's directory:
|
|
795
|
-
- For OpenClaw / QClaw: scan `~/.openclaw/workspace/` and `~/.qclaw/workspace/` recursively
|
|
1054
|
+
- For OpenClaw / QClaw: scan `~/.openclaw/workspace/` and `~/.qclaw/workspace/` recursively
|
|
796
1055
|
- For Claude Code: scan `~/.claude/` recursively
|
|
797
1056
|
- For Hermes Agent: scan `~/.hermes/` recursively
|
|
798
1057
|
- Patterns to detect:
|
|
799
1058
|
- Private keys: `0x[a-fA-F0-9]{64}`, `-----BEGIN.*PRIVATE KEY-----`
|
|
800
1059
|
- Mnemonics: sequences of 12+ BIP-39 words, `seed_phrase`, `mnemonic`
|
|
801
1060
|
- API keys/tokens: `AKIA[0-9A-Z]{16}`, `gh[pousr]_[A-Za-z0-9_]{36}`, plaintext passwords
|
|
1061
|
+
- Record: `private_keys_found`, `mnemonics_found`, `api_keys_found` (boolean, with location if found).
|
|
802
1062
|
- **Important**: Use the workspace *root* directory as the scan target (e.g. `~/.qclaw/workspace/`), not a specific agent subdirectory. All sibling `workspace-agent-*` directories must be included.
|
|
803
|
-
4. **[REQUIRED] Network exposure** (→ feeds Dimension 3: Network & System): Run `lsof -i -P -n 2>/dev/null | grep LISTEN` or `ss -tlnp 2>/dev/null` to check for dangerous open ports (Redis 6379, Docker API 2375, MySQL 3306, MongoDB 27017 on 0.0.0.0)
|
|
804
|
-
5. **[REQUIRED] Scheduled tasks audit** (→ feeds Dimension 3: Network & System): Check `crontab -l 2>/dev/null` for suspicious entries containing `curl|bash`, `wget|sh`, or accessing `~/.ssh
|
|
805
|
-
6. **[REQUIRED] Environment variable exposure** (→ feeds Dimension 3: Network & System): Run `env` and check for sensitive variable names (`PRIVATE_KEY`, `MNEMONIC`, `SECRET`, `PASSWORD`) — detect presence only, mask values
|
|
806
|
-
7. **[REQUIRED] Runtime protection check** (→ feeds Dimension 4: Runtime Protection): Check if security hooks exist in `~/.claude/settings.json`, `~/.openclaw/openclaw.json`, or `~/.hermes/config.yaml
|
|
807
|
-
|
|
808
|
-
### Step 2: Score Calculation
|
|
809
|
-
|
|
810
|
-
**Additive scoring**: Each dimension starts at **0**. For each check that **passes**, add the listed points. Maximum is 100 per dimension. **Every failed check = 1 finding with severity and description.**
|
|
811
|
-
|
|
812
|
-
#### Dimension 1: Skill & Code Safety (weight: 25%)
|
|
1063
|
+
4. **[REQUIRED] Network exposure** (→ feeds Dimension 3: Network & System): Run `lsof -i -P -n 2>/dev/null | grep LISTEN` or `ss -tlnp 2>/dev/null` to check for dangerous open ports (Redis 6379, Docker API 2375, MySQL 3306, MongoDB 27017 on 0.0.0.0). Record list of dangerous ports found (e.g. `["Redis on 0.0.0.0:6379"]`).
|
|
1064
|
+
5. **[REQUIRED] Scheduled tasks audit** (→ feeds Dimension 3: Network & System): Check `crontab -l 2>/dev/null` for suspicious entries containing `curl|bash`, `wget|sh`, or accessing `~/.ssh/`. Record list of suspicious cron command strings found.
|
|
1065
|
+
6. **[REQUIRED] Environment variable exposure** (→ feeds Dimension 3: Network & System): Run `env` and check for sensitive variable names (`PRIVATE_KEY`, `MNEMONIC`, `SECRET`, `PASSWORD`) — detect presence only, mask values. Record list of sensitive variable names found.
|
|
1066
|
+
7. **[REQUIRED] Runtime protection check** (→ feeds Dimension 4: Runtime Protection): Check if security hooks exist in `~/.claude/settings.json`, `~/.openclaw/openclaw.json`, or `~/.hermes/config.yaml`. Check for audit logs at `~/.agentguard/audit.jsonl`. Check if installed skills have been previously scanned (audit log contains `scan` events). Record booleans: `hooks_installed`, `audit_log_exists`, `skills_ever_scanned`.
|
|
813
1067
|
|
|
814
|
-
|
|
1068
|
+
### Step 2: Assemble Raw Facts JSON
|
|
815
1069
|
|
|
816
|
-
|
|
817
|
-
- Each CRITICAL finding: **−15**
|
|
818
|
-
- Each HIGH finding: **−8**
|
|
819
|
-
- Each MEDIUM finding: **−3**
|
|
820
|
-
- Floor at **0** (never negative)
|
|
1070
|
+
After completing all 7 checks, assemble the raw facts into a structured JSON and write it to a temporary file (e.g. `/tmp/agentguard-raw-facts.json`):
|
|
821
1071
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
| Check | Points if PASS | If FAIL → finding |
|
|
863
|
-
|-------|---------------|-------------------|
|
|
864
|
-
| Security hooks/guards installed (AgentGuard, custom hooks, etc.) | **+40** | "No security hooks installed — actions are unmonitored" (HIGH) |
|
|
865
|
-
| Security audit log exists with recent events | **+30** | "No security audit log — no threat history available" (MEDIUM) |
|
|
866
|
-
| Skills have been security-scanned at least once | **+30** | "Installed skills have never been security-scanned" (MEDIUM) |
|
|
867
|
-
|
|
868
|
-
#### Dimension 5: Web3 Safety (weight: 15% if applicable)
|
|
1072
|
+
```json
|
|
1073
|
+
{
|
|
1074
|
+
"skills": [
|
|
1075
|
+
{
|
|
1076
|
+
"name": "<skill-name>",
|
|
1077
|
+
"risk_level": "<low|medium|high|critical>",
|
|
1078
|
+
"findings": [
|
|
1079
|
+
{ "rule": "<RULE_ID>", "severity": "<CRITICAL|HIGH|MEDIUM|LOW>", "file": "<filename>", "line": <number> }
|
|
1080
|
+
]
|
|
1081
|
+
}
|
|
1082
|
+
],
|
|
1083
|
+
"credential_files": {
|
|
1084
|
+
"ssh_dir": { "exists": <bool>, "permissions": "<octal string, e.g. 700>" },
|
|
1085
|
+
"gnupg_dir": { "exists": <bool>, "permissions": "<octal string>" },
|
|
1086
|
+
"openclaw_config": { "exists": <bool>, "ok": <bool> }
|
|
1087
|
+
},
|
|
1088
|
+
"dlp": {
|
|
1089
|
+
"private_keys_found": <bool>,
|
|
1090
|
+
"mnemonics_found": <bool>,
|
|
1091
|
+
"api_keys_found": <bool>
|
|
1092
|
+
},
|
|
1093
|
+
"network": {
|
|
1094
|
+
"dangerous_ports": ["<description>"],
|
|
1095
|
+
"suspicious_crons": ["<command>"],
|
|
1096
|
+
"sensitive_env_vars": ["<VAR_NAME>"],
|
|
1097
|
+
"openclaw_config_ok": <bool|null>
|
|
1098
|
+
},
|
|
1099
|
+
"runtime": {
|
|
1100
|
+
"hooks_installed": <bool>,
|
|
1101
|
+
"audit_log_exists": <bool>,
|
|
1102
|
+
"skills_ever_scanned": <bool>
|
|
1103
|
+
},
|
|
1104
|
+
"web3": {
|
|
1105
|
+
"detected": <bool>,
|
|
1106
|
+
"wallet_draining_found": <bool>,
|
|
1107
|
+
"unlimited_approval_found": <bool>,
|
|
1108
|
+
"goplus_configured": <bool>
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
```
|
|
869
1112
|
|
|
870
|
-
|
|
1113
|
+
**Web3 detection**: set `detected: true` if any of these are present: env vars `GOPLUS_API_KEY`, `CHAIN_ID`, or `RPC_URL`; or any skill with web3-related findings (WALLET_DRAINING, UNLIMITED_APPROVAL).
|
|
871
1114
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1115
|
+
**Pre-Step-3 validation** — verify all fields are populated before proceeding:
|
|
1116
|
+
- [ ] `skills` — from check 1
|
|
1117
|
+
- [ ] `credential_files` — from check 2
|
|
1118
|
+
- [ ] `dlp` — from check 3
|
|
1119
|
+
- [ ] `network` — from checks 4, 5, 6
|
|
1120
|
+
- [ ] `runtime` — from check 7
|
|
1121
|
+
- [ ] `web3` — detected flag + fields
|
|
877
1122
|
|
|
878
|
-
|
|
1123
|
+
**If any field is missing, go back and run the missing check. Do NOT proceed with incomplete data.**
|
|
879
1124
|
|
|
880
|
-
|
|
1125
|
+
### Step 3: Compute Scores with checkup-score.js
|
|
881
1126
|
|
|
882
|
-
|
|
883
|
-
composite_score = (code_safety × 0.25) + (credential_safety × 0.25) + (network_exposure × 0.20) + (runtime_protection × 0.15) + (web3_safety × 0.15)
|
|
884
|
-
```
|
|
1127
|
+
Run the scoring script (it reads the raw facts and deterministically computes all dimension scores, composite score, and tier — do NOT calculate these yourself):
|
|
885
1128
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
composite_score = (code_safety × 0.294) + (credential_safety × 0.294) + (network_exposure × 0.235) + (runtime_protection × 0.176)
|
|
1129
|
+
```bash
|
|
1130
|
+
cd <skill_directory> && node scripts/checkup-score.js --file /tmp/agentguard-raw-facts.json
|
|
889
1131
|
```
|
|
890
1132
|
|
|
891
|
-
|
|
1133
|
+
The script outputs a JSON object with:
|
|
1134
|
+
- `composite_score` (0–100)
|
|
1135
|
+
- `tier` (S/A/B/F) and `tier_label`
|
|
1136
|
+
- `total_findings`
|
|
1137
|
+
- `dimensions`: `code_safety`, `credential_safety`, `network_exposure`, `runtime_protection`, `web3_safety` — each with `score` and `findings[]`
|
|
892
1138
|
|
|
893
|
-
|
|
1139
|
+
Capture this JSON output — you will use it in Step 4.
|
|
894
1140
|
|
|
895
|
-
|
|
896
|
-
|-------------|------|-------|
|
|
897
|
-
| **90–100** | **S** | JACKED |
|
|
898
|
-
| **70–89** | **A** | Healthy |
|
|
899
|
-
| **50–69** | **B** | Tired |
|
|
900
|
-
| **0–49** | **F** | Critical |
|
|
1141
|
+
### Step 4: Generate Analysis Report
|
|
901
1142
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
### Step 3: Generate Analysis Report
|
|
905
|
-
|
|
906
|
-
Based on all collected data and findings, write a **comprehensive security analysis report** as a single text block. This is where you use your AI reasoning ability — don't just list facts, **analyze** them:
|
|
1143
|
+
Based on the scored output from Step 3 and the raw facts you collected, write a **comprehensive security analysis report** as a single text block. This is where you use your AI reasoning ability — don't just list facts, **analyze** them:
|
|
907
1144
|
|
|
908
1145
|
- Summarize the overall security posture in 2-3 sentences
|
|
909
1146
|
- Highlight the most critical risks and explain **why** they matter (e.g. "Your ~/.ssh/ permissions allow any process running as your user to read your private keys, which means a malicious skill could silently exfiltrate them")
|
|
910
|
-
- For each major finding, provide a specific actionable fix (exact command to run)
|
|
1147
|
+
- For each major finding from the scored output, provide a specific actionable fix (exact command to run)
|
|
911
1148
|
- Note what's going well — acknowledge secure areas
|
|
912
|
-
- If applicable, explain attack scenarios that the current configuration is vulnerable to
|
|
1149
|
+
- If applicable, explain attack scenarios that the current configuration is vulnerable to
|
|
913
1150
|
- Keep the tone professional but direct, like a security consultant's report
|
|
914
1151
|
|
|
915
|
-
This report goes into the `"analysis"` field of the JSON
|
|
1152
|
+
This report goes into the `"analysis"` field of the final JSON.
|
|
916
1153
|
|
|
917
1154
|
Also generate a list of actionable recommendations as `{ "severity": "...", "text": "..." }` objects for the structured view.
|
|
918
1155
|
|
|
919
|
-
###
|
|
920
|
-
|
|
921
|
-
**Before assembling the JSON, verify you have collected data for ALL 5 dimensions:**
|
|
922
|
-
|
|
923
|
-
- [ ] `code_safety` — from Step 1 check 1 (skill scanning)
|
|
924
|
-
- [ ] `credential_safety` — from Step 1 checks 2 + 3 (permissions + DLP)
|
|
925
|
-
- [ ] `network_exposure` — from Step 1 checks 4 + 5 + 6 (ports + cron + env vars)
|
|
926
|
-
- [ ] `runtime_protection` — from Step 1 check 7 (hooks + audit log)
|
|
927
|
-
- [ ] `web3_safety` — from Step 2 (only if Web3 detected, otherwise `{ "score": null, "na": true }`)
|
|
1156
|
+
### Step 5: Generate HTML Report
|
|
928
1157
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
### Step 4: Generate Report
|
|
932
|
-
|
|
933
|
-
Assemble the results into a JSON object and pipe it to the report generator:
|
|
1158
|
+
Assemble the final JSON by merging the scored output from Step 3 with the analysis from Step 4, then pass it to the report generator:
|
|
934
1159
|
|
|
935
1160
|
```json
|
|
936
1161
|
{
|
|
937
1162
|
"timestamp": "<ISO 8601>",
|
|
938
|
-
"composite_score": <
|
|
939
|
-
"tier": "<
|
|
1163
|
+
"composite_score": <from checkup-score.js>,
|
|
1164
|
+
"tier": "<from checkup-score.js>",
|
|
940
1165
|
"dimensions": {
|
|
941
|
-
"code_safety":
|
|
942
|
-
"credential_safety":
|
|
943
|
-
"network_exposure":
|
|
944
|
-
"runtime_protection": { "score": <
|
|
945
|
-
"web3_safety":
|
|
1166
|
+
"code_safety": { "score": <from score>, "findings": [...], "details": "<one-line summary>" },
|
|
1167
|
+
"credential_safety": { "score": <from score>, "findings": [...], "details": "<one-line summary>" },
|
|
1168
|
+
"network_exposure": { "score": <from score>, "findings": [...], "details": "<one-line summary>" },
|
|
1169
|
+
"runtime_protection": { "score": <from score>, "findings": [...], "details": "<one-line summary>" },
|
|
1170
|
+
"web3_safety": { "score": <from score|null>, "na": <bool>, "findings": [...], "details": "<one-line summary>" }
|
|
946
1171
|
},
|
|
947
|
-
"skills_scanned": <count>,
|
|
1172
|
+
"skills_scanned": <count of skills from Step 1>,
|
|
948
1173
|
"protection_level": "<level>",
|
|
949
1174
|
"analysis": "<the comprehensive AI-written security analysis report>",
|
|
950
1175
|
"recommendations": [
|
|
@@ -953,19 +1178,24 @@ Assemble the results into a JSON object and pipe it to the report generator:
|
|
|
953
1178
|
}
|
|
954
1179
|
```
|
|
955
1180
|
|
|
956
|
-
|
|
1181
|
+
**If `--format json` was specified**:
|
|
1182
|
+
1. Write this JSON to the `--output <file>` path (or `/tmp/agentguard-checkup-data.json` if no `--output` given) using the Write tool.
|
|
1183
|
+
2. Tell the user: "Checkup JSON written to `<file>`." — include the composite score and tier in the message.
|
|
1184
|
+
3. **Stop here** — skip Steps 5 and 6 (HTML generation and MEDIA delivery). The terminal summary in Step 5 is also skipped since the user is consuming the raw JSON programmatically.
|
|
1185
|
+
|
|
1186
|
+
**Otherwise (default HTML flow)**:
|
|
1187
|
+
|
|
1188
|
+
Write the JSON to a temporary file using the Write tool (e.g. `/tmp/agentguard-checkup-data.json`), then run (remember to `cd` into the skill directory first — see "Resolving Script Paths" above):
|
|
957
1189
|
|
|
958
|
-
1. First, write the JSON to a temporary file using the Write tool (e.g. `/tmp/agentguard-checkup-data.json`)
|
|
959
|
-
2. Then run (remember to `cd` into the skill directory first — see "Resolving Script Paths" above):
|
|
960
1190
|
```bash
|
|
961
1191
|
cd <skill_directory> && node scripts/checkup-report.js --file /tmp/agentguard-checkup-data.json
|
|
962
1192
|
```
|
|
963
1193
|
|
|
964
|
-
The script outputs the HTML file path to stdout (e.g. `/tmp/agentguard-checkup-1234567890.html`). Capture this path — you will need it for delivery in Step
|
|
1194
|
+
The script outputs the HTML file path to stdout (e.g. `/tmp/agentguard-checkup-1234567890.html`). Capture this path — you will need it for delivery in Step 7.
|
|
965
1195
|
|
|
966
|
-
> **Note**: The script also supports stdin pipe (`echo '<json>' | node scripts/checkup-report.js`) but this may fail on Windows cmd.exe
|
|
1196
|
+
> **Note**: The script also supports stdin pipe (`echo '<json>' | node scripts/checkup-report.js`) but this may fail on Windows cmd.exe. Always prefer `--file`.
|
|
967
1197
|
|
|
968
|
-
### Step
|
|
1198
|
+
### Step 6: Terminal Summary (REQUIRED)
|
|
969
1199
|
|
|
970
1200
|
**You MUST output this summary after the report generates.** This is the primary output the user sees. Do NOT skip this step — always show the score, dimension table, and report path:
|
|
971
1201
|
|
|
@@ -1009,11 +1239,11 @@ Examples of plain-language descriptions:
|
|
|
1009
1239
|
- SSH permissions: "Your SSH key folder has loose permissions — other processes on this machine could potentially read your private keys."
|
|
1010
1240
|
- Plaintext credential: "A private key or API token was found in plain text in a file — it should be removed and rotated."
|
|
1011
1241
|
|
|
1012
|
-
### Step
|
|
1242
|
+
### Step 7: Deliver the Report to the User
|
|
1013
1243
|
|
|
1014
1244
|
After printing the terminal summary, deliver the HTML report file. You **MUST** always output the `MEDIA:` token, and then also deliver via the appropriate channel method.
|
|
1015
1245
|
|
|
1016
|
-
####
|
|
1246
|
+
#### 7a. MEDIA token (required — always do this)
|
|
1017
1247
|
|
|
1018
1248
|
Output the following line on its **own line** in your response:
|
|
1019
1249
|
|
|
@@ -1025,10 +1255,10 @@ For example: `MEDIA:/tmp/agentguard-checkup-1234567890.html`
|
|
|
1025
1255
|
|
|
1026
1256
|
This is how platforms like OpenClaw automatically deliver the file as a Telegram/Discord/WhatsApp attachment via `sendDocument`. The platform strips this line from visible text — the user won't see it. **Always output this regardless of what channel you think you're in.**
|
|
1027
1257
|
|
|
1028
|
-
####
|
|
1258
|
+
#### 7b. Channel-specific delivery (in addition to MEDIA token)
|
|
1029
1259
|
|
|
1030
1260
|
**Claude Code (local desktop)**
|
|
1031
|
-
- The browser should already be open from Step
|
|
1261
|
+
- The browser should already be open from Step 5.
|
|
1032
1262
|
- Also copy to Desktop: `cp <file_path> ~/Desktop/agentguard-checkup-$(date +%Y-%m-%d).html`
|
|
1033
1263
|
- Tell the user: "✅ Report saved to your Desktop and opened in browser."
|
|
1034
1264
|
|