Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ See also:
- [Privacy and data boundary](docs/privacy-boundary.md)
- [Claude Code setup](docs/claude-code.md)
- [OpenClaw setup](docs/openclaw.md)
- [Hermes Agent setup](docs/hermes.md)
- [Codex setup](docs/codex.md)

<details>
Expand Down Expand Up @@ -300,24 +301,26 @@ GoPlus AgentGuard follows the [Agent Skills](https://agentskills.io) open standa
|----------|---------|----------|
| **Claude Code** | Full | Skill + hooks auto-guard, transcript-based skill tracking |
| **OpenClaw** | Full | Plugin hooks + **auto-scan on load** + tool→plugin mapping + **daily patrol** |
| **Hermes Agent** | Hooks | Shell hooks for `pre_tool_call` / `post_tool_call` runtime protection |
| **OpenAI Codex CLI** | Skill | Scan/action/trust commands |
| **Gemini CLI** | Skill | Scan/action/trust commands |
| **Cursor** | Skill | Scan/action/trust commands |
| **GitHub Copilot** | Skill | Scan/action/trust commands |

> **Hooks-based auto-guard (Layer 1)** works on Claude Code (PreToolUse/PostToolUse) and OpenClaw (before_tool_call/after_tool_call). Both platforms share the same decision engine via a unified adapter abstraction layer.
> **Hooks-based auto-guard (Layer 1)** works on Claude Code (PreToolUse/PostToolUse), OpenClaw (before_tool_call/after_tool_call), and Hermes Agent (pre_tool_call/post_tool_call shell hooks). These platforms share the same decision engine via a unified adapter abstraction layer.
>
> **OpenClaw exclusive**: Auto-scans all loaded plugins at registration time, automatically registers them to the trust registry, and supports automated daily security patrols via cron.

## Hook Limitations

The auto-guard hooks (Layer 1) have the following constraints:

- **Platform-specific**: Hooks rely on Claude Code's `PreToolUse` / `PostToolUse` events or OpenClaw's `before_tool_call` / `after_tool_call` plugin hooks. Both share the same decision engine via the adapter abstraction layer.
- **Platform-specific**: Hooks rely on Claude Code's `PreToolUse` / `PostToolUse` events, OpenClaw's `before_tool_call` / `after_tool_call` plugin hooks, or Hermes Agent's `pre_tool_call` / `post_tool_call` shell hooks. All share the same decision engine via the adapter abstraction layer.
- **Default-deny policy**: First-time use may trigger confirmation prompts for certain commands. A built-in safe-command allowlist (`ls`, `echo`, `pwd`, `git status`, etc.) reduces false positives.
- **Skill source tracking**:
- *Claude Code*: Infers which skill initiated an action by analyzing the conversation transcript (heuristic, not 100% precise)
- *OpenClaw*: Uses tool→plugin mapping built at registration time (more reliable)
- *Hermes Agent*: Uses session/tool metadata when available; most shell-hook payloads do not identify an initiating skill.
- **Cannot intercept skill installation itself**: Hooks can only intercept tool calls (Bash, Write, WebFetch, etc.) that a skill makes *after* loading — they cannot block the Skill tool invocation itself.
- **OpenClaw auto-scan timing**: Plugins are scanned asynchronously after AgentGuard registration completes. Very fast tool calls immediately after startup may execute before scan completes.

Expand Down
70 changes: 70 additions & 0 deletions docs/hermes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Hermes Agent

Hermes Agent can use AgentGuard through Hermes shell hooks. AgentGuard evaluates
`pre_tool_call` events before risky tools execute and returns Hermes-compatible
block decisions on stdout.

## Shell hook usage

Build AgentGuard first so the hook script can import `dist/index.js`:

```bash
npm run build
```

Copy the template from `skills/agentguard/hermes-hooks.yaml` into
`~/.hermes/config.yaml` and replace `AGENTGUARD_SKILL_DIR` with the absolute
path to the installed AgentGuard skill directory.

```yaml
hooks:
on_session_start:
- command: "env AGENTGUARD_AUTO_SCAN=1 node \"/path/to/agentguard/skills/agentguard/scripts/auto-scan.js\""
timeout: 30

pre_tool_call:
- matcher: "terminal|execute_code"
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
timeout: 10
- matcher: "write_file|patch|skill_manage"
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
timeout: 10
- matcher: "web_search|web_extract|browser_navigate"
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
timeout: 10

post_tool_call:
- matcher: "terminal|execute_code|write_file|patch|skill_manage|read_file|web_search|web_extract|browser_navigate"
command: "node \"/path/to/agentguard/skills/agentguard/scripts/hermes-hook.js\""
timeout: 5
```

Hermes asks for first-use consent for shell hooks. Use one of:

```bash
hermes --accept-hooks chat
HERMES_ACCEPT_HOOKS=1 hermes chat
```

or set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.

## Tool mapping

| Hermes tool | AgentGuard action |
|-------------|-------------------|
| `terminal`, `execute_code` | `exec_command` |
| `write_file`, `patch`, `skill_manage` | `write_file` |
| `read_file` | `read_file` |
| `web_search`, `web_extract`, `browser_navigate` | `network_request` |

## Decisions

Hermes `pre_tool_call` supports allow or block. AgentGuard `deny` decisions are
returned as:

```json
{"action":"block","message":"GoPlus AgentGuard: ..."}
```

AgentGuard `ask` decisions are also represented as blocks because Hermes shell
hooks do not have a native confirmation decision.
12 changes: 12 additions & 0 deletions skills/agentguard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,20 @@ AI Agent Security Guard — protect your AI agents from dangerous commands, data
/agentguard report — View security event audit log
/agentguard config <level> — Set protection level (strict/balanced/permissive)
/agentguard checkup — Run agent health checkup with visual HTML report
/agentguard hermes-hooks — Configure Hermes Agent shell hooks
```

## Hermes Agent hooks

When installed from SkillHub, Hermes sees the contents of this
`skills/agentguard` directory first. Runtime hooks are not loaded from
`SKILL.md` automatically; copy `hermes-hooks.yaml` into `~/.hermes/config.yaml`
and replace `AGENTGUARD_SKILL_DIR` with this skill's absolute path.

The hook runner is `scripts/hermes-hook.js`. It uses the published
`@goplus/agentguard` package, so run `npm install` inside this skill directory
or install `@goplus/agentguard` globally if the package is not already present.

## Agent Health Checkup 🦞

Run a full security health check on your AI agent and get a visual report in the browser:
Expand Down
84 changes: 83 additions & 1 deletion skills/agentguard/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ filesystem-access:
- path: "~/.openclaw/"
access: read-only
reason: "Discover installed skills and read OpenClaw config for patrol checks"
- path: "~/.hermes/"
access: read-write
reason: "Discover installed Hermes skills and help configure AgentGuard shell hooks"
- path: "~/.qclaw/"
access: read-only
reason: "Discover installed skills in QClaw environments"
Expand Down Expand Up @@ -60,9 +63,86 @@ Parse `$ARGUMENTS` to determine the subcommand:
- **`report`** — View recent security events from the audit log
- **`config <strict|balanced|permissive>`** — Set protection level
- **`checkup`** — Run a comprehensive agent health checkup and generate a visual HTML report
- **`hermes-hooks`** — Show or install Hermes shell-hook configuration for runtime protection

If no subcommand is given, or the first argument is a path, default to **scan**.

## Subcommand: hermes-hooks

Help the user configure AgentGuard runtime protection for Hermes Agent.

Hermes does **not** load hooks from `SKILL.md` automatically. Hermes shell hooks
must be present in `~/.hermes/config.yaml`. This skill ships the hook runner at
`scripts/hermes-hook.js` and a copyable template at `hermes-hooks.yaml`.

### What the Hermes hook protects

| Hermes hook | Tools | AgentGuard action |
|---|---|---|
| `pre_tool_call` | `terminal`, `execute_code` | `exec_command` |
| `pre_tool_call` | `write_file`, `patch`, `skill_manage` | `write_file` |
| `pre_tool_call` | `read_file` | `read_file` |
| `pre_tool_call` | `web_search`, `web_extract`, `browser_navigate` | `network_request` |
| `post_tool_call` | Same tools | Audit-only |

Hermes `pre_tool_call` supports allow/block only. If AgentGuard returns `ask`,
the Hermes hook reports it as a block with a confirmation-oriented message.

### Procedure

1. Resolve the AgentGuard skill directory using the "Important: Resolving Script
Paths" rules above.
2. Confirm that dependencies are available. If `node scripts/hermes-hook.js`
cannot load `@goplus/agentguard`, tell the user to run:
```bash
cd <agentguard-skill-dir> && npm install
```
or install the published package globally:
```bash
npm install -g @goplus/agentguard
```
3. Read `hermes-hooks.yaml`, replace `AGENTGUARD_SKILL_DIR` with the absolute
skill directory, and show the resulting YAML to the user.
4. Ask for explicit confirmation before editing `~/.hermes/config.yaml`.
5. If confirmed, merge the `hooks:` entries into `~/.hermes/config.yaml`.
Preserve existing hooks and config values. Do not overwrite unrelated user
configuration.
6. Tell the user to restart Hermes or launch it with one of the first-use
consent options:
```bash
hermes --accept-hooks chat
HERMES_ACCEPT_HOOKS=1 hermes chat
```
They may also set `hooks_auto_accept: true` in `~/.hermes/config.yaml`.

### Verification

After configuration, suggest a harmless test:

```bash
printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"echo hello"}}' \
| node <agentguard-skill-dir>/scripts/hermes-hook.js
```

Expected output:

```json
{}
```

And a blocked-action test:

```bash
printf '{"hook_event_name":"pre_tool_call","tool_name":"terminal","tool_input":{"command":"rm -rf /"}}' \
| node <agentguard-skill-dir>/scripts/hermes-hook.js
```

Expected output contains:

```json
{"action":"block"}
```

## Subcommand: subscribe

Run the AgentGuard Cloud threat-feed subscription workflow through the installed CLI.
Expand Down Expand Up @@ -666,6 +746,7 @@ Run these checks in parallel where possible. These are **universal agent securit
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:
- For OpenClaw / QClaw: scan `~/.openclaw/workspace/` and `~/.qclaw/workspace/` recursively — this includes **all** `workspace-agent-*/` subdirectories, not just the current agent's workspace
- For Claude Code: scan `~/.claude/` recursively
- For Hermes Agent: scan `~/.hermes/` recursively
- Patterns to detect:
- Private keys: `0x[a-fA-F0-9]{64}`, `-----BEGIN.*PRIVATE KEY-----`
- Mnemonics: sequences of 12+ BIP-39 words, `seed_phrase`, `mnemonic`
Expand All @@ -674,7 +755,7 @@ Run these checks in parallel where possible. These are **universal agent securit
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)
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/`
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
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`
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`

### Step 2: Score Calculation

Expand Down Expand Up @@ -929,6 +1010,7 @@ AgentGuard can optionally scan installed skills at session startup. **This is di

- **Claude Code**: Set environment variable `AGENTGUARD_AUTO_SCAN=1`
- **OpenClaw**: Pass `{ skipAutoScan: false }` when registering the plugin
- **Hermes Agent**: Configure the `on_session_start` shell hook from `hermes-hooks.yaml`; the template sets `AGENTGUARD_AUTO_SCAN=1` for that hook.

When enabled, auto-scan operates in **report-only mode**:

Expand Down
31 changes: 31 additions & 0 deletions skills/agentguard/hermes-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# GoPlus AgentGuard hook template for Hermes Agent.
#
# Copy this block into ~/.hermes/config.yaml and replace AGENTGUARD_SKILL_DIR
# with the absolute path to the installed AgentGuard skill directory, e.g.
# ~/.hermes/skills/agentguard or ~/.openclaw/skills/agentguard.

hooks:
on_session_start:
- command: "env AGENTGUARD_AUTO_SCAN=1 node \"AGENTGUARD_SKILL_DIR/scripts/auto-scan.js\""
timeout: 30

pre_tool_call:
- matcher: "terminal|execute_code"
command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
timeout: 10
- matcher: "write_file|patch|skill_manage"
command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
timeout: 10
- matcher: "read_file"
command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
timeout: 10
- matcher: "web_search|web_extract|browser_navigate"
command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
timeout: 10

post_tool_call:
- matcher: "terminal|execute_code|write_file|patch|skill_manage|read_file|web_search|web_extract|browser_navigate"
command: "node \"AGENTGUARD_SKILL_DIR/scripts/hermes-hook.js\""
timeout: 5

hooks_auto_accept: false
2 changes: 1 addition & 1 deletion skills/agentguard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"type": "module",
"dependencies": {
"@goplus/agentguard": "^1.0.6",
"@goplus/agentguard": "^1.1.4",
"open": "11.0.0"
}
}
5 changes: 3 additions & 2 deletions skills/agentguard/scripts/auto-scan.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* GoPlus AgentGuard — SessionStart Auto-Scan Hook
*
* Runs on session startup to discover and scan newly installed skills.
* For each skill in ~/.claude/skills/:
* For each skill in supported agent skill directories:
* 1. Calculate artifact hash
* 2. Check trust registry — skip if already registered with same hash
* 3. Run quickScan for new/updated skills
Expand Down Expand Up @@ -59,6 +59,7 @@ try {

const SKILLS_DIRS = [
join(homedir(), '.claude', 'skills'),
join(homedir(), '.hermes', 'skills'),
join(homedir(), '.openclaw', 'skills'),
];
const AGENTGUARD_DIR = join(homedir(), '.agentguard');
Expand All @@ -84,7 +85,7 @@ function writeAuditLog(entry) {
// ---------------------------------------------------------------------------

/**
* Find all skill directories under ~/.claude/skills/ and ~/.openclaw/skills/
* Find all skill directories under supported agent skill roots.
* A skill directory is one that contains a SKILL.md file.
*/
function discoverSkills() {
Expand Down
Loading
Loading