agentinel 0.0.1 → 1.0.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 +196 -70
- package/dist/asen.js +36 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,104 +1,230 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="assets/banner.jpg" alt="Agentinel Banner" width="100%" />
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
[](https://www.npmjs.com/package/agentinel)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/aman-janwani/agentinel/actions)
|
|
7
|
+
[](#)
|
|
8
|
+
</div>
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
they install a package that was registered last week with no history, sometimes one whose name they
|
|
7
|
-
invented, and sometimes a legitimate package that pulls in a compromised one three levels deep.
|
|
8
|
-
agentinel checks every package an install would bring in, at the moment the agent reaches for it,
|
|
9
|
-
and tells the agent why something looks wrong so it can back off.
|
|
10
|
+
<br />
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
> **The zero-cost, locally-run package guardrail for your AI coding agents.**
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
*Agentinel guards your AI agent when it installs npm packages, catching hallucinated dependencies, slopsquatting, and malicious packages before they execute on your machine.*
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 📖 The Problem
|
|
19
|
+
|
|
20
|
+
AI coding agents (like Claude Code, Copilot, or Cursor) install dependencies on your behalf, often while you aren't looking closely.
|
|
21
|
+
- Sometimes they install a package that was registered last week with no history.
|
|
22
|
+
- Sometimes they install a package whose name they entirely **hallucinated**.
|
|
23
|
+
- Sometimes, they install a legitimate package that pulls in a compromised one three levels deep.
|
|
24
|
+
|
|
25
|
+
**Agentinel** checks every package an install would bring in, at the exact moment the agent reaches for it. It evaluates the package against a bundled, locally-run database of over 216,000 known malicious packages and zero-cost registry heuristics. It then tells the agent why something looks wrong so the AI can back off and reconsider.
|
|
26
|
+
|
|
27
|
+
Every other tool in this space guards your terminal. **Agentinel guards your agent.**
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ⚡ Features & Security Philosophy
|
|
32
|
+
|
|
33
|
+
- **Zero-Cost & Private:** Agentinel does no network interception, runs no cloud proxies, and requires no paid APIs. The malware list is matched locally.
|
|
34
|
+
- **Deep Tree Scanning:** Checks every package an install would *actually* bring in, not just the one named. (`npm install express` brings in 67 packages. We check all 67).
|
|
35
|
+
- **Known Malware:** Bundles a local OSV database of 216,000+ confirmed malicious packages.
|
|
36
|
+
- **Zero False Positives on Popular Packages:** Tested against the top 100 npm packages.
|
|
37
|
+
- **Heuristic Scanning:** Flags npm takedowns, packages under 30 days old with < 1k downloads (slopsquatting), publisher drift, and non-existent hallucinated names.
|
|
38
|
+
- **Cross-Platform Compatibility:** Fully tested and natively supported across macOS, Linux, and Windows.
|
|
39
|
+
- **Fails Open:** Designed so that if it crashes or can't reach the registry, it fails open. It will never permanently wedge your terminal or block your work.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 🚀 Installation
|
|
44
|
+
|
|
45
|
+
Install it as a dev-dependency in your repository:
|
|
14
46
|
|
|
15
47
|
```sh
|
|
16
|
-
npm install --save-dev agentinel
|
|
48
|
+
npm install --save-dev agentinel
|
|
49
|
+
npx asen init
|
|
17
50
|
```
|
|
51
|
+
*(No account, no server, no complex configuration.)*
|
|
18
52
|
|
|
19
|
-
|
|
20
|
-
server, no configuration.
|
|
53
|
+
---
|
|
21
54
|
|
|
22
|
-
|
|
23
|
-
resolves through npx on every command, which is slower.
|
|
55
|
+
## 🤖 1. Agentic Use (Native Hooks)
|
|
24
56
|
|
|
25
|
-
|
|
57
|
+
Agentinel wires itself directly into the native pre-execution hooks of popular CLI agents: **Claude Code, Codex CLI, Copilot CLI, and Gemini CLI**.
|
|
26
58
|
|
|
27
|
-
|
|
28
|
-
looks like one package and installs 67, and most real npm malware hides in the transitive ones.
|
|
59
|
+
When an agent attempts to run `npm install`, Agentinel intercepts the event (e.g., `PreToolUse` for Claude) and scans the requested dependency tree.
|
|
29
60
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- **npm takedowns.** Packages npm itself has pulled for security.
|
|
33
|
-
- **New and unused.** Registered in the last 30 days with under 1,000 monthly downloads, the classic
|
|
34
|
-
slopsquat shape.
|
|
35
|
-
- **No track record.** No repository, one version ever, barely downloaded.
|
|
36
|
-
- **Sudden bloat.** A patch release that triples the amount of code, paired with a change of
|
|
37
|
-
publisher: the fingerprint of a hijacked maintainer account.
|
|
61
|
+
### How it feeds back to the AI
|
|
62
|
+
If Agentinel flags a package, it feeds the context *back* to the AI agent in a concise format the agent understands, rather than just crashing the terminal.
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
**Example Intercept:**
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"hookEvent": "PreToolUse",
|
|
68
|
+
"action": "BLOCK",
|
|
69
|
+
"reason": "agentinel blocked 'react-router-v7-beta': Package does not exist on npm (hallucination)."
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
The AI reads this, realizes the package is fake or malicious, and intelligently searches for the correct alternative instead of blindly retrying.
|
|
73
|
+
|
|
74
|
+
---
|
|
41
75
|
|
|
42
|
-
|
|
43
|
-
package in its known-bad test set. A security tool that cries wolf gets uninstalled the same day, so
|
|
44
|
-
that number is the one that matters.
|
|
76
|
+
## 🧑💻 2. Normal / Human Use (The Shim)
|
|
45
77
|
|
|
46
|
-
|
|
78
|
+
What about installs that never go through an agent? (e.g., You typing `npm install` manually).
|
|
47
79
|
|
|
48
|
-
|
|
49
|
-
Gemini CLI**. `asen init` wires up whichever of them it finds on your machine. When it blocks
|
|
50
|
-
something in strict mode, the agent is told why in a way it understands, so it looks for a safe
|
|
51
|
-
alternative instead of retrying.
|
|
80
|
+
Agentinel provides an opt-in **PATH shim**.
|
|
52
81
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
```sh
|
|
83
|
+
npx asen init --shim
|
|
84
|
+
```
|
|
56
85
|
|
|
57
|
-
|
|
86
|
+
This puts a tiny, fail-open wrapper script earlier in your `PATH`. When you type `npm install`, the shim checks the package first. If it's safe, the real `npm` command runs instantly.
|
|
58
87
|
|
|
59
|
-
|
|
60
|
-
|
|
88
|
+
**Terminal Example:**
|
|
89
|
+
```bash
|
|
90
|
+
$ npm install left-pad-malicious
|
|
61
91
|
|
|
62
|
-
|
|
92
|
+
⚠️ agentinel warning: left-pad-malicious is 2 days old and has 12 downloads.
|
|
93
|
+
This matches the profile of a slopsquatting or malicious package.
|
|
94
|
+
```
|
|
63
95
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
asen
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 🔒 3. The Git Pre-Commit Hook
|
|
99
|
+
|
|
100
|
+
As a final safety net, `asen init` installs a Git pre-commit hook.
|
|
101
|
+
Before you can commit a change to `package-lock.json`, Agentinel scans the staged lockfile. If a poisoned dependency slipped in somehow, the commit is flagged, ensuring malware never reaches your `main` branch.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## ⚖️ Competitors vs. Us
|
|
106
|
+
|
|
107
|
+
How do we stack up against traditional commercial security scanners?
|
|
108
|
+
|
|
109
|
+
| Feature | Agentinel (Us) | Commercial Alternatives |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| **Cost Model** | **100% Free / Zero-cost** | Monthly Subscriptions |
|
|
112
|
+
| **Data Privacy** | **100% Local (No cloud)** | Sends telemetry/code to cloud |
|
|
113
|
+
| **Agent Hooking** | **Native (intercepts AI directly)** | Scans terminal post-facto |
|
|
114
|
+
| **Feedback Loop** | **Tells AI *why* it failed** | Just blocks the terminal |
|
|
115
|
+
| **Setup** | **Zero-config, drop-in** | Requires API keys & accounts |
|
|
116
|
+
| **Malware Database** | Local OSV Feed (~216k pkgs) | Proprietary Feeds |
|
|
117
|
+
| **Feed Freshness** | *Lags 1-3 days behind OSV* | Real-time / Minutes |
|
|
118
|
+
| **Detection Method** | *Version-exact + Heuristics* | Advanced Behavioral Analysis |
|
|
119
|
+
|
|
120
|
+
*Note: We currently lag slightly on feed freshness (by a few days) and advanced behavioral analysis compared to paid enterprise tools. These are areas we acknowledge and plan to explore and improve in future versions, without compromising our zero-cost, 100% local philosophy.*
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## ⚙️ Modes: warn vs strict
|
|
125
|
+
|
|
126
|
+
Agentinel supports two operating modes, controlled by the `mode` field. You can switch between them using `npx asen mode <warn|strict>`.
|
|
127
|
+
|
|
128
|
+
### warn (default)
|
|
129
|
+
Agentinel surfaces a warning in the agent output but does not block the install. The agent decides whether to proceed.
|
|
130
|
+
|
|
131
|
+
`.agentinel.json`
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"mode": "warn"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
*Best for teams migrating to Agentinel gradually or using agents in read-heavy workflows.*
|
|
138
|
+
|
|
139
|
+
### strict
|
|
140
|
+
Agentinel hard-blocks the install and returns an error payload to the agent. The install never reaches npm.
|
|
141
|
+
|
|
142
|
+
`.agentinel.json`
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"mode": "strict"
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
*Recommended for production repos, CI pipelines, and any project with autonomous agentic access.*
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 🧰 Command Reference
|
|
153
|
+
|
|
154
|
+
Here are all the commands you can run via `npx asen <command>`:
|
|
155
|
+
|
|
156
|
+
### `npx asen init [--shim]`
|
|
157
|
+
Wires up agent hooks and git hooks in the current repo.
|
|
158
|
+
```bash
|
|
159
|
+
$ npx asen init
|
|
160
|
+
wrote .agentinel.json
|
|
161
|
+
registered the Claude Code PreToolUse hook in .claude/settings.json
|
|
162
|
+
installed the git pre-commit hook in .git/hooks
|
|
163
|
+
|
|
164
|
+
agentinel is set up. New npm packages will be checked before they land.
|
|
165
|
+
Default mode is warn. Set "mode": "strict" in .agentinel.json to block instead.
|
|
71
166
|
```
|
|
72
167
|
|
|
73
|
-
|
|
168
|
+
When used with `--shim`, it wires up hooks AND installs the global PATH shim for human terminal protection.
|
|
169
|
+
```bash
|
|
170
|
+
$ npx asen init --shim
|
|
171
|
+
wrote .agentinel.json
|
|
172
|
+
registered the Claude Code PreToolUse hook in .claude/settings.json
|
|
173
|
+
installed the git pre-commit hook in .git/hooks
|
|
174
|
+
wrote shims for npm, npx, pnpm, yarn, bun in /Users/user/.agentinel/bin
|
|
175
|
+
added the shims to PATH in /Users/user/.zshrc
|
|
176
|
+
Mode is warn, so a risky package typed at the terminal will be reported, not blocked.
|
|
177
|
+
Open a new terminal, or run \`asen unshim\` to undo this.
|
|
178
|
+
|
|
179
|
+
agentinel is set up. New npm packages will be checked before they land.
|
|
180
|
+
Default mode is warn. Set "mode": "strict" in .agentinel.json to block instead.
|
|
181
|
+
```
|
|
74
182
|
|
|
75
|
-
|
|
76
|
-
|
|
183
|
+
### `npx asen check [pkg...]`
|
|
184
|
+
Scans the currently staged dependencies in your lockfile. Exits non-zero if flagged (great for CI/CD pipelines).
|
|
185
|
+
```bash
|
|
186
|
+
$ npx asen check
|
|
187
|
+
checked 142 package(s), nothing suspicious
|
|
188
|
+
```
|
|
77
189
|
|
|
78
|
-
|
|
190
|
+
Scans a specific package instantly without installing it.
|
|
191
|
+
```bash
|
|
192
|
+
$ npx asen check react-router-v7-fake
|
|
193
|
+
⚠️ agentinel warning: react-router-v7-fake is 1 day old and has 4 downloads.
|
|
194
|
+
This matches the profile of a slopsquatting or malicious package.
|
|
195
|
+
```
|
|
79
196
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
197
|
+
### `npx asen allow <pkg> --reason "..."`
|
|
198
|
+
Adds a package to the allowlist in `.agentinel.json` with a required reason. This provides an audited trail for your team.
|
|
199
|
+
```bash
|
|
200
|
+
$ npx asen allow my-internal-pkg --reason "Internal company package not on public npm"
|
|
201
|
+
allowlisted my-internal-pkg in .agentinel.json
|
|
202
|
+
```
|
|
84
203
|
|
|
85
|
-
|
|
204
|
+
### `npx asen mode <warn|strict>`
|
|
205
|
+
Switches Agentinel's operating mode in the `.agentinel.json` file.
|
|
206
|
+
```bash
|
|
207
|
+
$ npx asen mode strict
|
|
208
|
+
set mode to strict in .agentinel.json
|
|
209
|
+
```
|
|
86
210
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
211
|
+
### `npx asen unshim`
|
|
212
|
+
Removes the global PATH shim.
|
|
213
|
+
```bash
|
|
214
|
+
$ npx asen unshim
|
|
215
|
+
removed /Users/user/.agentinel/bin
|
|
216
|
+
removed the PATH line from /Users/user/.zshrc
|
|
217
|
+
```
|
|
91
218
|
|
|
92
|
-
|
|
219
|
+
---
|
|
93
220
|
|
|
94
|
-
|
|
95
|
-
CVE scanner, that is what `npm audit`, Snyk, and Dependabot are for. This finds malicious packages,
|
|
96
|
-
not vulnerable-but-legitimate ones.
|
|
221
|
+
## 🤝 Contributing & Maintainers
|
|
97
222
|
|
|
98
|
-
|
|
223
|
+
We welcome contributions!
|
|
224
|
+
- Please read our [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, the zero-cost architecture rules, and the process for submitting pull requests.
|
|
99
225
|
|
|
100
|
-
|
|
226
|
+
**Maintainer:** [Aman Janwani](https://github.com/aman-janwani)
|
|
101
227
|
|
|
102
|
-
## License
|
|
228
|
+
## 📄 License
|
|
103
229
|
|
|
104
|
-
MIT
|
|
230
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/dist/asen.js
CHANGED
|
@@ -102,7 +102,21 @@ import { join } from "path";
|
|
|
102
102
|
// src/config/schema.ts
|
|
103
103
|
var CONFIG_FILENAME = ".agentinel.json";
|
|
104
104
|
function defaultConfig() {
|
|
105
|
-
return {
|
|
105
|
+
return {
|
|
106
|
+
mode: "warn",
|
|
107
|
+
allow: [
|
|
108
|
+
{
|
|
109
|
+
name: "asen",
|
|
110
|
+
reason: "Agentinel CLI tool",
|
|
111
|
+
date: (/* @__PURE__ */ new Date()).toISOString().substring(0, 10)
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "agentinel",
|
|
115
|
+
reason: "Agentinel package",
|
|
116
|
+
date: (/* @__PURE__ */ new Date()).toISOString().substring(0, 10)
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
};
|
|
106
120
|
}
|
|
107
121
|
function parseConfig(raw, warn2 = () => {
|
|
108
122
|
}) {
|
|
@@ -1464,6 +1478,24 @@ function asRecord2(value) {
|
|
|
1464
1478
|
return typeof value === "object" && value !== null ? value : null;
|
|
1465
1479
|
}
|
|
1466
1480
|
|
|
1481
|
+
// src/commands/mode.ts
|
|
1482
|
+
function runMode(targetMode) {
|
|
1483
|
+
if (targetMode !== "warn" && targetMode !== "strict") {
|
|
1484
|
+
console.error("usage: asen mode <warn|strict>");
|
|
1485
|
+
return 1;
|
|
1486
|
+
}
|
|
1487
|
+
const repoRoot = repoRootOrCwd();
|
|
1488
|
+
const config = loadConfig(repoRoot);
|
|
1489
|
+
if (config.mode === targetMode) {
|
|
1490
|
+
console.log(`mode is already ${targetMode}`);
|
|
1491
|
+
return 0;
|
|
1492
|
+
}
|
|
1493
|
+
config.mode = targetMode;
|
|
1494
|
+
saveConfig(repoRoot, config);
|
|
1495
|
+
console.log(`set mode to ${targetMode} in .agentinel.json`);
|
|
1496
|
+
return 0;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1467
1499
|
// src/hooks/claude-code.ts
|
|
1468
1500
|
import { existsSync as existsSync6 } from "fs";
|
|
1469
1501
|
import { join as join6 } from "path";
|
|
@@ -1769,6 +1801,7 @@ var USAGE = `asen, a guard for AI coding agent workflows
|
|
|
1769
1801
|
asen init [--shim] set up the hooks and config in this repo
|
|
1770
1802
|
asen check [pkg...] check staged dependencies, or specific packages
|
|
1771
1803
|
asen allow <pkg> --reason "..." allowlist a flagged package, with a logged reason
|
|
1804
|
+
asen mode <warn|strict> switch Agentinel's operating mode
|
|
1772
1805
|
asen unshim remove the PATH shims that --shim installed
|
|
1773
1806
|
`;
|
|
1774
1807
|
async function main(argv2) {
|
|
@@ -1780,6 +1813,8 @@ async function main(argv2) {
|
|
|
1780
1813
|
return runCheck(positionals(rest));
|
|
1781
1814
|
case "allow":
|
|
1782
1815
|
return runAllow(positionals(rest)[0], readFlag(rest, "--reason"));
|
|
1816
|
+
case "mode":
|
|
1817
|
+
return runMode(positionals(rest)[0]);
|
|
1783
1818
|
case "unshim":
|
|
1784
1819
|
return removeShim();
|
|
1785
1820
|
// Not documented in the usage text on purpose. These are what the installed hooks call.
|