@goplus/agentguard 1.1.4 → 1.1.5

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.
Files changed (53) hide show
  1. package/README.md +20 -2
  2. package/dist/action/index.d.ts.map +1 -1
  3. package/dist/action/index.js +3 -1
  4. package/dist/action/index.js.map +1 -1
  5. package/dist/adapters/hermes.d.ts +25 -0
  6. package/dist/adapters/hermes.d.ts.map +1 -0
  7. package/dist/adapters/hermes.js +131 -0
  8. package/dist/adapters/hermes.js.map +1 -0
  9. package/dist/adapters/index.d.ts +1 -0
  10. package/dist/adapters/index.d.ts.map +1 -1
  11. package/dist/adapters/index.js +3 -1
  12. package/dist/adapters/index.js.map +1 -1
  13. package/dist/adapters/openclaw-plugin.d.ts +12 -1
  14. package/dist/adapters/openclaw-plugin.d.ts.map +1 -1
  15. package/dist/adapters/openclaw-plugin.js +165 -9
  16. package/dist/adapters/openclaw-plugin.js.map +1 -1
  17. package/dist/cli.js +85 -12
  18. package/dist/cli.js.map +1 -1
  19. package/dist/feed/cron.d.ts +25 -0
  20. package/dist/feed/cron.d.ts.map +1 -0
  21. package/dist/feed/cron.js +173 -0
  22. package/dist/feed/cron.js.map +1 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/installers.js +0 -1
  28. package/dist/installers.js.map +1 -1
  29. package/dist/runtime/protect.d.ts.map +1 -1
  30. package/dist/runtime/protect.js +6 -1
  31. package/dist/runtime/protect.js.map +1 -1
  32. package/dist/tests/adapter.test.js +146 -0
  33. package/dist/tests/adapter.test.js.map +1 -1
  34. package/dist/tests/feed-cron.test.d.ts +2 -0
  35. package/dist/tests/feed-cron.test.d.ts.map +1 -0
  36. package/dist/tests/feed-cron.test.js +78 -0
  37. package/dist/tests/feed-cron.test.js.map +1 -0
  38. package/dist/tests/installer.test.js +3 -1
  39. package/dist/tests/installer.test.js.map +1 -1
  40. package/dist/tests/integration.test.js +211 -1
  41. package/dist/tests/integration.test.js.map +1 -1
  42. package/dist/tests/runtime-cloud.test.js +24 -0
  43. package/dist/tests/runtime-cloud.test.js.map +1 -1
  44. package/dist/tests/smoke.test.js +141 -7
  45. package/dist/tests/smoke.test.js.map +1 -1
  46. package/docs/hermes.md +70 -0
  47. package/package.json +1 -1
  48. package/skills/agentguard/README.md +12 -0
  49. package/skills/agentguard/SKILL.md +104 -3
  50. package/skills/agentguard/hermes-hooks.yaml +31 -0
  51. package/skills/agentguard/package.json +1 -1
  52. package/skills/agentguard/scripts/auto-scan.js +3 -2
  53. package/skills/agentguard/scripts/hermes-hook.js +201 -0
@@ -9,6 +9,7 @@ const node_child_process_1 = require("node:child_process");
9
9
  const node_fs_1 = require("node:fs");
10
10
  const node_path_1 = require("node:path");
11
11
  const node_os_1 = require("node:os");
12
+ const node_perf_hooks_1 = require("node:perf_hooks");
12
13
  const index_js_1 = require("../scanner/index.js");
13
14
  // ─────────────────────────────────────────────────────────────────────────────
14
15
  // D: guard-hook.js subprocess E2E
@@ -16,27 +17,51 @@ const index_js_1 = require("../scanner/index.js");
16
17
  // __dirname points to dist/tests/ after compilation, project root is 2 levels up
17
18
  const projectRoot = (0, node_path_1.resolve)(__dirname, '..', '..');
18
19
  const GUARD_HOOK_PATH = (0, node_path_1.join)(projectRoot, 'skills', 'agentguard', 'scripts', 'guard-hook.js');
20
+ const HERMES_HOOK_PATH = (0, node_path_1.join)(projectRoot, 'skills', 'agentguard', 'scripts', 'hermes-hook.js');
19
21
  function runGuardHook(input) {
22
+ return runNodeHook(GUARD_HOOK_PATH, input);
23
+ }
24
+ function runHermesHook(input) {
25
+ return runNodeHook(HERMES_HOOK_PATH, input);
26
+ }
27
+ function runHermesHookWithEnv(input, env) {
28
+ return runNodeHook(HERMES_HOOK_PATH, input, env);
29
+ }
30
+ function runHermesHookRaw(input) {
31
+ return runNodeHookRaw(HERMES_HOOK_PATH, input);
32
+ }
33
+ function runNodeHook(scriptPath, input, env = {}) {
34
+ return runNodeHookRaw(scriptPath, JSON.stringify(input), env);
35
+ }
36
+ function runNodeHookRaw(scriptPath, input, env = {}) {
20
37
  return new Promise((resolvePromise) => {
21
38
  // Isolate HOME to a temp dir so loadConfig/writeAuditLog don't touch real ~/.agentguard/
22
39
  const tempHome = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentguard-smoke-'));
23
- const child = (0, node_child_process_1.spawn)('node', [GUARD_HOOK_PATH], {
40
+ const child = (0, node_child_process_1.spawn)('node', [scriptPath], {
24
41
  stdio: ['pipe', 'pipe', 'pipe'],
25
- env: { ...process.env, HOME: tempHome },
42
+ env: { ...process.env, HOME: tempHome, ...env },
26
43
  });
27
44
  let stdout = '';
28
45
  let stderr = '';
46
+ let settled = false;
47
+ const finish = (result) => {
48
+ if (settled)
49
+ return;
50
+ settled = true;
51
+ clearTimeout(timeout);
52
+ resolvePromise(result);
53
+ };
29
54
  child.stdout.on('data', (d) => (stdout += d.toString()));
30
55
  child.stderr.on('data', (d) => (stderr += d.toString()));
31
- child.stdin.write(JSON.stringify(input));
56
+ child.stdin.write(input);
32
57
  child.stdin.end();
33
58
  child.on('close', (code) => {
34
- resolvePromise({ exitCode: code ?? 1, stdout, stderr });
59
+ finish({ exitCode: code ?? 1, stdout, stderr });
35
60
  });
36
61
  // Timeout safety
37
- setTimeout(() => {
62
+ const timeout = setTimeout(() => {
38
63
  child.kill();
39
- resolvePromise({ exitCode: -1, stdout, stderr: 'TIMEOUT' });
64
+ finish({ exitCode: -1, stdout, stderr: 'TIMEOUT' });
40
65
  }, 8000);
41
66
  });
42
67
  }
@@ -76,7 +101,116 @@ function runGuardHook(input) {
76
101
  });
77
102
  });
78
103
  // ─────────────────────────────────────────────────────────────────────────────
79
- // E: Scanner integration
104
+ // E: hermes-hook.js subprocess E2E
105
+ // ─────────────────────────────────────────────────────────────────────────────
106
+ (0, node_test_1.describe)('Smoke: hermes-hook.js E2E', () => {
107
+ (0, node_test_1.it)('should allow echo hello with empty JSON output', async () => {
108
+ const { exitCode, stdout } = await runHermesHook({
109
+ hook_event_name: 'pre_tool_call',
110
+ tool_name: 'terminal',
111
+ tool_input: { command: 'echo hello' },
112
+ });
113
+ strict_1.default.equal(exitCode, 0);
114
+ strict_1.default.deepEqual(JSON.parse(stdout), {});
115
+ });
116
+ (0, node_test_1.it)('should block rm -rf / using Hermes stdout protocol', async () => {
117
+ const { exitCode, stdout } = await runHermesHook({
118
+ hook_event_name: 'pre_tool_call',
119
+ tool_name: 'terminal',
120
+ tool_input: { command: 'rm -rf /' },
121
+ });
122
+ strict_1.default.equal(exitCode, 0);
123
+ const payload = JSON.parse(stdout);
124
+ strict_1.default.equal(payload.action, 'block');
125
+ strict_1.default.ok(payload.message?.includes('AgentGuard'), 'message should mention AgentGuard');
126
+ });
127
+ (0, node_test_1.it)('should block write to .env using Hermes stdout protocol', async () => {
128
+ const { exitCode, stdout } = await runHermesHook({
129
+ hook_event_name: 'pre_tool_call',
130
+ tool_name: 'write_file',
131
+ tool_input: { path: '/project/.env' },
132
+ });
133
+ strict_1.default.equal(exitCode, 0);
134
+ const payload = JSON.parse(stdout);
135
+ strict_1.default.equal(payload.action, 'block');
136
+ });
137
+ (0, node_test_1.it)('should allow post_tool_call event for audit-only handling', async () => {
138
+ const { exitCode, stdout } = await runHermesHook({
139
+ hook_event_name: 'post_tool_call',
140
+ tool_name: 'terminal',
141
+ tool_input: { command: 'rm -rf /' },
142
+ });
143
+ strict_1.default.equal(exitCode, 0);
144
+ strict_1.default.deepEqual(JSON.parse(stdout), {});
145
+ });
146
+ (0, node_test_1.it)('should fail closed when the Hermes engine cannot load for pre_tool_call', async () => {
147
+ const { exitCode, stdout } = await runHermesHookWithEnv({
148
+ hook_event_name: 'pre_tool_call',
149
+ tool_name: 'terminal',
150
+ tool_input: { command: 'echo hello' },
151
+ }, { AGENTGUARD_TEST_FORCE_ENGINE_LOAD_FAILURE: '1' });
152
+ strict_1.default.equal(exitCode, 0);
153
+ const payload = JSON.parse(stdout);
154
+ strict_1.default.equal(payload.action, 'block');
155
+ strict_1.default.ok(payload.message?.includes('unable to load Hermes hook engine'));
156
+ });
157
+ (0, node_test_1.it)('should block unknown pre_tool_call tools', async () => {
158
+ const { exitCode, stdout } = await runHermesHook({
159
+ hook_event_name: 'pre_tool_call',
160
+ tool_name: 'browser_click',
161
+ tool_input: { selector: '#danger' },
162
+ });
163
+ strict_1.default.equal(exitCode, 0);
164
+ const payload = JSON.parse(stdout);
165
+ strict_1.default.equal(payload.action, 'block');
166
+ strict_1.default.ok(payload.message?.includes('not recognized by AgentGuard'));
167
+ });
168
+ (0, node_test_1.it)('should block terminal payloads without a command', async () => {
169
+ const { exitCode, stdout } = await runHermesHook({
170
+ hook_event_name: 'pre_tool_call',
171
+ tool_name: 'terminal',
172
+ tool_input: {},
173
+ });
174
+ strict_1.default.equal(exitCode, 0);
175
+ const payload = JSON.parse(stdout);
176
+ strict_1.default.equal(payload.action, 'block');
177
+ strict_1.default.ok(payload.message?.includes('missing command'));
178
+ });
179
+ (0, node_test_1.it)('should block file payloads without a path', async () => {
180
+ const { exitCode, stdout } = await runHermesHook({
181
+ hook_event_name: 'pre_tool_call',
182
+ tool_name: 'write_file',
183
+ tool_input: { content: 'secret' },
184
+ });
185
+ strict_1.default.equal(exitCode, 0);
186
+ const payload = JSON.parse(stdout);
187
+ strict_1.default.equal(payload.action, 'block');
188
+ strict_1.default.ok(payload.message?.includes('missing path'));
189
+ });
190
+ (0, node_test_1.it)('should block URL payloads without a URL', async () => {
191
+ const { exitCode, stdout } = await runHermesHook({
192
+ hook_event_name: 'pre_tool_call',
193
+ tool_name: 'browser_navigate',
194
+ tool_input: { selector: '#login' },
195
+ });
196
+ strict_1.default.equal(exitCode, 0);
197
+ const payload = JSON.parse(stdout);
198
+ strict_1.default.equal(payload.action, 'block');
199
+ strict_1.default.ok(payload.message?.includes('missing URL'));
200
+ });
201
+ (0, node_test_1.it)('should block invalid stdin without waiting for the stdin timeout', async () => {
202
+ const start = node_perf_hooks_1.performance.now();
203
+ const { exitCode, stdout } = await runHermesHookRaw('{not-json');
204
+ const elapsedMs = node_perf_hooks_1.performance.now() - start;
205
+ strict_1.default.equal(exitCode, 0);
206
+ strict_1.default.ok(elapsedMs < 2000, `hook should exit promptly, took ${elapsedMs}ms`);
207
+ const payload = JSON.parse(stdout);
208
+ strict_1.default.equal(payload.action, 'block');
209
+ strict_1.default.ok(payload.message?.includes('invalid or missing Hermes hook payload'));
210
+ });
211
+ });
212
+ // ─────────────────────────────────────────────────────────────────────────────
213
+ // F: Scanner integration
80
214
  // ─────────────────────────────────────────────────────────────────────────────
81
215
  (0, node_test_1.describe)('Smoke: SkillScanner on vulnerable-skill', () => {
82
216
  (0, node_test_1.it)('should detect multiple violations in examples/vulnerable-skill', async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"smoke.test.js","sourceRoot":"","sources":["../../src/tests/smoke.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"smoke.test.js","sourceRoot":"","sources":["../../src/tests/smoke.test.ts"],"names":[],"mappings":"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"}
package/docs/hermes.md ADDED
@@ -0,0 +1,70 @@
1
+ # Hermes Agent
2
+
3
+ Hermes Agent can use AgentGuard through Hermes shell hooks. AgentGuard evaluates
4
+ `pre_tool_call` events before risky tools execute and returns Hermes-compatible
5
+ block decisions on stdout.
6
+
7
+ ## Shell hook usage
8
+
9
+ Build AgentGuard first so the hook script can import `dist/index.js`:
10
+
11
+ ```bash
12
+ npm run build
13
+ ```
14
+
15
+ Copy the template from `skills/agentguard/hermes-hooks.yaml` into
16
+ `~/.hermes/config.yaml` and replace `AGENTGUARD_SKILL_DIR` with the absolute
17
+ path to the installed AgentGuard skill directory.
18
+
19
+ ```yaml
20
+ hooks:
21
+ on_session_start:
22
+ - command: "env AGENTGUARD_AUTO_SCAN=1 node \"/path/to/agentguard/skills/agentguard/scripts/auto-scan.js\""
23
+ timeout: 30
24
+
25
+ pre_tool_call:
26
+ - matcher: "terminal|execute_code"
27
+ command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
28
+ timeout: 10
29
+ - matcher: "write_file|patch|skill_manage"
30
+ command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
31
+ timeout: 10
32
+ - matcher: "web_search|web_extract|browser_navigate"
33
+ command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
34
+ timeout: 10
35
+
36
+ post_tool_call:
37
+ - matcher: "terminal|execute_code|write_file|patch|skill_manage|read_file|web_search|web_extract|browser_navigate"
38
+ command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
39
+ timeout: 5
40
+ ```
41
+
42
+ Hermes asks for first-use consent for shell hooks. Use one of:
43
+
44
+ ```bash
45
+ hermes --accept-hooks chat
46
+ HERMES_ACCEPT_HOOKS=1 hermes chat
47
+ ```
48
+
49
+ or set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.
50
+
51
+ ## Tool mapping
52
+
53
+ | Hermes tool | AgentGuard action |
54
+ |-------------|-------------------|
55
+ | `terminal`, `execute_code` | `exec_command` |
56
+ | `write_file`, `patch`, `skill_manage` | `write_file` |
57
+ | `read_file` | `read_file` |
58
+ | `web_search`, `web_extract`, `browser_navigate` | `network_request` |
59
+
60
+ ## Decisions
61
+
62
+ Hermes `pre_tool_call` supports allow or block. AgentGuard `deny` decisions are
63
+ returned as:
64
+
65
+ ```json
66
+ {"action":"block","message":"GoPlus AgentGuard: ..."}
67
+ ```
68
+
69
+ AgentGuard `ask` decisions are also represented as blocks because Hermes shell
70
+ hooks do not have a native confirmation decision.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goplus/agentguard",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "GoPlus AgentGuard — Security guard for AI agents. Blocks dangerous commands, prevents data leaks, protects secrets. 20 detection rules, runtime action evaluation, trust registry.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -21,8 +21,20 @@ AI Agent Security Guard — protect your AI agents from dangerous commands, data
21
21
  /agentguard report — View security event audit log
22
22
  /agentguard config <level> — Set protection level (strict/balanced/permissive)
23
23
  /agentguard checkup — Run agent health checkup with visual HTML report
24
+ /agentguard hermes-hooks — Configure Hermes Agent shell hooks
24
25
  ```
25
26
 
27
+ ## Hermes Agent hooks
28
+
29
+ When installed from SkillHub, Hermes sees the contents of this
30
+ `skills/agentguard` directory first. Runtime hooks are not loaded from
31
+ `SKILL.md` automatically; copy `hermes-hooks.yaml` into `~/.hermes/config.yaml`
32
+ and replace `AGENTGUARD_SKILL_DIR` with this skill's absolute path.
33
+
34
+ The hook runner is `scripts/hermes-hook.js`. It uses the published
35
+ `@goplus/agentguard` package, so run `npm install` inside this skill directory
36
+ or install `@goplus/agentguard` globally if the package is not already present.
37
+
26
38
  ## Agent Health Checkup 🦞
27
39
 
28
40
  Run a full security health check on your AI agent and get a visual report in the browser:
@@ -20,6 +20,9 @@ filesystem-access:
20
20
  - path: "~/.openclaw/"
21
21
  access: read-only
22
22
  reason: "Discover installed skills and read OpenClaw config for patrol checks"
23
+ - path: "~/.hermes/"
24
+ access: read-write
25
+ reason: "Discover installed Hermes skills and help configure AgentGuard shell hooks"
23
26
  - path: "~/.qclaw/"
24
27
  access: read-only
25
28
  reason: "Discover installed skills in QClaw environments"
@@ -27,8 +30,8 @@ filesystem-access:
27
30
  access: read-write
28
31
  reason: "Read/write audit log (audit.jsonl) and protection level config (config.json)"
29
32
  user-invocable: true
30
- allowed-tools: Read, Write, Grep, Glob, Bash(node *trust-cli.ts *) Bash(node *action-cli.ts *) Bash(*checkup-report.js) Bash(echo *checkup-report.js) Bash(cat *checkup-report.js) 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 *)
31
- argument-hint: "[scan|action|patrol|trust|report|config|checkup] [args...]"
33
+ allowed-tools: Read, Write, Grep, Glob, Bash(node *trust-cli.ts *) Bash(node *action-cli.ts *) Bash(*checkup-report.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] [args...]"
32
35
  ---
33
36
 
34
37
  # GoPlus AgentGuard — AI Agent Security Framework
@@ -55,13 +58,109 @@ Parse `$ARGUMENTS` to determine the subcommand:
55
58
  - **`scan <path>`** — Scan a skill or codebase for security risks
56
59
  - **`action <description>`** — Evaluate whether a runtime action is safe
57
60
  - **`patrol [run|setup|status]`** — Daily security patrol for OpenClaw environments
61
+ - **`subscribe [args...]`** — Pull AgentGuard Cloud threat-feed advisories, self-check local skills, and optionally install the OpenClaw 15-minute conditional notification cron
58
62
  - **`trust <lookup|attest|revoke|list> [args]`** — Manage skill trust levels
59
63
  - **`report`** — View recent security events from the audit log
60
64
  - **`config <strict|balanced|permissive>`** — Set protection level
61
65
  - **`checkup`** — Run a comprehensive agent health checkup and generate a visual HTML report
66
+ - **`hermes-hooks`** — Show or install Hermes shell-hook configuration for runtime protection
62
67
 
63
68
  If no subcommand is given, or the first argument is a path, default to **scan**.
64
69
 
70
+ ## Subcommand: hermes-hooks
71
+
72
+ Help the user configure AgentGuard runtime protection for Hermes Agent.
73
+
74
+ Hermes does **not** load hooks from `SKILL.md` automatically. Hermes shell hooks
75
+ must be present in `~/.hermes/config.yaml`. This skill ships the hook runner at
76
+ `scripts/hermes-hook.js` and a copyable template at `hermes-hooks.yaml`.
77
+
78
+ ### What the Hermes hook protects
79
+
80
+ | Hermes hook | Tools | AgentGuard action |
81
+ |---|---|---|
82
+ | `pre_tool_call` | `terminal`, `execute_code` | `exec_command` |
83
+ | `pre_tool_call` | `write_file`, `patch`, `skill_manage` | `write_file` |
84
+ | `pre_tool_call` | `read_file` | `read_file` |
85
+ | `pre_tool_call` | `web_search`, `web_extract`, `browser_navigate` | `network_request` |
86
+ | `post_tool_call` | Same tools | Audit-only |
87
+
88
+ Hermes `pre_tool_call` supports allow/block only. If AgentGuard returns `ask`,
89
+ the Hermes hook reports it as a block with a confirmation-oriented message.
90
+
91
+ ### Procedure
92
+
93
+ 1. Resolve the AgentGuard skill directory using the "Important: Resolving Script
94
+ Paths" rules above.
95
+ 2. Confirm that dependencies are available. If `node scripts/hermes-hook.js`
96
+ cannot load `@goplus/agentguard`, tell the user to run:
97
+ ```bash
98
+ cd <agentguard-skill-dir> && npm install
99
+ ```
100
+ or install the published package globally:
101
+ ```bash
102
+ npm install -g @goplus/agentguard
103
+ ```
104
+ 3. Read `hermes-hooks.yaml`, replace `AGENTGUARD_SKILL_DIR` with the absolute
105
+ skill directory, and show the resulting YAML to the user.
106
+ 4. Ask for explicit confirmation before editing `~/.hermes/config.yaml`.
107
+ 5. If confirmed, merge the `hooks:` entries into `~/.hermes/config.yaml`.
108
+ Preserve existing hooks and config values. Do not overwrite unrelated user
109
+ configuration.
110
+ 6. Tell the user to restart Hermes or launch it with one of the first-use
111
+ consent options:
112
+ ```bash
113
+ hermes --accept-hooks chat
114
+ HERMES_ACCEPT_HOOKS=1 hermes chat
115
+ ```
116
+ They may also set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.
117
+
118
+ ### Verification
119
+
120
+ After configuration, suggest a harmless test:
121
+
122
+ ```bash
123
+ printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"echo hello"}}' \
124
+ | node <agentguard-skill-dir>/scripts/hermes-hook.js
125
+ ```
126
+
127
+ Expected output:
128
+
129
+ ```json
130
+ {}
131
+ ```
132
+
133
+ And a blocked-action test:
134
+
135
+ ```bash
136
+ printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"rm -rf /"}}' \
137
+ | node <agentguard-skill-dir>/scripts/hermes-hook.js
138
+ ```
139
+
140
+ Expected output contains:
141
+
142
+ ```json
143
+ {"action":"block"}
144
+ ```
145
+
146
+ ## Subcommand: subscribe
147
+
148
+ Run the AgentGuard Cloud threat-feed subscription workflow through the installed CLI.
149
+
150
+ Examples:
151
+
152
+ ```bash
153
+ agentguard subscribe
154
+ agentguard subscribe --json
155
+ agentguard subscribe --install-cron
156
+ agentguard subscribe --install-cron --interval-minutes 5
157
+ agentguard subscribe --install-cron --force
158
+ ```
159
+
160
+ When `--install-cron` is used, the CLI registers an OpenClaw isolated cron job through the local OpenClaw Gateway at `127.0.0.1:18789`. It runs every 15 minutes by default. Pass `--interval-minutes <n>` to override the cadence. If a job with the same name already exists, the CLI leaves it untouched unless `--force` is passed. The cron delivery is intentionally silent (`delivery.mode = "none"`); the isolated turn executes `agentguard subscribe --json --cron-run` and only sends the configured notification when `shouldNotify` is `true`.
161
+
162
+ `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.
163
+
65
164
  ---
66
165
 
67
166
  # Security Operations
@@ -647,6 +746,7 @@ Run these checks in parallel where possible. These are **universal agent securit
647
746
  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:
648
747
  - For OpenClaw / QClaw: scan `~/.openclaw/workspace/` and `~/.qclaw/workspace/` recursively — this includes **all** `workspace-agent-*/` subdirectories, not just the current agent's workspace
649
748
  - For Claude Code: scan `~/.claude/` recursively
749
+ - For Hermes Agent: scan `~/.hermes/` recursively
650
750
  - Patterns to detect:
651
751
  - Private keys: `0x[a-fA-F0-9]{64}`, `-----BEGIN.*PRIVATE KEY-----`
652
752
  - Mnemonics: sequences of 12+ BIP-39 words, `seed_phrase`, `mnemonic`
@@ -655,7 +755,7 @@ Run these checks in parallel where possible. These are **universal agent securit
655
755
  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)
656
756
  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/`
657
757
  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
658
- 7. **[REQUIRED] Runtime protection check** (→ feeds Dimension 4: Runtime Protection): Check if security hooks exist in `~/.claude/settings.json` or `~/.openclaw/openclaw.json`, check for audit logs at `~/.agentguard/audit.jsonl`
758
+ 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`
659
759
 
660
760
  ### Step 2: Score Calculation
661
761
 
@@ -910,6 +1010,7 @@ AgentGuard can optionally scan installed skills at session startup. **This is di
910
1010
 
911
1011
  - **Claude Code**: Set environment variable `AGENTGUARD_AUTO_SCAN=1`
912
1012
  - **OpenClaw**: Pass `{ skipAutoScan: false }` when registering the plugin
1013
+ - **Hermes Agent**: Configure the `on_session_start` shell hook from `hermes-hooks.yaml`; the template sets `AGENTGUARD_AUTO_SCAN=1` for that hook.
913
1014
 
914
1015
  When enabled, auto-scan operates in **report-only mode**:
915
1016
 
@@ -0,0 +1,31 @@
1
+ # GoPlus AgentGuard hook template for Hermes Agent.
2
+ #
3
+ # Copy this block into ~/.hermes/config.yaml and replace AGENTGUARD_SKILL_DIR
4
+ # with the absolute path to the installed AgentGuard skill directory, e.g.
5
+ # ~/.hermes/skills/agentguard or ~/.openclaw/skills/agentguard.
6
+
7
+ hooks:
8
+ on_session_start:
9
+ - command: "env AGENTGUARD_AUTO_SCAN=1 node \"AGENTGUARD_SKILL_DIR/scripts/auto-scan.js\""
10
+ timeout: 30
11
+
12
+ pre_tool_call:
13
+ - matcher: "terminal|execute_code"
14
+ command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
15
+ timeout: 10
16
+ - matcher: "write_file|patch|skill_manage"
17
+ command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
18
+ timeout: 10
19
+ - matcher: "read_file"
20
+ command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
21
+ timeout: 10
22
+ - matcher: "web_search|web_extract|browser_navigate"
23
+ command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
24
+ timeout: 10
25
+
26
+ post_tool_call:
27
+ - matcher: "terminal|execute_code|write_file|patch|skill_manage|read_file|web_search|web_extract|browser_navigate"
28
+ command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
29
+ timeout: 5
30
+
31
+ hooks_auto_accept: false
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@goplus/agentguard": "^1.0.6",
5
+ "@goplus/agentguard": "^1.1.4",
6
6
  "open": "11.0.0"
7
7
  }
8
8
  }
@@ -4,7 +4,7 @@
4
4
  * GoPlus AgentGuard — SessionStart Auto-Scan Hook
5
5
  *
6
6
  * Runs on session startup to discover and scan newly installed skills.
7
- * For each skill in ~/.claude/skills/:
7
+ * For each skill in supported agent skill directories:
8
8
  * 1. Calculate artifact hash
9
9
  * 2. Check trust registry — skip if already registered with same hash
10
10
  * 3. Run quickScan for new/updated skills
@@ -59,6 +59,7 @@ try {
59
59
 
60
60
  const SKILLS_DIRS = [
61
61
  join(homedir(), '.claude', 'skills'),
62
+ join(homedir(), '.hermes', 'skills'),
62
63
  join(homedir(), '.openclaw', 'skills'),
63
64
  ];
64
65
  const AGENTGUARD_DIR = join(homedir(), '.agentguard');
@@ -84,7 +85,7 @@ function writeAuditLog(entry) {
84
85
  // ---------------------------------------------------------------------------
85
86
 
86
87
  /**
87
- * Find all skill directories under ~/.claude/skills/ and ~/.openclaw/skills/
88
+ * Find all skill directories under supported agent skill roots.
88
89
  * A skill directory is one that contains a SKILL.md file.
89
90
  */
90
91
  function discoverSkills() {