@node9/proxy 2.9.3 → 2.11.0
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/dist/cli.js +107 -8
- package/dist/cli.mjs +107 -8
- package/dist/index.js +105 -7
- package/dist/index.mjs +105 -7
- package/docs/README.md +49 -0
- package/docs/agents/README.md +29 -0
- package/docs/agents/antigravity.md +33 -0
- package/docs/agents/claude-code.md +40 -0
- package/docs/agents/claude-desktop.md +32 -0
- package/docs/agents/codex.md +37 -0
- package/docs/agents/copilot-cli.md +34 -0
- package/docs/agents/cursor.md +36 -0
- package/docs/agents/gemini-cli.md +34 -0
- package/docs/agents/hermes.md +35 -0
- package/docs/agents/opencode.md +36 -0
- package/docs/agents/pi.md +34 -0
- package/docs/agents/vscode.md +33 -0
- package/docs/agents/windsurf.md +31 -0
- package/docs/badges.md +98 -0
- package/docs/comparison.md +66 -0
- package/docs/egress.md +119 -0
- package/package.json +2 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# node9 per agent
|
|
2
|
+
|
|
3
|
+
One page per agent: what node9 wires into it, what that covers, and what it does not. The
|
|
4
|
+
"what is not covered" section is the one to read before you tell your team an agent is governed.
|
|
5
|
+
|
|
6
|
+
| Agent | Control model | Prompt scan | Guide |
|
|
7
|
+
| --------------------------- | ------------- | ----------- | -------------------------------------- |
|
|
8
|
+
| Claude Code | hooks + MCP | yes | [claude-code.md](claude-code.md) |
|
|
9
|
+
| Codex CLI | hooks + MCP | yes | [codex.md](codex.md) |
|
|
10
|
+
| GitHub Copilot CLI | hooks + MCP | yes | [copilot-cli.md](copilot-cli.md) |
|
|
11
|
+
| Gemini CLI | hooks + MCP | no | [gemini-cli.md](gemini-cli.md) |
|
|
12
|
+
| Antigravity | hooks + MCP | no | [antigravity.md](antigravity.md) |
|
|
13
|
+
| Hermes Agent | hooks | no | [hermes.md](hermes.md) |
|
|
14
|
+
| OpenCode | plugin | yes | [opencode.md](opencode.md) |
|
|
15
|
+
| Pi | extension | yes | [pi.md](pi.md) |
|
|
16
|
+
| Cursor | MCP only | no | [cursor.md](cursor.md) |
|
|
17
|
+
| Windsurf | MCP only | no | [windsurf.md](windsurf.md) |
|
|
18
|
+
| VS Code (Copilot extension) | MCP only | no | [vscode.md](vscode.md) |
|
|
19
|
+
| Claude Desktop | MCP only | no | [claude-desktop.md](claude-desktop.md) |
|
|
20
|
+
|
|
21
|
+
"Hooks" means node9 sees every tool call before it runs. "MCP only" means node9 sees the tools
|
|
22
|
+
that go through MCP servers and nothing the editor does on its own.
|
|
23
|
+
|
|
24
|
+
Every page ends with the same two commands, and they are the real check:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
node9 doctor
|
|
28
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa'
|
|
29
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# node9 with Antigravity
|
|
2
|
+
|
|
3
|
+
| Surface | How node9 is wired | What it does |
|
|
4
|
+
| ----------------- | ------------------------------------------------------ | ------------------------------------------- |
|
|
5
|
+
| Every tool call | `PreToolUse` hook in `~/.gemini/config/hooks.json` | allow / review / block before the tool runs |
|
|
6
|
+
| Every tool result | `PostToolUse` hook | audit record |
|
|
7
|
+
| MCP servers | `~/.gemini/config/mcp_config.json` entries are wrapped | per-tool allow / review / block |
|
|
8
|
+
|
|
9
|
+
Payload shape verified against Antigravity 1.0.6.
|
|
10
|
+
|
|
11
|
+
## Set it up
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node9 agents add antigravity
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
18
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
19
|
+
|
|
20
|
+
## What is not covered
|
|
21
|
+
|
|
22
|
+
- **No prompt scan.** There is no prompt event to hook.
|
|
23
|
+
- Cost is not tracked for Antigravity.
|
|
24
|
+
|
|
25
|
+
## Verify it on this machine
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
29
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
33
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# node9 with Claude Code
|
|
2
|
+
|
|
3
|
+
Claude Code is the most fully covered agent.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------------- | ----------------------------------------------------------------- | --------------------------------------------------------- |
|
|
7
|
+
| Every tool call | `PreToolUse` hook in `~/.claude/settings.json` | allow / review / block before the tool runs |
|
|
8
|
+
| Every tool result | `PostToolUse` hook | writes the audit record |
|
|
9
|
+
| Pasted prompts | `UserPromptSubmit` hook | secret pasted into the prompt is caught before it is sent |
|
|
10
|
+
| MCP servers | entries in `~/.claude.json` are wrapped through the node9 gateway | per-tool allow / review / block |
|
|
11
|
+
| Cost | reads `~/.claude/projects` session logs | per-project spend in `node9 report` |
|
|
12
|
+
|
|
13
|
+
The `PreToolUse` hook runs in every Claude Code permission mode, including
|
|
14
|
+
`--dangerously-skip-permissions`. That was verified with a standalone probe, and it is
|
|
15
|
+
undocumented behaviour, so treat it as a fact about today's Claude Code rather than a guarantee.
|
|
16
|
+
|
|
17
|
+
## Set it up
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
node9 agents add claude
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
24
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
25
|
+
|
|
26
|
+
## What is not covered
|
|
27
|
+
|
|
28
|
+
- Tool **output** is observed, not gated. Claude Code's `PostToolUse` cannot suppress a
|
|
29
|
+
result, so a secret or an injected instruction inside a tool result is recorded and the
|
|
30
|
+
session is tainted for review on the next call; it is not stripped before Claude sees it.
|
|
31
|
+
|
|
32
|
+
## Verify it on this machine
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
36
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
40
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# node9 with Claude Desktop
|
|
2
|
+
|
|
3
|
+
Claude Desktop only calls tools through MCP, so wrapping its servers covers every tool it
|
|
4
|
+
can use.
|
|
5
|
+
|
|
6
|
+
| Surface | How node9 is wired | What it does |
|
|
7
|
+
| ----------- | ----------------------------------------------------------------------------- | ------------------------------- |
|
|
8
|
+
| MCP servers | entries in `claude_desktop_config.json` are wrapped through the node9 gateway | per-tool allow / review / block |
|
|
9
|
+
|
|
10
|
+
## Set it up
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
node9 agents add claudeDesktop
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
17
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
18
|
+
|
|
19
|
+
## What is not covered
|
|
20
|
+
|
|
21
|
+
- No prompt scan and no cost tracking.
|
|
22
|
+
- `node9 doctor` and `node9 status` do not list Claude Desktop yet.
|
|
23
|
+
|
|
24
|
+
## Verify it on this machine
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
28
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
32
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# node9 with Codex CLI
|
|
2
|
+
|
|
3
|
+
Codex gets the same pre-tool gate as Claude Code.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------------- | --------------------------------------------------- | -------------------------------------------------- |
|
|
7
|
+
| Every tool call | `PreToolUse` hook in `~/.codex/hooks.json` | allow / review / block before the tool runs |
|
|
8
|
+
| Pasted prompts | `UserPromptSubmit` hook | prompt secret scan |
|
|
9
|
+
| Every tool result | `PostToolUse` hook | audit record; verified against real Codex sessions |
|
|
10
|
+
| MCP servers | `mcp_servers` in `~/.codex/config.toml` are wrapped | per-tool allow / review / block |
|
|
11
|
+
|
|
12
|
+
Headless `codex exec` runs the same hooks. Verified with a nonce probe against the real
|
|
13
|
+
trusted-hooks config: both the pre and post hook fired.
|
|
14
|
+
|
|
15
|
+
## Set it up
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
node9 agents add codex
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
22
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
23
|
+
|
|
24
|
+
## What is not covered
|
|
25
|
+
|
|
26
|
+
- Cost is not tracked for Codex. `node9 report` cost figures are Claude Code only today.
|
|
27
|
+
- Tool output is observed, not gated (same as Claude Code).
|
|
28
|
+
|
|
29
|
+
## Verify it on this machine
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
33
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
37
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# node9 with GitHub Copilot CLI
|
|
2
|
+
|
|
3
|
+
Copilot CLI is wired on three events, which makes it one of the strongest integrations.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------------- | ------------------------------------------------ | ------------------------------------------- |
|
|
7
|
+
| Every tool call | `PreToolUse` in `~/.copilot/hooks/node9.json` | allow / review / block before the tool runs |
|
|
8
|
+
| Every tool result | `PostToolUse` | audit record |
|
|
9
|
+
| Pasted prompts | `UserPromptSubmit` | prompt secret scan |
|
|
10
|
+
| MCP servers | `~/.copilot/mcp-config.json` entries are wrapped | per-tool allow / review / block |
|
|
11
|
+
|
|
12
|
+
## Set it up
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node9 agents add copilot
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
19
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
20
|
+
|
|
21
|
+
## What is not covered
|
|
22
|
+
|
|
23
|
+
- Cost is not tracked for Copilot.
|
|
24
|
+
- Tool output is observed, not gated.
|
|
25
|
+
|
|
26
|
+
## Verify it on this machine
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
30
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
34
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# node9 with Cursor
|
|
2
|
+
|
|
3
|
+
Cursor has no pre-execution hook, so node9 protects it through MCP only.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
|
|
7
|
+
| MCP servers | `~/.cursor/mcp.json` entries are wrapped through the node9 gateway | every `tools/call` is authorized, pinned and env-scrubbed before it reaches the server |
|
|
8
|
+
|
|
9
|
+
For tools that go through MCP this is the same allow / review / block gate every other agent
|
|
10
|
+
gets.
|
|
11
|
+
|
|
12
|
+
## Set it up
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node9 agents add cursor
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
19
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
20
|
+
|
|
21
|
+
## What is not covered
|
|
22
|
+
|
|
23
|
+
- **Cursor's own terminal and file edits are not gated.** Nothing in Cursor exposes them to a
|
|
24
|
+
hook today. If Cursor runs `cat ~/.ssh/id_rsa` in its built-in terminal, node9 does not see it.
|
|
25
|
+
- No prompt scan, no audit of native tool calls, no cost tracking.
|
|
26
|
+
- Say this plainly to your team: with Cursor, node9 governs the MCP surface, not the editor.
|
|
27
|
+
|
|
28
|
+
## Verify it on this machine
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
32
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
36
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# node9 with Gemini CLI
|
|
2
|
+
|
|
3
|
+
| Surface | How node9 is wired | What it does |
|
|
4
|
+
| ----------------- | ----------------------------------------------------- | ------------------------------------------- |
|
|
5
|
+
| Every tool call | `BeforeTool` hook in `~/.gemini/settings.json` | allow / review / block before the tool runs |
|
|
6
|
+
| Every tool result | `AfterTool` hook | audit record |
|
|
7
|
+
| MCP servers | `mcpServers` in `~/.gemini/settings.json` are wrapped | per-tool allow / review / block |
|
|
8
|
+
|
|
9
|
+
## Set it up
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node9 agents add gemini
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
16
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
17
|
+
|
|
18
|
+
## What is not covered
|
|
19
|
+
|
|
20
|
+
- **No prompt scan.** Gemini CLI has no prompt-submit hook, so a secret pasted into the prompt
|
|
21
|
+
is not caught until it shows up in a tool call.
|
|
22
|
+
- The session id Gemini sends drifts across resumes, so a review taint set before a resume can
|
|
23
|
+
be orphaned. Within one session it works.
|
|
24
|
+
- Cost is not tracked for Gemini.
|
|
25
|
+
|
|
26
|
+
## Verify it on this machine
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
30
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
34
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# node9 with Hermes Agent
|
|
2
|
+
|
|
3
|
+
| Surface | How node9 is wired | What it does |
|
|
4
|
+
| ----------------- | ------------------------------------------------------ | ------------------------------------------- |
|
|
5
|
+
| Every tool call | `pre_tool_call` command hook in the Hermes YAML config | allow / review / block before the tool runs |
|
|
6
|
+
| Every tool result | `post_tool_call` command hook | audit record |
|
|
7
|
+
|
|
8
|
+
Run `node9 status` to see the exact config path on your machine.
|
|
9
|
+
|
|
10
|
+
## Set it up
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
node9 agents add hermes
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
17
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
18
|
+
|
|
19
|
+
## What is not covered
|
|
20
|
+
|
|
21
|
+
- **No prompt scan.** Hermes has no prompt event.
|
|
22
|
+
- **No MCP wrapping.** Hermes' MCP servers are not routed through the node9 gateway.
|
|
23
|
+
- Hermes sends an empty session id on the pre-tool hook, so the output-taint review gate
|
|
24
|
+
does not work for Hermes. Upstream issue: NousResearch/hermes-agent#48311.
|
|
25
|
+
- Cost is not tracked for Hermes.
|
|
26
|
+
|
|
27
|
+
## Verify it on this machine
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
31
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
35
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# node9 with OpenCode
|
|
2
|
+
|
|
3
|
+
OpenCode is protected by a node9 plugin rather than hooks or MCP.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
7
|
+
| Every tool call | `tool.execute.before` in the node9 plugin under the OpenCode config directory (`plugins/node9.js`) | allow / review / block before the tool runs |
|
|
8
|
+
| Prompts | `chat.message` | prompt secret scan |
|
|
9
|
+
| Every tool result | `tool.execute.after` | audit record, and output redaction in place |
|
|
10
|
+
|
|
11
|
+
Because the plugin can mutate tool output, secrets in a result are redacted before the model
|
|
12
|
+
sees them. That is stronger than the observe-only agents.
|
|
13
|
+
|
|
14
|
+
## Set it up
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
node9 agents add opencode
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
21
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
22
|
+
|
|
23
|
+
## What is not covered
|
|
24
|
+
|
|
25
|
+
- MCP servers are not wrapped for OpenCode; the plugin gates tool calls directly.
|
|
26
|
+
- Cost is not tracked for OpenCode.
|
|
27
|
+
|
|
28
|
+
## Verify it on this machine
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
32
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
36
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# node9 with Pi
|
|
2
|
+
|
|
3
|
+
Pi is protected by a node9 extension rather than hooks or MCP.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| --------------------------------- | ------------------------------------------------ | ------------------------------------------- |
|
|
7
|
+
| Every tool call | `tool_call` in `~/.pi/agent/extensions/node9.js` | allow / review / block before the tool runs |
|
|
8
|
+
| Prompts | `input` | prompt secret scan |
|
|
9
|
+
| The `!` / `!!` shell side channel | `user_bash` | gated like any other command |
|
|
10
|
+
| Every tool result | `tool_result` | audit record, and output redaction in place |
|
|
11
|
+
|
|
12
|
+
## Set it up
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node9 agents add pi
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
19
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
20
|
+
|
|
21
|
+
## What is not covered
|
|
22
|
+
|
|
23
|
+
- MCP servers are not wrapped for Pi.
|
|
24
|
+
- Cost is not tracked for Pi.
|
|
25
|
+
|
|
26
|
+
## Verify it on this machine
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
30
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
34
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# node9 with VS Code (Copilot extension)
|
|
2
|
+
|
|
3
|
+
The VS Code Copilot extension exposes no hook, so node9 wraps its MCP servers only. This is
|
|
4
|
+
a different integration from the Copilot **CLI**, which has full hooks; see
|
|
5
|
+
[copilot-cli.md](copilot-cli.md).
|
|
6
|
+
|
|
7
|
+
| Surface | How node9 is wired | What it does |
|
|
8
|
+
| ----------- | ------------------------------------------------------------------ | ------------------------------- |
|
|
9
|
+
| MCP servers | VS Code's MCP config entries are wrapped through the node9 gateway | per-tool allow / review / block |
|
|
10
|
+
|
|
11
|
+
## Set it up
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node9 agents add vscode
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
18
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
19
|
+
|
|
20
|
+
## What is not covered
|
|
21
|
+
|
|
22
|
+
- The editor's own terminal and edits are not gated.
|
|
23
|
+
- `node9 doctor` and `node9 status` do not list VS Code yet.
|
|
24
|
+
|
|
25
|
+
## Verify it on this machine
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
29
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
33
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# node9 with Windsurf
|
|
2
|
+
|
|
3
|
+
Windsurf exposes no pre-execution hook, so node9 wraps its MCP servers and nothing else.
|
|
4
|
+
|
|
5
|
+
| Surface | How node9 is wired | What it does |
|
|
6
|
+
| ----------- | ------------------------------------------------------------------- | ------------------------------- |
|
|
7
|
+
| MCP servers | Windsurf's MCP config entries are wrapped through the node9 gateway | per-tool allow / review / block |
|
|
8
|
+
|
|
9
|
+
## Set it up
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node9 agents add windsurf
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`node9 init` does this for every agent it detects on the machine. Either command is safe to
|
|
16
|
+
re-run; it repairs a hook that an agent update removed and leaves everything else alone.
|
|
17
|
+
|
|
18
|
+
## What is not covered
|
|
19
|
+
|
|
20
|
+
- Windsurf's own terminal and edits are not gated, and there is no audit of them.
|
|
21
|
+
- `node9 doctor` and `node9 status` do not list Windsurf yet; check the MCP config by hand.
|
|
22
|
+
|
|
23
|
+
## Verify it on this machine
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node9 doctor # is the hook (or MCP wrap) actually in place?
|
|
27
|
+
node9 explain Bash 'cat ~/.ssh/id_rsa' # shows the verdict the live hook enforces: BLOCK
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`node9 explain` prints the exact rule that fires and where the decision came from. If `doctor`
|
|
31
|
+
says the agent is not wired, the guard is not running, whatever the config looks like.
|
package/docs/badges.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# node9 badges
|
|
2
|
+
|
|
3
|
+
Drop-in Markdown for showing that a project's agent-security surface is checked by node9.
|
|
4
|
+
|
|
5
|
+
Two badges ship. One is for projects that use node9; the other is reserved for this repository.
|
|
6
|
+
|
|
7
|
+
## `scanned by node9`
|
|
8
|
+
|
|
9
|
+
Use this on any public project where the node9 Action runs in CI. It says that the repo's
|
|
10
|
+
committed agent configuration — CI workflows, agent settings, MCP servers, instruction files — is
|
|
11
|
+
inspected on every pull request, and it links readers back to node9 so they can judge what the
|
|
12
|
+
badge is worth.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
### Requirements
|
|
17
|
+
|
|
18
|
+
Only display this badge if the node9 Action genuinely runs on every pull request. The honest CI
|
|
19
|
+
wiring is the signal; the badge is only a surface for it. A badge on a repo that does not run the
|
|
20
|
+
check is misleading, and it devalues the badge for everyone who does.
|
|
21
|
+
|
|
22
|
+
The minimum is a job that runs `node9-ai/node9-proxy@v2` on `pull_request`:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
# .github/workflows/agent-security.yml
|
|
26
|
+
name: node9 agent-security
|
|
27
|
+
on: pull_request
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
pull-requests: write
|
|
31
|
+
checks: write
|
|
32
|
+
jobs:
|
|
33
|
+
scan:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: node9-ai/node9-proxy@v2
|
|
37
|
+
with:
|
|
38
|
+
fail-on: high # 'never' to comment without gating
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`fail-on: never` still counts as running the check: the badge claims the surface is _inspected_,
|
|
42
|
+
not that merges are blocked.
|
|
43
|
+
|
|
44
|
+
### Markdown
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
[](https://github.com/node9-ai/node9-proxy)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### HTML
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<a href="https://github.com/node9-ai/node9-proxy">
|
|
54
|
+
<img
|
|
55
|
+
alt="scanned by node9"
|
|
56
|
+
src="https://img.shields.io/badge/scanned%20by-node9-a855f7?style=flat&labelColor=%231A1A2E&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNCAxNCI+PHBhdGggZmlsbD0iI0Y1RTlGRiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDAuNCAxLjYgMi41djQuMmMwIDMuMSAyLjMgNS42IDUuNCA2LjkgMy4xLTEuMyA1LjQtMy44IDUuNC02LjlWMi41TDcgMC40Wm0wIDEuNSAzLjkgMS41djMuM2MwIDIuMy0xLjYgNC4yLTMuOSA1LjMtMi4zLTEuMS0zLjktMy0zLjktNS4zVjMuNEw3IDEuOVptMCAyLjJhMS45IDEuOSAwIDAgMC0xIDMuNXYxLjZoMlY3LjZhMS45IDEuOSAwIDAgMC0xLTMuNVoiLz48L3N2Zz4K"
|
|
57
|
+
/>
|
|
58
|
+
</a>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Placement
|
|
62
|
+
|
|
63
|
+
Put it with the other status badges at the top of the README. It follows the standard shields.io
|
|
64
|
+
layout, so it sits cleanly next to CI, coverage, and license badges.
|
|
65
|
+
|
|
66
|
+
### Link target
|
|
67
|
+
|
|
68
|
+
Link the badge to `https://github.com/node9-ai/node9-proxy` so a reader can click through and find out what it asserts. Linking to
|
|
69
|
+
your own passing CI run instead is also fine.
|
|
70
|
+
|
|
71
|
+
## `node9 self-scanned`
|
|
72
|
+
|
|
73
|
+
**Reserved for this repository.** It says that node9 runs its own Action against its own source on
|
|
74
|
+
every pull request, and gates merges on the result — dogfooding in public. It links to the workflow
|
|
75
|
+
that does it, so the claim is checkable in one click.
|
|
76
|
+
|
|
77
|
+

|
|
78
|
+
|
|
79
|
+
```markdown
|
|
80
|
+
[](https://github.com/node9-ai/node9-proxy/blob/main/.github/workflows/agent-security.yml)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
On any other project, use `scanned by node9` above. This wording is only honest here.
|
|
84
|
+
|
|
85
|
+
## Brand
|
|
86
|
+
|
|
87
|
+
- Label background: `#1A1A2E`
|
|
88
|
+
- Message background: `#a855f7` (the node9 accent)
|
|
89
|
+
- Logo: `#F5E9FF`, a shield glyph inlined as an SVG data URI
|
|
90
|
+
|
|
91
|
+
shields.io renders an inlined SVG verbatim rather than tinting it, so the fill is baked into the
|
|
92
|
+
glyph. Do not change the colours or substitute a different logo. The consistency is the point: a
|
|
93
|
+
badge is only recognisable if it looks the same everywhere.
|
|
94
|
+
|
|
95
|
+
## Problems
|
|
96
|
+
|
|
97
|
+
If the badge renders oddly in your README, open an issue on
|
|
98
|
+
[node9-ai/node9-proxy](https://github.com/node9-ai/node9-proxy/issues) with the rendered image and your README source.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Where node9 sits among agent-security tools
|
|
2
|
+
|
|
3
|
+
Most comparisons in this space grade tools on runtime mediation: where the allow / deny decision
|
|
4
|
+
is computed, where it is enforced, and what evidence the tool emits. That is a fair axis and
|
|
5
|
+
node9 is not the strongest tool on it. This page grades on a second axis that the same
|
|
6
|
+
comparisons leave out: **what a tool can see before an agent ever runs**.
|
|
7
|
+
|
|
8
|
+
Every claim below about node9 is code-verified against this repository. Claims about other
|
|
9
|
+
tools come from their own public documentation as of September 2026; if one is wrong, open an
|
|
10
|
+
issue and it will be corrected.
|
|
11
|
+
|
|
12
|
+
## Two questions, two fields
|
|
13
|
+
|
|
14
|
+
| Question | Who answers it |
|
|
15
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| At runtime, can a mediator stop this action and prove it did? | pipelock, CAPSEM, Signet, AgentMint, Cupcake, agentsh, Docker MCP gateway, Microsoft AGT, Invariant, **node9** |
|
|
17
|
+
| Before any run, is this repository's committed agent surface hijackable? | **node9 `scan-repo`**, and in narrow slices Snyk `mcp-scan` (MCP tool definitions) and Trail of Bits `mcp-context-protector` (MCP drift) |
|
|
18
|
+
|
|
19
|
+
The first field is crowded and well served. The second is nearly empty.
|
|
20
|
+
|
|
21
|
+
## The committed agent surface
|
|
22
|
+
|
|
23
|
+
An agent wired into a repository leaves configuration behind: hook files, workflow YAML, MCP
|
|
24
|
+
server pins, instruction files. That configuration decides what an outsider can make the agent
|
|
25
|
+
do, and it is reviewable without running anything.
|
|
26
|
+
|
|
27
|
+
| Check | What it reads | What it flags | Nearest alternative |
|
|
28
|
+
| ----- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
|
29
|
+
| CI-1 | `.claude/settings.json` and hooks | committed config that pre-authorizes broad tools or runs remote hooks | none |
|
|
30
|
+
| CI-2 | `.github/workflows/*.yml` | an agent that an outsider can trigger with the repository's secrets in reach (`pull_request_target`, untrusted checkout, no actor gate) | none |
|
|
31
|
+
| CI-3 | `.mcp.json`, `.cursor/mcp.json` | unpinned or `@latest` MCP servers, inline credentials | Snyk `mcp-scan` (definitions, not pins) |
|
|
32
|
+
| CI-4 | workflow YAML | secrets an injected agent could exfiltrate, given the shell it has | none |
|
|
33
|
+
| CI-6 | `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `copilot-instructions.md`, `.windsurfrules`, `.clinerules` | poisoned or dangerous instructions, including concealed text | none |
|
|
34
|
+
|
|
35
|
+
Not built: CI-5, drift of these files over time. `mcp-context-protector` does drift for MCP tool
|
|
36
|
+
descriptions; nobody does it for the rest of the surface, including node9.
|
|
37
|
+
|
|
38
|
+
Runs as `npx node9-ai scan-repo <owner/repo>` on any public repository with no install and no
|
|
39
|
+
token, or as a GitHub Action that fails the PR. This repository runs it on itself on every pull
|
|
40
|
+
request.
|
|
41
|
+
|
|
42
|
+
## Runtime: what node9 is and is not
|
|
43
|
+
|
|
44
|
+
node9 gates tool calls in the agent's own hook system (Claude Code, Codex, Copilot CLI, Gemini
|
|
45
|
+
CLI, Antigravity, Hermes, OpenCode, Pi) or at the MCP boundary (Cursor, Windsurf, VS Code,
|
|
46
|
+
Claude Desktop). Shell commands are parsed as an AST, so `$(cat ~/.aws/credentials | base64)`
|
|
47
|
+
is a credential read, not a string that happens to contain the word `cat`.
|
|
48
|
+
|
|
49
|
+
Where the runtime tools are ahead of node9, in their own words and ours:
|
|
50
|
+
|
|
51
|
+
| Capability | Strongest tool on it | node9 today |
|
|
52
|
+
| ------------------------------------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| Offline-verifiable, signed evidence per decision | pipelock (Ed25519, hash-chained receipts) | audit log with privacy hashing; release artifacts are signed, decisions are not |
|
|
54
|
+
| Content scanning of HTTP and WebSocket egress | pipelock | egress is a destination gate, off by default; no wire-level content scan |
|
|
55
|
+
| Kernel or container boundary | agentsh, pipelock containment, CAPSEM | `node9 sandbox` is a first-phase container run |
|
|
56
|
+
| Prompt-injection detection on tool output | pipelock, Invariant | observed and quarantined on hook agents, redacted in place on OpenCode and Pi; not blocked before the model sees it on Claude Code or Codex |
|
|
57
|
+
|
|
58
|
+
Where node9 is ahead: per-agent wiring across twelve agents with one `node9 doctor` that tells
|
|
59
|
+
you which hook is actually in place, and the repository scan above.
|
|
60
|
+
|
|
61
|
+
## How to read this page
|
|
62
|
+
|
|
63
|
+
If your risk is an agent that is already running, pick from the first field and compare
|
|
64
|
+
evidence models. If your risk is a repository that wires an agent into CI, there is one tool
|
|
65
|
+
that reads that surface, and this is it. Most teams have both risks, and node9 is the only one
|
|
66
|
+
of the set that tries to cover both, which is also why it is not the deepest on either.
|