@goplus/agentguard 1.1.28-beta.1 → 1.1.28
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 +3 -2
- package/dist/action/detectors/exec.d.ts.map +1 -1
- package/dist/action/detectors/exec.js +265 -4
- package/dist/action/detectors/exec.js.map +1 -1
- package/dist/action/detectors/network.d.ts.map +1 -1
- package/dist/action/detectors/network.js +63 -0
- package/dist/action/detectors/network.js.map +1 -1
- package/dist/adapters/openclaw-plugin.d.ts.map +1 -1
- package/dist/adapters/openclaw-plugin.js +2 -0
- package/dist/adapters/openclaw-plugin.js.map +1 -1
- package/dist/cli.js +14 -1
- package/dist/cli.js.map +1 -1
- package/dist/installers.d.ts +1 -0
- package/dist/installers.d.ts.map +1 -1
- package/dist/installers.js +144 -6
- package/dist/installers.js.map +1 -1
- package/dist/runtime/evaluator.d.ts +4 -1
- package/dist/runtime/evaluator.d.ts.map +1 -1
- package/dist/runtime/evaluator.js +59 -10
- package/dist/runtime/evaluator.js.map +1 -1
- package/dist/runtime/protect.d.ts +1 -0
- package/dist/runtime/protect.d.ts.map +1 -1
- package/dist/runtime/protect.js +3 -1
- package/dist/runtime/protect.js.map +1 -1
- package/dist/runtime/types.d.ts +1 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/tests/action.test.js +159 -1
- package/dist/tests/action.test.js.map +1 -1
- package/dist/tests/cli-init.test.js +8 -3
- package/dist/tests/cli-init.test.js.map +1 -1
- package/dist/tests/feed-cron.test.js +1 -1
- package/dist/tests/feed-cron.test.js.map +1 -1
- package/dist/tests/installer.test.js +47 -7
- package/dist/tests/installer.test.js.map +1 -1
- package/dist/tests/integration.test.js +26 -0
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/mcpb-manifest.test.d.ts +2 -0
- package/dist/tests/mcpb-manifest.test.d.ts.map +1 -0
- package/dist/tests/mcpb-manifest.test.js +83 -0
- package/dist/tests/mcpb-manifest.test.js.map +1 -0
- package/dist/tests/runtime-cloud.test.js +111 -0
- package/dist/tests/runtime-cloud.test.js.map +1 -1
- package/dist/utils/system-paths.d.ts +14 -0
- package/dist/utils/system-paths.d.ts.map +1 -0
- package/dist/utils/system-paths.js +172 -0
- package/dist/utils/system-paths.js.map +1 -0
- package/docs/SECURITY-POLICY.md +22 -0
- package/docs/hermes.md +46 -15
- package/docs/mcpb-build.md +49 -0
- package/package.json +5 -2
- package/plugins/hermes/README.md +78 -0
- package/plugins/hermes/__init__.py +13 -0
- package/plugins/hermes/bridge.py +305 -0
- package/plugins/hermes/plugin.py +116 -0
- package/plugins/hermes/plugin.yaml +19 -0
- package/plugins/hermes/tests/conftest.py +8 -0
- package/plugins/hermes/tests/helpers.py +70 -0
- package/plugins/hermes/tests/test_allow.py +30 -0
- package/plugins/hermes/tests/test_ask.py +18 -0
- package/plugins/hermes/tests/test_block.py +38 -0
- package/plugins/hermes/tests/test_command.py +29 -0
- package/plugins/hermes/tests/test_failmodes.py +57 -0
- package/plugins/hermes/tests/test_post.py +19 -0
- package/plugins/hermes/tests/test_resolution.py +35 -0
- package/plugins/hermes/tests/test_validation.py +43 -0
- package/skills/agentguard/action-policies.md +22 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type SystemPathOperation = 'read' | 'write' | 'delete' | 'move' | 'chmod' | 'chown';
|
|
2
|
+
export type SystemPathDecision = 'block' | 'require_approval';
|
|
3
|
+
export type SystemPathSeverity = 'high' | 'critical';
|
|
4
|
+
export interface SystemPathClassification {
|
|
5
|
+
path: string;
|
|
6
|
+
operation: SystemPathOperation;
|
|
7
|
+
decision: SystemPathDecision;
|
|
8
|
+
severity: SystemPathSeverity;
|
|
9
|
+
category: 'system_boot' | 'system_config' | 'security_credentials' | 'kernel_device' | 'root';
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function classifySystemPathOperation(rawPath: string, operation: SystemPathOperation): SystemPathClassification | null;
|
|
13
|
+
export declare function normalizeSystemPath(rawPath: string): string;
|
|
14
|
+
//# sourceMappingURL=system-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-paths.d.ts","sourceRoot":"","sources":["../../src/utils/system-paths.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAC3F,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,kBAAkB,CAAC;AAC9D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,mBAAmB,CAAC;IAC/B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,aAAa,GAAG,eAAe,GAAG,sBAAsB,GAAG,eAAe,GAAG,MAAM,CAAC;IAC9F,WAAW,EAAE,MAAM,CAAC;CACrB;AA6CD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,mBAAmB,GAC7B,wBAAwB,GAAG,IAAI,CA0GjC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAa3D"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classifySystemPathOperation = classifySystemPathOperation;
|
|
4
|
+
exports.normalizeSystemPath = normalizeSystemPath;
|
|
5
|
+
const node_os_1 = require("node:os");
|
|
6
|
+
const BOOT_PREFIXES = [
|
|
7
|
+
'/bin',
|
|
8
|
+
'/sbin',
|
|
9
|
+
'/usr',
|
|
10
|
+
'/usr/bin',
|
|
11
|
+
'/usr/sbin',
|
|
12
|
+
'/lib',
|
|
13
|
+
'/lib64',
|
|
14
|
+
];
|
|
15
|
+
const CRITICAL_CONFIG_EXACT = [
|
|
16
|
+
'/etc/shadow',
|
|
17
|
+
'/etc/sudoers',
|
|
18
|
+
];
|
|
19
|
+
const HIGH_CONFIG_EXACT = [
|
|
20
|
+
'/etc/passwd',
|
|
21
|
+
'/etc/group',
|
|
22
|
+
'/etc/hosts',
|
|
23
|
+
'/etc/resolv.conf',
|
|
24
|
+
];
|
|
25
|
+
const MEDIUM_CONFIG_EXACT = [
|
|
26
|
+
'/etc/crontab',
|
|
27
|
+
];
|
|
28
|
+
const CONFIG_PREFIXES = [
|
|
29
|
+
'/etc',
|
|
30
|
+
'/etc/ssh',
|
|
31
|
+
'/etc/systemd',
|
|
32
|
+
];
|
|
33
|
+
const SECURITY_HOME_PATHS = [
|
|
34
|
+
'~/.ssh',
|
|
35
|
+
'~/.gnupg',
|
|
36
|
+
'~/.aws',
|
|
37
|
+
'~/.kube',
|
|
38
|
+
'~/.npmrc',
|
|
39
|
+
'~/.netrc',
|
|
40
|
+
];
|
|
41
|
+
const MUTATING_OPERATIONS = new Set(['write', 'delete', 'move', 'chmod', 'chown']);
|
|
42
|
+
function classifySystemPathOperation(rawPath, operation) {
|
|
43
|
+
const path = normalizeSystemPath(rawPath);
|
|
44
|
+
if (!path)
|
|
45
|
+
return null;
|
|
46
|
+
if (path === '/') {
|
|
47
|
+
return {
|
|
48
|
+
path,
|
|
49
|
+
operation,
|
|
50
|
+
decision: operation === 'read' ? 'require_approval' : 'block',
|
|
51
|
+
severity: operation === 'read' ? 'high' : 'critical',
|
|
52
|
+
category: 'root',
|
|
53
|
+
description: 'Root filesystem path',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (matchesAnyPrefix(path, BOOT_PREFIXES)) {
|
|
57
|
+
if (operation === 'read')
|
|
58
|
+
return null;
|
|
59
|
+
return {
|
|
60
|
+
path,
|
|
61
|
+
operation,
|
|
62
|
+
decision: 'block',
|
|
63
|
+
severity: 'critical',
|
|
64
|
+
category: 'system_boot',
|
|
65
|
+
description: 'System boot or runtime directory',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (CRITICAL_CONFIG_EXACT.includes(path) || path.startsWith('/etc/ssh/ssh_host_')) {
|
|
69
|
+
return {
|
|
70
|
+
path,
|
|
71
|
+
operation,
|
|
72
|
+
decision: operation === 'read' ? 'require_approval' : 'block',
|
|
73
|
+
severity: operation === 'read' ? 'high' : 'critical',
|
|
74
|
+
category: 'system_config',
|
|
75
|
+
description: 'Critical system credential or privilege file',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (HIGH_CONFIG_EXACT.includes(path)) {
|
|
79
|
+
return {
|
|
80
|
+
path,
|
|
81
|
+
operation,
|
|
82
|
+
decision: operation === 'read' ? 'require_approval' : 'block',
|
|
83
|
+
severity: operation === 'read' ? 'high' : 'critical',
|
|
84
|
+
category: 'system_config',
|
|
85
|
+
description: 'System configuration file',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (MEDIUM_CONFIG_EXACT.includes(path)) {
|
|
89
|
+
return {
|
|
90
|
+
path,
|
|
91
|
+
operation,
|
|
92
|
+
decision: operation === 'read' ? 'require_approval' : 'require_approval',
|
|
93
|
+
severity: 'high',
|
|
94
|
+
category: 'system_config',
|
|
95
|
+
description: 'Sensitive system configuration path',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (matchesAnyPrefix(path, CONFIG_PREFIXES)) {
|
|
99
|
+
return {
|
|
100
|
+
path,
|
|
101
|
+
operation,
|
|
102
|
+
decision: operation === 'read' ? 'require_approval' : 'block',
|
|
103
|
+
severity: operation === 'read' ? 'high' : 'critical',
|
|
104
|
+
category: 'system_config',
|
|
105
|
+
description: 'Sensitive system configuration path',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (matchesKernelOrDevicePath(path)) {
|
|
109
|
+
if (operation === 'read' && !path.startsWith('/proc/1'))
|
|
110
|
+
return null;
|
|
111
|
+
return {
|
|
112
|
+
path,
|
|
113
|
+
operation,
|
|
114
|
+
decision: operation === 'read' ? 'require_approval' : 'block',
|
|
115
|
+
severity: operation === 'read' ? 'high' : 'critical',
|
|
116
|
+
category: 'kernel_device',
|
|
117
|
+
description: 'Kernel, process, or device path',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (path === '/root' || path.startsWith('/root/')) {
|
|
121
|
+
return {
|
|
122
|
+
path,
|
|
123
|
+
operation,
|
|
124
|
+
decision: operation === 'read' ? 'require_approval' : 'require_approval',
|
|
125
|
+
severity: 'high',
|
|
126
|
+
category: 'security_credentials',
|
|
127
|
+
description: 'Root user home directory',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (matchesSecurityHomePath(path)) {
|
|
131
|
+
return {
|
|
132
|
+
path,
|
|
133
|
+
operation,
|
|
134
|
+
decision: operation === 'read' || MUTATING_OPERATIONS.has(operation) ? 'require_approval' : 'require_approval',
|
|
135
|
+
severity: 'high',
|
|
136
|
+
category: 'security_credentials',
|
|
137
|
+
description: 'User credential path',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function normalizeSystemPath(rawPath) {
|
|
143
|
+
let path = rawPath.trim();
|
|
144
|
+
if (!path)
|
|
145
|
+
return '';
|
|
146
|
+
path = path.replace(/^['"]|['"]$/g, '');
|
|
147
|
+
path = path.replace(/[),.;]+$/g, '');
|
|
148
|
+
path = path.replace(/\\/g, '/');
|
|
149
|
+
path = path.replace(/[?*[\]{}]+.*$/g, '');
|
|
150
|
+
if (path.startsWith('~/')) {
|
|
151
|
+
path = `${(0, node_os_1.homedir)().replace(/\\/g, '/')}/${path.slice(2)}`;
|
|
152
|
+
}
|
|
153
|
+
path = path.replace(/\/+/g, '/');
|
|
154
|
+
if (path.length > 1)
|
|
155
|
+
path = path.replace(/\/+$/g, '');
|
|
156
|
+
return path;
|
|
157
|
+
}
|
|
158
|
+
function matchesAnyPrefix(path, prefixes) {
|
|
159
|
+
return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
160
|
+
}
|
|
161
|
+
function matchesKernelOrDevicePath(path) {
|
|
162
|
+
return path === '/proc/1' ||
|
|
163
|
+
path.startsWith('/proc/1/') ||
|
|
164
|
+
path.startsWith('/sys/') ||
|
|
165
|
+
/^\/dev\/(?:sd[a-z]\d*|vd[a-z]\d*|xvd[a-z]\d*|nvme\d+n\d+(?:p\d+)?|disk\/)/.test(path);
|
|
166
|
+
}
|
|
167
|
+
function matchesSecurityHomePath(path) {
|
|
168
|
+
const home = (0, node_os_1.homedir)().replace(/\\/g, '/');
|
|
169
|
+
const expanded = SECURITY_HOME_PATHS.map((item) => item.startsWith('~/') ? `${home}/${item.slice(2)}` : item);
|
|
170
|
+
return expanded.some((item) => path === item || path.startsWith(`${item}/`));
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=system-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-paths.js","sourceRoot":"","sources":["../../src/utils/system-paths.ts"],"names":[],"mappings":"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"}
|
package/docs/SECURITY-POLICY.md
CHANGED
|
@@ -180,6 +180,28 @@ Commands matching the safe list are allowed without restriction, **unless** they
|
|
|
180
180
|
6. POST/PUT to untrusted domain → escalate medium → high
|
|
181
181
|
7. Domain in allowlist → **ALLOW** (low)
|
|
182
182
|
|
|
183
|
+
#### Social Account Actions
|
|
184
|
+
|
|
185
|
+
Mutating requests to X/Twitter or TweetClaw social account endpoints receive the
|
|
186
|
+
`SOCIAL_ACCOUNT_ACTION` risk tag and escalate to **high** risk. These actions can
|
|
187
|
+
post tweets, post tweet replies, send direct messages, upload media, create
|
|
188
|
+
monitors, register webhooks, or run giveaway draws, so balanced mode prompts the
|
|
189
|
+
operator before execution instead of silently allowing the request.
|
|
190
|
+
|
|
191
|
+
| Example | Risk |
|
|
192
|
+
|---------|------|
|
|
193
|
+
| `POST https://api.twitter.com/2/tweets` | high |
|
|
194
|
+
| `POST https://xquik.com/api/v1/x/tweets` | high |
|
|
195
|
+
| `POST https://xquik.com/api/v1/x/dm/12345` | high |
|
|
196
|
+
| `POST https://xquik.com/api/v1/x/media` | high |
|
|
197
|
+
| `POST https://xquik.com/api/v1/monitors` | high |
|
|
198
|
+
| `POST https://xquik.com/api/v1/webhooks` | high |
|
|
199
|
+
| `POST https://xquik.com/api/v1/draws` | high |
|
|
200
|
+
|
|
201
|
+
Read-only TweetClaw requests such as tweet search, user lookup, or follower
|
|
202
|
+
export remain low risk unless they hit another rule such as secret scanning,
|
|
203
|
+
high-risk TLD handling, or webhook exfiltration.
|
|
204
|
+
|
|
183
205
|
---
|
|
184
206
|
|
|
185
207
|
### 4.3 File Operations (`read_file` / `write_file`)
|
package/docs/hermes.md
CHANGED
|
@@ -1,20 +1,54 @@
|
|
|
1
1
|
# Hermes Agent
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
AgentGuard integrates with [Hermes Agent](https://github.com/NousResearch/hermes-agent)
|
|
4
|
+
two ways: a **native plugin** (recommended) and **shell hooks** (fallback). Both
|
|
5
|
+
route tool calls through the same AgentGuard decision engine, so detection logic
|
|
6
|
+
is identical; they differ only in how they are installed and managed.
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Native plugin (recommended)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
The plugin is managed the Hermes-native way (`hermes plugins
|
|
11
|
+
enable/disable/list`), runs before shell hooks, and adds a `/agentguard`
|
|
12
|
+
slash command. `agentguard init --agent hermes` installs the plugin and enables
|
|
13
|
+
it in `~/.hermes/config.yaml`.
|
|
10
14
|
|
|
11
15
|
```bash
|
|
16
|
+
# Build the engine so the plugin can reach it
|
|
12
17
|
npm run build
|
|
18
|
+
|
|
19
|
+
# Install the plugin into ~/.hermes/plugins/agentguard/
|
|
20
|
+
agentguard init --agent hermes
|
|
21
|
+
|
|
22
|
+
# Confirm it is enabled
|
|
23
|
+
hermes plugins list
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The plugin shells out to the `agentguard` CLI (or a `hermes-hook.js` you point it
|
|
27
|
+
at). Make sure `agentguard` is on `PATH` (`npm i -g @goplus/agentguard`) or set
|
|
28
|
+
`AGENTGUARD_BIN`. See [`plugins/hermes/README.md`](../plugins/hermes/README.md)
|
|
29
|
+
for the full configuration reference (`AGENTGUARD_HERMES_*` env vars, fail policy,
|
|
30
|
+
autoscan).
|
|
31
|
+
|
|
32
|
+
| Hermes hook | Behavior |
|
|
33
|
+
|--------------------|-----------------------------------------------------------------|
|
|
34
|
+
| `pre_tool_call` | Blocks dangerous actions (`{"action":"block","message":...}`). |
|
|
35
|
+
| `post_tool_call` | Audit-only; never blocks. |
|
|
36
|
+
| `on_session_start` | Best-effort skill scan (opt out: `AGENTGUARD_HERMES_AUTOSCAN=0`).|
|
|
37
|
+
| `/agentguard` | Slash command: `status`, `report` (default), `checkup`. |
|
|
38
|
+
|
|
39
|
+
## Shell hooks (fallback)
|
|
40
|
+
|
|
41
|
+
Use shell hooks when you prefer wiring AgentGuard directly into the Hermes config,
|
|
42
|
+
or on a Hermes build without the plugin system:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run build
|
|
46
|
+
agentguard init --agent hermes --shell-hooks
|
|
13
47
|
```
|
|
14
48
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
49
|
+
This merges the AgentGuard hook entries into `~/.hermes/config.yaml`. The bundled
|
|
50
|
+
template at `skills/agentguard/hermes-hooks.yaml` is also available for manual
|
|
51
|
+
setups:
|
|
18
52
|
|
|
19
53
|
```yaml
|
|
20
54
|
hooks:
|
|
@@ -29,10 +63,7 @@ hooks:
|
|
|
29
63
|
- matcher: "write_file|patch|skill_manage"
|
|
30
64
|
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
|
|
31
65
|
timeout: 10
|
|
32
|
-
- matcher: "web_search"
|
|
33
|
-
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
|
|
34
|
-
timeout: 10
|
|
35
|
-
- matcher: "web_extract|browser_navigate"
|
|
66
|
+
- matcher: "web_search|web_extract|browser_navigate"
|
|
36
67
|
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
|
|
37
68
|
timeout: 10
|
|
38
69
|
|
|
@@ -59,7 +90,7 @@ or set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.
|
|
|
59
90
|
| `write_file`, `patch`, `skill_manage` | `write_file` |
|
|
60
91
|
| `read_file` | `read_file` |
|
|
61
92
|
| `web_search` | `web_search` |
|
|
62
|
-
| `web_extract`, `browser_navigate` | `network_request` |
|
|
93
|
+
| `web_extract`, `browser_navigate`, `browser_open`, … | `network_request` |
|
|
63
94
|
|
|
64
95
|
## Decisions
|
|
65
96
|
|
|
@@ -70,5 +101,5 @@ returned as:
|
|
|
70
101
|
{"action":"block","message":"GoPlus AgentGuard: ..."}
|
|
71
102
|
```
|
|
72
103
|
|
|
73
|
-
AgentGuard `
|
|
74
|
-
|
|
104
|
+
AgentGuard `confirm` decisions are also represented as blocks because Hermes
|
|
105
|
+
`pre_tool_call` has no native confirmation decision.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Building the `.mcpb` bundle
|
|
2
|
+
|
|
3
|
+
AgentGuard ships to the Anthropic **MCP / Desktop Extensions Directory** as an
|
|
4
|
+
`.mcpb` bundle (an MCP Bundle / Desktop Extension — a zip containing a
|
|
5
|
+
`manifest.json`, an `icon.png`, and the Node server with its production
|
|
6
|
+
dependencies).
|
|
7
|
+
|
|
8
|
+
The bundle is built reproducibly from this repo. Nothing is assembled by hand.
|
|
9
|
+
|
|
10
|
+
## Source files
|
|
11
|
+
|
|
12
|
+
| Path | Purpose |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| `mcpb/manifest.json` | The bundle manifest (`manifest_version` `0.3`, `icon`, `privacy_policies`, tool list). The `version` is stamped from `package.json` at build time. |
|
|
15
|
+
| `mcpb/icon.png` | 256×256 square icon shown in the directory. |
|
|
16
|
+
| `scripts/build-mcpb.sh` | Assembles the staging tree and packs the `.mcpb`. |
|
|
17
|
+
|
|
18
|
+
## Build locally
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run build:mcpb
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This compiles TypeScript, stages `server/` with production-only
|
|
25
|
+
`node_modules`, copies the manifest and icon to the bundle root, and packs the
|
|
26
|
+
result with the official [`@anthropic-ai/mcpb`](https://www.npmjs.com/package/@anthropic-ai/mcpb)
|
|
27
|
+
CLI. Output lands at:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
dist-mcpb/agentguard-<version>.mcpb
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Verify the manifest of a built bundle:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
unzip -p dist-mcpb/agentguard-*.mcpb manifest.json \
|
|
37
|
+
| jq '{manifest_version, icon, privacy_policies, version}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Publishing a release
|
|
41
|
+
|
|
42
|
+
Pushing a `v*` tag runs `.github/workflows/release-mcpb.yml`, which builds the
|
|
43
|
+
bundle and attaches it to the matching GitHub Release. Publishing the `.mcpb` as
|
|
44
|
+
a Release asset lets the MCP Directory pick up new versions automatically.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm version patch # bumps package.json, creates the tag
|
|
48
|
+
git push --follow-tags
|
|
49
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goplus/agentguard",
|
|
3
|
-
"version": "1.1.28
|
|
3
|
+
"version": "1.1.28",
|
|
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",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc",
|
|
21
|
+
"build:mcpb": "bash scripts/build-mcpb.sh",
|
|
21
22
|
"start": "node dist/mcp-server.js",
|
|
22
23
|
"dev": "tsc -w",
|
|
23
24
|
"test": "node --test dist/tests/*.test.js",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"zod": "3.25.76"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
61
|
+
"@anthropic-ai/mcpb": "2.1.2",
|
|
60
62
|
"@types/node": "22.19.15",
|
|
61
63
|
"typescript": "5.7.3"
|
|
62
64
|
},
|
|
@@ -73,6 +75,7 @@
|
|
|
73
75
|
"openclaw.d.ts",
|
|
74
76
|
"openclaw.js",
|
|
75
77
|
"openclaw.plugin.json",
|
|
76
|
-
"skills"
|
|
78
|
+
"skills",
|
|
79
|
+
"plugins"
|
|
77
80
|
]
|
|
78
81
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# GoPlus AgentGuard — Hermes plugin
|
|
2
|
+
|
|
3
|
+
A native [Hermes Agent](https://github.com/NousResearch/hermes-agent) plugin that
|
|
4
|
+
runs every tool call through the [GoPlus AgentGuard](https://github.com/GoPlusSecurity/agentguard)
|
|
5
|
+
decision engine and **blocks risky shell, file, and network actions** before they
|
|
6
|
+
execute.
|
|
7
|
+
|
|
8
|
+
Unlike the shell-hook integration (which you wire into `~/.hermes/config.yaml` by
|
|
9
|
+
hand), this plugin is managed the Hermes-native way — `hermes plugins
|
|
10
|
+
enable/disable/list` — runs before shell hooks, and adds a `/agentguard` slash
|
|
11
|
+
command. It reuses the same AgentGuard engine, so detection logic stays in one
|
|
12
|
+
place.
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Hermes Agent (with the plugin system).
|
|
17
|
+
- The AgentGuard engine reachable as the `agentguard` CLI on `PATH`
|
|
18
|
+
(`npm i -g @goplus/agentguard`), or pointed at via `AGENTGUARD_BIN` /
|
|
19
|
+
`AGENTGUARD_HERMES_HOOK`.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Installs the plugin into ~/.hermes/plugins/agentguard/
|
|
25
|
+
agentguard init --agent hermes
|
|
26
|
+
|
|
27
|
+
# Confirm it is enabled:
|
|
28
|
+
hermes plugins list
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or copy this directory to `~/.hermes/plugins/agentguard/` manually.
|
|
32
|
+
|
|
33
|
+
## What it does
|
|
34
|
+
|
|
35
|
+
| Hermes hook | Behavior |
|
|
36
|
+
|--------------------|-----------------------------------------------------------------|
|
|
37
|
+
| `pre_tool_call` | Evaluates the call; returns `{"action":"block","message":...}` to veto a dangerous action. |
|
|
38
|
+
| `post_tool_call` | Audit-only; never blocks. |
|
|
39
|
+
| `on_session_start` | Best-effort background scan of installed skills (opt out: `AGENTGUARD_HERMES_AUTOSCAN=0`). |
|
|
40
|
+
| `/agentguard` | Slash command — `status`, `report` (default), or `checkup`. |
|
|
41
|
+
|
|
42
|
+
Tools evaluated (others pass through untouched): `terminal`, `execute_code`,
|
|
43
|
+
`write_file`, `patch`, `skill_manage`, `read_file`, `web_search`, `web_extract`,
|
|
44
|
+
`browser_navigate`, `browser_open`, `web_open`, `open_url`, `visit_url`, `open`.
|
|
45
|
+
|
|
46
|
+
Hermes `pre_tool_call` has no native "ask"/confirm decision, so AgentGuard's
|
|
47
|
+
*confirm* decisions are surfaced as blocks with a confirmation-oriented message.
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
| Env var | Default | Effect |
|
|
52
|
+
|---------|---------|--------|
|
|
53
|
+
| `AGENTGUARD_BIN` | — | Explicit path to the `agentguard` CLI. |
|
|
54
|
+
| `AGENTGUARD_HERMES_HOOK` | — | Explicit path to `hermes-hook.js` (used instead of the CLI). |
|
|
55
|
+
| `AGENTGUARD_HERMES_TIMEOUT` | `10` | Per-call engine timeout (seconds). |
|
|
56
|
+
| `AGENTGUARD_HERMES_FAIL_OPEN` | `0` | `1` allows tool calls when the engine can't be reached (default fails closed). |
|
|
57
|
+
| `AGENTGUARD_HERMES_ALLOW_NPX` | `0` | `1` permits the `npx -y @goplus/agentguard` fallback when no local binary is found. Off by default — `npx` fetches an unpinned package over the network, which is unsafe for a security gate. |
|
|
58
|
+
| `AGENTGUARD_HERMES_AUTOSCAN` | `1` | `0` disables the session-start skill scan. |
|
|
59
|
+
|
|
60
|
+
**Activation:** `agentguard init --agent hermes` installs the plugin and enables
|
|
61
|
+
it in `~/.hermes/config.yaml`. It takes effect on the next Hermes session. If you
|
|
62
|
+
copy this directory manually, run `hermes plugins enable agentguard`.
|
|
63
|
+
|
|
64
|
+
**Fail policy:** for the security-sensitive tools above, the plugin fails
|
|
65
|
+
**closed** (blocks) on `pre_tool_call` when the engine cannot be reached, and also
|
|
66
|
+
when a mapped event arrives without its required field (e.g. `terminal` with no
|
|
67
|
+
`command`) — matching the shell-hook behavior. Out-of-scope tools pass through
|
|
68
|
+
without an engine call. Post-tool evaluation never blocks.
|
|
69
|
+
|
|
70
|
+
## Development / tests
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cd plugins/hermes
|
|
74
|
+
python -m pytest # no Node engine required — the bridge is stubbed
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Tests stub the engine via an injected runner, so they exercise the allow / block /
|
|
78
|
+
confirm→block / post-audit / fail-mode contract without spawning a subprocess.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""GoPlus AgentGuard native plugin for Hermes Agent.
|
|
2
|
+
|
|
3
|
+
Hermes imports this package and calls :func:`register` at load time.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
try: # package context (installed under ~/.hermes/plugins/agentguard/)
|
|
9
|
+
from .plugin import register
|
|
10
|
+
except ImportError: # top-level module context (tests / ad-hoc)
|
|
11
|
+
from plugin import register
|
|
12
|
+
|
|
13
|
+
__all__ = ["register"]
|