@elmoxbt/agentskillguard 0.1.0 → 0.1.1

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 CHANGED
@@ -1,180 +1,65 @@
1
1
  # AgentSkillGuard
2
2
 
3
- **A static security scanner for AI agent tools before they get anywhere near a Solana wallet.**
3
+ A static security scanner for AI agent tools (MCP servers, plugins, skills) before they're granted access to a Solana wallet.
4
4
 
5
- Agents increasingly install tools (MCP servers, plugins, "skills") from third parties. Every wallet-security effort so far has assumed the *agent* is the thing to secure. AgentSkillGuard's thesis: **the tool supply chain is the attack surface.** A perfectly secure agent handing a perfectly signed transaction to a malicious swap-tool is still a drained wallet.
6
-
7
- Think `npm audit` + ClamAV, scoped to the specific things an agent tool can do to a Solana wallet.
8
-
9
- ```
10
- skillguard scan ./my-agent-tool --policy policies/example-swap-agent.yaml
11
- ```
5
+ Agents increasingly install third-party tools. AgentSkillGuard's thesis: the tool supply chain is part of the attack surface, not just the wallet itself. It scans a tool's source for dangerous capabilities, checks them against a YAML permission manifest, and returns a clear **ALLOW / WARN / BLOCK** verdict.
12
6
 
13
7
  ```
14
- AGENTSKILLGUARD
15
- target: /home/user/my-agent-tool
16
- files scanned: 3
17
-
18
- Capabilities detected:
19
- [x] CRITICAL wallet.private_key_access — Tool references private key / secret / mnemonic material directly.
20
- index.js:12 const secretKey = process.env.WALLET_PRIVATE_KEY;
21
- [x] CRITICAL system.shell_exec — Tool can execute OS shell commands via child_process.
22
- index.js:34 exec('curl -s ' + relayHost + '/beacon');
23
- [x] CRITICAL code.dynamic_load — Tool loads or executes code dynamically at runtime.
24
- index.js:30 eval(Buffer.from(patch, 'base64').toString());
25
- ...
26
-
27
- Policy violations:
28
- [!] CRITICAL wallet.private_key_access is never permitted, regardless of policy
29
- [!] CRITICAL system.shell_exec is never permitted, regardless of policy
30
- [!] CRITICAL code.dynamic_load is never permitted, regardless of policy
31
-
32
- Recommended action: BLOCK
33
- 3 critical violation(s): wallet.private_key_access, system.shell_exec, code.dynamic_load.
8
+ npx @elmoxbt/agentskillguard scan ./my-agent-tool --policy policies/example-swap-agent.yaml
34
9
  ```
35
10
 
36
- ---
11
+ - **Repo:** https://github.com/elmoxbt/agentskillguard
12
+ - **npm:** https://www.npmjs.com/package/@elmoxbt/agentskillguard
37
13
 
38
14
  ## How it works
39
15
 
40
- ```
41
- ┌────────────────────┐
42
- tool code → │ static analyzer │ → findings (capability + severity + line)
43
- │ (rule engine) │
44
- └─────────┬──────────┘
45
- │
46
- ┌──────────▼──────────┐
47
- policy.yml → │ policy enforcer │ → violations (findings checked against
48
- │ (capability manifest│ the manifest + a hard floor of
49
- │ + hard floor) │ never-allowed capabilities)
50
- └─────────┬──────────┘
51
- │
52
- ┌──────────▼──────────┐
53
- │ verdict engine │ → ALLOW / WARN / BLOCK
54
- └──────────────────────┘
55
- ```
56
-
57
- 1. **Static analyzer** (`src/scanner/staticAnalyzer.ts`) walks every `.js`/`.ts` file in the target and runs a rule set (`src/rules/rules.ts`) against it line-by-line, tagging matches with a **capability** (e.g. `wallet.signing`, `system.shell_exec`) and severity.
58
- 2. **Policy enforcer** (`src/policy/enforcer.ts`) loads a YAML **capability manifest** and checks detected capabilities against it. A small set of capabilities (private-key access, shell exec, dynamic code loading, obfuscated execution, unlimited approvals) are an **always-blocked floor** — no policy can grant them.
59
- 3. **Verdict engine** (`src/report/verdict.ts`) turns violations into a single recommendation: `BLOCK` (critical violation), `WARN` (needs manual review), or `ALLOW`.
60
- 4. Every scan is optionally persisted to a local SQLite database (`~/.agentskillguard/scans.db`) so you can build a `skillguard history` audit trail across every tool you've ever vetted.
61
-
62
- ### Detected capabilities
63
-
64
- | Capability | Checks for | Severity |
65
- |---|---|---|
66
- | `wallet.signing` | Can the tool sign transactions/messages? | CRITICAL |
67
- | `wallet.private_key_access` | Does it touch raw private keys / mnemonics? | CRITICAL |
68
- | `network.http` | Does it make outbound HTTP requests? | MEDIUM |
69
- | `network.dynamic_url` | Are request URLs built dynamically (unverifiable)? | HIGH |
70
- | `solana.tx_modification` | Does it mutate transaction instructions/destinations? | HIGH |
71
- | `system.shell_exec` | Can it run OS shell commands? | CRITICAL |
72
- | `code.dynamic_load` | Does it `eval`/`new Function`/dynamic `require`? | CRITICAL |
73
- | `solana.unlimited_approval` | Does it request unlimited token approvals? | HIGH |
74
- | `system.env_read` | Does it read `process.env`? | MEDIUM |
75
- | `code.obfuscation` | Does it decode+execute base64/hex payloads? | CRITICAL |
76
- | `system.filesystem_write` | Does it write/delete files? | MEDIUM |
16
+ 1. **Static analyzer** — walks the target's source files and flags capabilities like wallet signing, private key access, shell execution, dynamic code loading, unlimited token approvals, and arbitrary network calls.
17
+ 2. **Policy enforcer** — checks detected capabilities against a YAML capability manifest. A fixed set of capabilities (private-key access, shell exec, `eval`/dynamic code, obfuscated execution, unlimited approvals) are never permitted, regardless of policy.
18
+ 3. **Verdict engine** — combines the results into a single recommendation, with CI-friendly exit codes (`0` ALLOW, `1` WARN, `2` BLOCK).
19
+ 4. Scans are optionally logged to a local history so you can audit everything you've vetted over time.
77
20
 
78
- This maps directly to the "tool permissions" checklist a human reviewer would ask about — the scanner just does it automatically, on every install.
79
-
80
- ## The capability manifest
21
+ ## Capability manifest
81
22
 
82
23
  ```yaml
83
24
  name: swap-agent
84
- description: "Allows a swap tool to route trades through Jupiter and call its price API."
85
-
86
25
  permissions:
87
26
  solana:
88
- programs:
89
- - Jupiter
27
+ programs: [Jupiter]
90
28
  max_sol: 0.5
91
- tokens:
92
- - USDC
93
-
29
+ tokens: [USDC]
94
30
  network:
95
- domains:
96
- - api.jup.ag
97
- - quote-api.jup.ag
98
-
31
+ domains: [api.jup.ag]
99
32
  wallet:
100
33
  signing: true
101
34
  max_transactions_per_hour: 10
102
35
  ```
103
36
 
104
- The scanner statically enforces `wallet.signing`, `network.domains`, and `solana.programs`. `max_sol` and `max_transactions_per_hour` describe the intended **runtime** ceiling — static analysis can prove a tool is *capable* of signing, but it can't prove what amount it will sign at runtime. See Roadmap below.
105
-
106
37
  ## Install & run
107
38
 
108
39
  ```bash
109
40
  npm install
110
41
  npm run build
111
42
 
112
- # scan the bundled "malicious" fixture — should BLOCK
113
- npm run scan:demo:malicious
114
-
115
- # scan the bundled "safe" fixture — should ALLOW
116
- npm run scan:demo:safe
43
+ npm run scan:demo:malicious # bundled fixture — should BLOCK
44
+ npm run scan:demo:safe # bundled fixture — should ALLOW
117
45
 
118
- # scan any tool on your machine
119
46
  node dist/cli.js scan ./path/to/tool --policy policies/example-swap-agent.yaml
120
-
121
- # scan without a policy — only the hard-blocked floor applies
122
- node dist/cli.js scan ./path/to/tool
123
-
124
- # machine-readable output (for CI / pre-install hooks)
125
47
  node dist/cli.js scan ./path/to/tool --json
126
-
127
- # generate a starter deny-by-default policy
128
- node dist/cli.js init-policy -o my-tool.policy.yaml
129
-
130
- # see everything you've scanned so far
131
48
  node dist/cli.js history
132
49
  ```
133
50
 
134
- Exit codes are CI-friendly: `0` = ALLOW, `1` = WARN, `2` = BLOCK — so you can wire `skillguard scan` into a pre-install hook and have it actually stop an install.
135
-
136
- Run the smoke tests directly with `npm test` (no test framework, just assertions — see `test/scanner.test.ts`).
137
-
138
- ## Project structure
51
+ Or, once published, use it directly without cloning:
139
52
 
140
- ```
141
- agentskillguard/
142
- ├── src/
143
- │ ├── cli.ts # commander-based CLI entry point
144
- │ ├── types.ts # shared types (Finding, Violation, ScanResult...)
145
- │ ├── rules/rules.ts # the rule set — add new detection rules here
146
- │ ├── scanner/
147
- │ │ ├── index.ts # orchestrates a scan end-to-end
148
- │ │ ├── staticAnalyzer.ts # line-based rule matching + URL extraction
149
- │ │ └── mcpMetadata.ts # reads package.json / mcp.json for tool identity
150
- │ ├── policy/
151
- │ │ ├── schema.ts # zod schema for the YAML capability manifest
152
- │ │ ├── loader.ts # loads + validates a policy file
153
- │ │ └── enforcer.ts # findings + policy -> violations
154
- │ ├── report/
155
- │ │ ├── verdict.ts # violations -> ALLOW / WARN / BLOCK
156
- │ │ └── formatter.ts # colored CLI report
157
- │ ├── db/store.ts # SQLite scan history (better-sqlite3)
158
- │ └── utils/fileWalker.ts # recursive source-file discovery
159
- ├── policies/example-swap-agent.yaml
160
- ├── examples/
161
- │ ├── malicious-tool/ # fixture that trips nearly every rule (inert — do not run)
162
- │ └── safe-tool/ # fixture that scans clean
163
- └── test/scanner.test.ts # smoke test asserting both fixtures verdict correctly
53
+ ```bash
54
+ npx @elmoxbt/agentskillguard scan ./path/to/tool
164
55
  ```
165
56
 
166
- ## Scope & honesty about limitations
57
+ ## Scope
167
58
 
168
- This is a portfolio-grade MVP, not a production security product. Specifically:
59
+ This is an MVP: detection is regex/line-based rather than a full AST, so it can be evaded by sufficiently obfuscated code, and runtime limits (`max_sol`, `max_transactions_per_hour`) are captured in the manifest but require a runtime enforcement layer to actually enforce — static analysis can only confirm a tool is *capable* of exceeding them.
169
60
 
170
- - **Detection is regex/line-based, not a real AST.** It's fast and dependency-light, but it can be evaded by anyone who tries (multi-line obfuscation, string-splitting `"ev" + "al"`, etc). The natural upgrade path is a Tree-sitter-based AST pass (`tree-sitter-javascript`/`tree-sitter-typescript`) doing call-graph and data-flow analysis instead of pattern matching — the rule *interface* (`Rule.pattern` → `Rule.check(ast)`) is designed so that swap is additive, not a rewrite.
171
- - **Static analysis can't enforce runtime limits.** `max_sol` and `max_transactions_per_hour` in the manifest are real intents but need a runtime wrapper (a proxy the agent calls through, which meters actual transaction amounts/frequency against the manifest) to actually enforce — the scanner can only flag that a tool *is capable* of exceeding them if it doesn't hard-code such limits itself.
172
- - **No sandboxed dynamic analysis yet.** A tool that decrypts its payload only at runtime (fetched from a CDN post-install, key derived from an unpredictable seed) won't be caught by source scanning at all. That needs an actual sandboxed execution pass — out of scope for the MVP.
61
+ **Roadmap:** Tree-sitter-based AST analysis, a runtime enforcement proxy for `web3.js` calls, and a hash database of previously scanned malicious tools.
173
62
 
174
- ## Roadmap
63
+ ## License
175
64
 
176
- - [ ] Tree-sitter AST engine (real call-graph analysis instead of regex)
177
- - [ ] Runtime enforcement proxy: wraps `@solana/web3.js` calls so `max_sol` / `max_transactions_per_hour` are enforced live, not just requested
178
- - [ ] MCP-native scanning: intercept tool registration at the protocol level and scan before an agent is ever allowed to call it
179
- - [ ] Signature/hash database of previously-scanned malicious tools (the "ClamAV" half of the pitch)
180
- - [ ] `skillguard watch` — scan on every `npm install` in an agent's tool directory
65
+ MIT
@@ -56,7 +56,7 @@ exports.RULES = [
56
56
  capability: 'system.shell_exec',
57
57
  severity: 'CRITICAL',
58
58
  description: 'Tool can execute OS shell commands via child_process.',
59
- pattern: /require\(\s*['"]child_process['"]\s*\)|\b(execSync|spawnSync|exec|spawn|fork)\s*\(/,
59
+ pattern: /require\(\s*['"]child_process['"]\s*\)|\b(?:child_process|cp)\.(?:exec|execSync|spawn|spawnSync|fork)\s*\(|(?<!\.)\b(?:execSync|spawnSync|exec|spawn|fork)\s*\(/,
60
60
  recommendation: 'No legitimate Solana/agent tool needs shell access. Treat as an automatic block.',
61
61
  },
62
62
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elmoxbt/agentskillguard",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "AgentSkillGuard — a static security scanner for AI agent tools (MCP tools, plugins, skills) before they are allowed to touch a Solana wallet.",
5
5
  "license": "MIT",
6
6
  "publishConfig": { "access": "public" },
@@ -64,7 +64,7 @@ export const RULES: Rule[] = [
64
64
  capability: 'system.shell_exec',
65
65
  severity: 'CRITICAL',
66
66
  description: 'Tool can execute OS shell commands via child_process.',
67
- pattern: /require\(\s*['"]child_process['"]\s*\)|\b(execSync|spawnSync|exec|spawn|fork)\s*\(/,
67
+ pattern: /require\(\s*['"]child_process['"]\s*\)|\b(?:child_process|cp)\.(?:exec|execSync|spawn|spawnSync|fork)\s*\(|(?<!\.)\b(?:execSync|spawnSync|exec|spawn|fork)\s*\(/,
68
68
  recommendation: 'No legitimate Solana/agent tool needs shell access. Treat as an automatic block.',
69
69
  },
70
70
  {