guard-scanner 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/LICENSE +21 -0
- package/README.md +586 -0
- package/SECURITY.md +45 -0
- package/SKILL.md +165 -0
- package/docs/THREAT_TAXONOMY.md +273 -0
- package/hooks/guard-scanner/HOOK.md +77 -0
- package/hooks/guard-scanner/handler.ts +150 -0
- package/package.json +42 -0
- package/src/cli.js +149 -0
- package/src/ioc-db.js +54 -0
- package/src/patterns.js +182 -0
- package/src/scanner.js +808 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Guava & Dee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">🛡️ guard-scanner</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Static security scanner for AI agent skills</strong><br>
|
|
5
|
+
Detect prompt injection, credential theft, exfiltration, identity hijacking, and 14 more threat categories.
|
|
6
|
+
</p>
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
|
|
9
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="Node.js 18+">
|
|
10
|
+
<img src="https://img.shields.io/badge/dependencies-0-success" alt="Zero Dependencies">
|
|
11
|
+
<img src="https://img.shields.io/badge/tests-45%2F45-brightgreen" alt="Tests Passing">
|
|
12
|
+
<img src="https://img.shields.io/badge/patterns-170%2B-orange" alt="170+ Patterns">
|
|
13
|
+
</p>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Why This Exists
|
|
19
|
+
|
|
20
|
+
In February 2026, [Snyk's ToxicSkills audit](https://snyk.io) of 3,984 AI agent skills revealed:
|
|
21
|
+
- **36.8%** contained at least one security flaw
|
|
22
|
+
- **13.4%** had critical-level issues
|
|
23
|
+
- **76 active malicious payloads** for credential theft, backdoors, and data exfiltration
|
|
24
|
+
|
|
25
|
+
The AI agent skill ecosystem has the same supply-chain security problem that npm and PyPI had in their early days — except agent skills inherit **full shell access, file system permissions, and environment variables** of the host agent.
|
|
26
|
+
|
|
27
|
+
**guard-scanner** was born from a real 3-day identity hijack incident where an AI agent's personality files were silently overwritten by a malicious skill. There was no scanner that could detect it. Now there is. 🍈
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
| Feature | Description |
|
|
34
|
+
|---|---|
|
|
35
|
+
| **17 Threat Categories** | Snyk ToxicSkills taxonomy + OWASP MCP Top 10 + Identity Hijacking |
|
|
36
|
+
| **170+ Detection Patterns** | Regex-based static analysis covering code, docs, and data files |
|
|
37
|
+
| **IoC Database** | Known malicious IPs, domains, URLs, usernames, and typosquat names |
|
|
38
|
+
| **Data Flow Analysis** | Lightweight JS analysis: secret reads → network calls → exec chains |
|
|
39
|
+
| **Cross-File Analysis** | Phantom references, base64 fragment assembly, multi-file exfil detection |
|
|
40
|
+
| **Shannon Entropy** | High-entropy string detection for leaked secrets and API keys |
|
|
41
|
+
| **Dependency Chain Scan** | Risky packages, lifecycle scripts, wildcard versions, git dependencies |
|
|
42
|
+
| **4 Output Formats** | Terminal (with colors), JSON, [SARIF 2.1.0](https://sarifweb.azurewebsites.net), HTML dashboard |
|
|
43
|
+
| **Plugin API** | Extend with custom detection rules via JS modules |
|
|
44
|
+
| **Ignore Files** | Whitelist trusted skills and patterns via `.guard-scanner-ignore` |
|
|
45
|
+
| **Zero Dependencies** | Pure Node.js stdlib. Nothing to install, nothing to audit. |
|
|
46
|
+
| **CI/CD Ready** | `--fail-on-findings` exit code + SARIF for GitHub Code Scanning |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Scan a skill directory (each subdirectory = one skill)
|
|
54
|
+
npx guard-scanner ./skills/
|
|
55
|
+
|
|
56
|
+
# Verbose output with category breakdown
|
|
57
|
+
npx guard-scanner ./skills/ --verbose
|
|
58
|
+
|
|
59
|
+
# Strict mode (lower thresholds)
|
|
60
|
+
npx guard-scanner ./skills/ --strict
|
|
61
|
+
|
|
62
|
+
# Full audit: verbose + deps + all output formats
|
|
63
|
+
npx guard-scanner ./skills/ --verbose --check-deps --json --sarif --html
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Installation (Optional)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Global install
|
|
70
|
+
npm install -g guard-scanner
|
|
71
|
+
|
|
72
|
+
# Or use directly via npx (no install needed)
|
|
73
|
+
npx guard-scanner ./skills/
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### As an OpenClaw Skill
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
openclaw skill install guard-scanner
|
|
80
|
+
guard-scanner ~/.openclaw/workspace/skills/ --self-exclude --verbose
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Threat Categories
|
|
86
|
+
|
|
87
|
+
guard-scanner covers **17 threat categories** derived from three taxonomies:
|
|
88
|
+
|
|
89
|
+
| # | Category | Based On | Severity | What It Detects |
|
|
90
|
+
|---|----------|----------|----------|----------------|
|
|
91
|
+
| 1 | **Prompt Injection** | Snyk ToxicSkills | CRITICAL | Invisible Unicode (ZWSP, BiDi), homoglyphs (Cyrillic/Greek/Math), role override, system tag injection, base64 execution instructions |
|
|
92
|
+
| 2 | **Malicious Code** | Snyk ToxicSkills | CRITICAL | `eval()`, `Function()` constructor, `child_process`, reverse shells, raw sockets, sandbox detection |
|
|
93
|
+
| 3 | **Suspicious Downloads** | Snyk ToxicSkills | CRITICAL | `curl\|bash` pipes, executable downloads, password-protected archives, prerequisite fraud |
|
|
94
|
+
| 4 | **Credential Handling** | Snyk ToxicSkills | HIGH | `.env` file reads, SSH key access, wallet seed phrases, credential echo/print, `sudo` in docs |
|
|
95
|
+
| 5 | **Secret Detection** | Snyk ToxicSkills | CRITICAL | AWS Access Keys (`AKIA...`), GitHub tokens (`ghp_/ghs_`), embedded private keys, high-entropy strings |
|
|
96
|
+
| 6 | **Exfiltration** | Snyk ToxicSkills | CRITICAL | webhook.site/requestbin.com/hookbin, POST with secrets, `curl --data`, DNS tunneling |
|
|
97
|
+
| 7 | **Unverifiable Deps** | Snyk ToxicSkills | HIGH | Remote dynamic imports, non-CDN script loading |
|
|
98
|
+
| 8 | **Financial Access** | Snyk ToxicSkills | HIGH | Crypto private keys, `sendTransaction`, Stripe/PayPal/Plaid API calls |
|
|
99
|
+
| 9 | **Obfuscation** | Snyk ToxicSkills | HIGH | Hex strings, `atob→eval` chains, `String.fromCharCode`, array join, `base64 -d\|bash` |
|
|
100
|
+
| 10 | **Prerequisites Fraud** | Snyk ToxicSkills | CRITICAL | Download-in-prerequisites, terminal paste instructions |
|
|
101
|
+
| 11 | **Leaky Skills** | Snyk ToxicSkills | CRITICAL | "Save API key in memory", "Share token with user", verbatim secrets in curl, PII collection, session log export |
|
|
102
|
+
| 12 | **Memory Poisoning** | Palo Alto IBC | CRITICAL | SOUL.md/IDENTITY.md modification, agent memory writes, behavioral rule override, persistence instructions |
|
|
103
|
+
| 13 | **Prompt Worm** | Palo Alto IBC | CRITICAL | Self-replication instructions, agent-to-agent propagation, hidden instruction embedding, CSS-hidden content |
|
|
104
|
+
| 14 | **Persistence** | MITRE ATT&CK | HIGH | Scheduled tasks/cron, startup execution, LaunchAgents/systemd |
|
|
105
|
+
| 15 | **CVE Patterns** | CVE Database | CRITICAL | CVE-2026-25253 `gatewayUrl` injection, sandbox disabling, xattr Gatekeeper bypass, WebSocket origin bypass |
|
|
106
|
+
| 16 | **MCP Security** | OWASP MCP Top 10 | CRITICAL | Tool poisoning (`<IMPORTANT>`), schema poisoning (malicious defaults), token leaks, shadow server registration, SSRF metadata endpoints |
|
|
107
|
+
| 17 | **Identity Hijacking** | Original Research | CRITICAL | SOUL.md/IDENTITY.md overwrite/redirect/sed/echo/Python/Node.js writes, persona swap instructions, memory wipe, name override |
|
|
108
|
+
|
|
109
|
+
> **Category 17 (Identity Hijacking)** is unique to guard-scanner. It was developed from direct experience with a real attack where an agent's identity files were silently replaced. Detection patterns are open-source; verification logic remains private.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Output Formats
|
|
114
|
+
|
|
115
|
+
### Terminal (Default)
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
🛡️ guard-scanner v1.0.0
|
|
119
|
+
══════════════════════════════════════════════════════
|
|
120
|
+
📂 Scanning: ./skills/
|
|
121
|
+
📦 Skills found: 22
|
|
122
|
+
|
|
123
|
+
🟢 my-safe-skill — CLEAN (risk: 0)
|
|
124
|
+
🟢 another-skill — LOW RISK (risk: 5)
|
|
125
|
+
🟡 suspicious-one — SUSPICIOUS (risk: 45)
|
|
126
|
+
📁 credential-handling
|
|
127
|
+
🔴 [HIGH] Reading .env file — scripts/main.js:12
|
|
128
|
+
🔴 [HIGH] SSH key access — scripts/deploy.sh:8
|
|
129
|
+
🔴 evil-skill — MALICIOUS (risk: 100)
|
|
130
|
+
📁 malicious-code
|
|
131
|
+
💀 [CRITICAL] Reverse shell — scripts/backdoor.js:3
|
|
132
|
+
📁 exfiltration
|
|
133
|
+
💀 [CRITICAL] Known exfiltration endpoint — scripts/exfil.js:15
|
|
134
|
+
|
|
135
|
+
══════════════════════════════════════════════════════
|
|
136
|
+
📊 Scan Summary
|
|
137
|
+
Scanned: 22
|
|
138
|
+
🟢 Clean: 18
|
|
139
|
+
🟢 Low Risk: 2
|
|
140
|
+
🟡 Suspicious: 1
|
|
141
|
+
🔴 Malicious: 1
|
|
142
|
+
Safety Rate: 91%
|
|
143
|
+
══════════════════════════════════════════════════════
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### JSON (`--json`)
|
|
147
|
+
|
|
148
|
+
Writes `guard-scanner-report.json` with full findings, stats, recommendations, and IoC version.
|
|
149
|
+
|
|
150
|
+
### SARIF (`--sarif`)
|
|
151
|
+
|
|
152
|
+
Writes `guard-scanner.sarif` — [SARIF 2.1.0](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning) compatible. Upload to GitHub Code Scanning:
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
# .github/workflows/scan.yml
|
|
156
|
+
- name: Scan agent skills
|
|
157
|
+
run: npx guard-scanner ./skills/ --sarif --fail-on-findings
|
|
158
|
+
|
|
159
|
+
- name: Upload SARIF
|
|
160
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
161
|
+
with:
|
|
162
|
+
sarif_file: skills/guard-scanner.sarif
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### HTML (`--html`)
|
|
166
|
+
|
|
167
|
+
Generates a dark-mode dashboard with stats grid and per-skill finding tables. Open in any browser.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Risk Scoring
|
|
172
|
+
|
|
173
|
+
Each skill receives a **risk score (0–100)** based on:
|
|
174
|
+
|
|
175
|
+
### Base Score
|
|
176
|
+
| Severity | Weight |
|
|
177
|
+
|----------|--------|
|
|
178
|
+
| CRITICAL | 40 points |
|
|
179
|
+
| HIGH | 15 points |
|
|
180
|
+
| MEDIUM | 5 points |
|
|
181
|
+
| LOW | 2 points |
|
|
182
|
+
|
|
183
|
+
### Amplification Rules
|
|
184
|
+
|
|
185
|
+
Certain combinations multiply the base score:
|
|
186
|
+
|
|
187
|
+
| Combination | Multiplier | Rationale |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| Credential handling + Exfiltration | **×2** | Classic steal-and-send pattern |
|
|
190
|
+
| Credential handling + Command exec | **×1.5** | Credential-powered RCE |
|
|
191
|
+
| Obfuscation + Malicious code | **×2** | Hiding malicious intent |
|
|
192
|
+
| Lifecycle script exec | **×2** | npm supply chain attack |
|
|
193
|
+
| BiDi characters + other findings | **×1.5** | Text direction attack as vector |
|
|
194
|
+
| Leaky skills + Exfiltration | **×2** | Secret leak through LLM context |
|
|
195
|
+
| Memory poisoning | **×1.5** | Persistent compromise |
|
|
196
|
+
| Prompt worm | **×2** | Self-replicating threat |
|
|
197
|
+
| Persistence + (malicious\|credential\|memory) | **×1.5** | Survives session restart |
|
|
198
|
+
| Identity hijacking | **×2** | Core identity compromise |
|
|
199
|
+
| Identity hijacking + Persistence | **min 90** | Full agent takeover |
|
|
200
|
+
| Known IoC (IP/URL/typosquat) | **= 100** | Confirmed malicious |
|
|
201
|
+
|
|
202
|
+
### Verdict Thresholds
|
|
203
|
+
|
|
204
|
+
| Mode | Suspicious | Malicious |
|
|
205
|
+
|------|-----------|-----------|
|
|
206
|
+
| Normal | ≥ 30 | ≥ 80 |
|
|
207
|
+
| Strict (`--strict`) | ≥ 20 | ≥ 60 |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Data Flow Analysis
|
|
212
|
+
|
|
213
|
+
guard-scanner performs lightweight static analysis on JavaScript/TypeScript files to detect **multi-step attack patterns** that individual regex rules miss:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
Secret Read (L36) ─── process.env.API_KEY ───→ Network Call (L56) ─── fetch() ───→ 🚨 CRITICAL
|
|
217
|
+
AST_CRED_TO_NET
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Detected Chains
|
|
221
|
+
|
|
222
|
+
| Pattern ID | Chain | Severity |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| `AST_CRED_TO_NET` | Secret read → Network call | CRITICAL |
|
|
225
|
+
| `AST_CRED_TO_EXEC` | Secret read → Command exec | HIGH |
|
|
226
|
+
| `AST_SUSPICIOUS_IMPORTS` | `child_process` + network module | HIGH |
|
|
227
|
+
| `AST_EXFIL_TRIFECTA` | `fs` + `child_process` + `http/https` | CRITICAL |
|
|
228
|
+
| `AST_SECRET_IN_URL` | Secret interpolated into URL | CRITICAL |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## IoC Database
|
|
233
|
+
|
|
234
|
+
Built-in Indicators of Compromise from real-world incidents:
|
|
235
|
+
|
|
236
|
+
| Type | Examples | Source |
|
|
237
|
+
|------|----------|--------|
|
|
238
|
+
| **IPs** | `91.92.242.30` (C2) | ClawHavoc campaign |
|
|
239
|
+
| **Domains** | `webhook.site`, `requestbin.com`, `hookbin.com`, `pipedream.net` | Common exfil endpoints |
|
|
240
|
+
| **URLs** | `glot.io/snippets/hfd3x9ueu5` | ClawHavoc macOS payload |
|
|
241
|
+
| **Usernames** | `zaycv`, `Ddoy233`, `Sakaen736jih` | Known malicious actors |
|
|
242
|
+
| **Filenames** | `openclaw-agent.zip`, `openclawcli.zip` | Trojanized installers |
|
|
243
|
+
| **Typosquats** | `clawhub`, `polymarket-trader`, `auto-updater-agent` + 20 more | ClawHavoc, Polymarket, Snyk ToxicSkills |
|
|
244
|
+
|
|
245
|
+
Any match against the IoC database automatically sets risk to **100 (MALICIOUS)**.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Plugin API
|
|
250
|
+
|
|
251
|
+
Extend guard-scanner with custom detection rules:
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
// my-org-rules.js
|
|
255
|
+
module.exports = {
|
|
256
|
+
name: 'my-org-security-rules',
|
|
257
|
+
patterns: [
|
|
258
|
+
{
|
|
259
|
+
id: 'ORG_INTERNAL_API',
|
|
260
|
+
cat: 'data-leak',
|
|
261
|
+
regex: /api\.internal\.mycompany\.com/gi,
|
|
262
|
+
severity: 'CRITICAL',
|
|
263
|
+
desc: 'Internal API endpoint exposed in skill',
|
|
264
|
+
all: true // scan all file types
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
id: 'ORG_STAGING_CRED',
|
|
268
|
+
cat: 'secret-detection',
|
|
269
|
+
regex: /staging[_-](?:key|token|password)\s*[:=]\s*['"][^'"]+['"]/gi,
|
|
270
|
+
severity: 'HIGH',
|
|
271
|
+
desc: 'Staging credential hardcoded',
|
|
272
|
+
codeOnly: true // only scan code files
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
};
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
guard-scanner ./skills/ --plugin ./my-org-rules.js
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Pattern Schema
|
|
283
|
+
|
|
284
|
+
| Field | Type | Required | Description |
|
|
285
|
+
|---|---|---|---|
|
|
286
|
+
| `id` | string | ✅ | Unique pattern identifier (e.g., `ORG_001`) |
|
|
287
|
+
| `cat` | string | ✅ | Category name for grouping |
|
|
288
|
+
| `regex` | RegExp | ✅ | Detection pattern (use `g` flag) |
|
|
289
|
+
| `severity` | string | ✅ | `CRITICAL` \| `HIGH` \| `MEDIUM` \| `LOW` |
|
|
290
|
+
| `desc` | string | ✅ | Human-readable description |
|
|
291
|
+
| `all` | boolean | | Scan all file types |
|
|
292
|
+
| `codeOnly` | boolean | | Only scan code files (.js, .ts, .py, .sh, etc.) |
|
|
293
|
+
| `docOnly` | boolean | | Only scan documentation files (.md, .txt, etc.) |
|
|
294
|
+
|
|
295
|
+
### Custom Rules via JSON
|
|
296
|
+
|
|
297
|
+
Alternatively, use a JSON rules file:
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
[
|
|
301
|
+
{
|
|
302
|
+
"id": "CUSTOM_001",
|
|
303
|
+
"pattern": "dangerous_function\\(",
|
|
304
|
+
"flags": "gi",
|
|
305
|
+
"severity": "HIGH",
|
|
306
|
+
"cat": "malicious-code",
|
|
307
|
+
"desc": "Dangerous function call"
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
guard-scanner ./skills/ --rules ./custom-rules.json
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Ignore Files
|
|
319
|
+
|
|
320
|
+
Create `.guard-scanner-ignore` (or `.guava-guard-ignore`) in the scan directory:
|
|
321
|
+
|
|
322
|
+
```gitignore
|
|
323
|
+
# Ignore trusted skills
|
|
324
|
+
my-trusted-skill
|
|
325
|
+
internal-tool
|
|
326
|
+
|
|
327
|
+
# Ignore specific patterns (false positives)
|
|
328
|
+
pattern:MAL_CHILD
|
|
329
|
+
pattern:CRED_ENV_REF
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## CLI Reference
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
Usage: guard-scanner [scan-dir] [options]
|
|
338
|
+
|
|
339
|
+
Arguments:
|
|
340
|
+
scan-dir Directory to scan (default: current directory)
|
|
341
|
+
|
|
342
|
+
Options:
|
|
343
|
+
--verbose, -v Show detailed findings with categories and samples
|
|
344
|
+
--json Write JSON report to scan-dir/guard-scanner-report.json
|
|
345
|
+
--sarif Write SARIF 2.1.0 report for CI/CD integration
|
|
346
|
+
--html Write HTML dashboard report
|
|
347
|
+
--self-exclude Skip scanning the guard-scanner skill itself
|
|
348
|
+
--strict Lower detection thresholds (suspicious: 20, malicious: 60)
|
|
349
|
+
--summary-only Only print the summary table
|
|
350
|
+
--check-deps Scan package.json for dependency chain risks
|
|
351
|
+
--rules <file> Load custom rules from JSON file
|
|
352
|
+
--plugin <file> Load plugin module (repeatable)
|
|
353
|
+
--fail-on-findings Exit code 1 if any findings (for CI/CD)
|
|
354
|
+
--help, -h Show help
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Exit Codes
|
|
358
|
+
|
|
359
|
+
| Code | Meaning |
|
|
360
|
+
|------|---------|
|
|
361
|
+
| 0 | No malicious skills detected |
|
|
362
|
+
| 1 | Malicious skill(s) detected, or `--fail-on-findings` with any findings |
|
|
363
|
+
| 2 | Invalid scan directory |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Architecture
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
guard-scanner/
|
|
371
|
+
├── src/
|
|
372
|
+
│ ├── scanner.js # GuardScanner class — core scan engine
|
|
373
|
+
│ ├── patterns.js # 170+ threat detection patterns (Cat 1–17)
|
|
374
|
+
│ ├── ioc-db.js # Indicators of Compromise database
|
|
375
|
+
│ └── cli.js # CLI entry point and argument parser
|
|
376
|
+
├── test/
|
|
377
|
+
│ ├── scanner.test.js # 45 tests across 10 sections
|
|
378
|
+
│ └── fixtures/ # Malicious + clean skill samples
|
|
379
|
+
├── package.json # Zero dependencies, node --test
|
|
380
|
+
├── CHANGELOG.md
|
|
381
|
+
├── LICENSE # MIT
|
|
382
|
+
└── README.md
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### How Scanning Works
|
|
386
|
+
|
|
387
|
+
```
|
|
388
|
+
┌──────────────────┐
|
|
389
|
+
│ CLI / API │
|
|
390
|
+
└────────┬─────────┘
|
|
391
|
+
│
|
|
392
|
+
┌────────▼─────────┐
|
|
393
|
+
│ GuardScanner │
|
|
394
|
+
│ constructor() │
|
|
395
|
+
│ • Load plugins │
|
|
396
|
+
│ • Load rules │
|
|
397
|
+
│ • Set thresholds│
|
|
398
|
+
└────────┬─────────┘
|
|
399
|
+
│
|
|
400
|
+
┌────────▼─────────┐
|
|
401
|
+
│ scanDirectory() │
|
|
402
|
+
│ • Load ignore │
|
|
403
|
+
│ • Enumerate │
|
|
404
|
+
└────────┬─────────┘
|
|
405
|
+
│
|
|
406
|
+
┌──────────────┼──────────────┐
|
|
407
|
+
│ │ │
|
|
408
|
+
┌────────▼──────┐ ┌────▼────┐ ┌───────▼──────┐
|
|
409
|
+
│ Per-Skill │ │ Per- │ │ Structural │
|
|
410
|
+
│ File Scan │ │ File │ │ Checks │
|
|
411
|
+
│ │ │ IoC │ │ │
|
|
412
|
+
│ • Pattern │ │ Check │ │ • SKILL.md │
|
|
413
|
+
│ matching │ │ │ │ • Hidden │
|
|
414
|
+
│ • Secret │ │ • IPs │ │ files │
|
|
415
|
+
│ entropy │ │ • URLs │ │ • Deps │
|
|
416
|
+
│ • Data flow │ │ • Names │ │ • Cross-file │
|
|
417
|
+
│ • Custom rules│ │ │ │ │
|
|
418
|
+
└───────┬───────┘ └────┬────┘ └──────┬───────┘
|
|
419
|
+
│ │ │
|
|
420
|
+
└──────────────┼──────────────┘
|
|
421
|
+
│
|
|
422
|
+
┌────────▼─────────┐
|
|
423
|
+
│ calculateRisk() │
|
|
424
|
+
│ • Base score │
|
|
425
|
+
│ • Amplifiers │
|
|
426
|
+
│ • IoC override │
|
|
427
|
+
└────────┬─────────┘
|
|
428
|
+
│
|
|
429
|
+
┌────────▼─────────┐
|
|
430
|
+
│ Output │
|
|
431
|
+
│ • Terminal │
|
|
432
|
+
│ • JSON │
|
|
433
|
+
│ • SARIF 2.1.0 │
|
|
434
|
+
│ • HTML │
|
|
435
|
+
└──────────────────┘
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## CI/CD Integration
|
|
441
|
+
|
|
442
|
+
### GitHub Actions
|
|
443
|
+
|
|
444
|
+
```yaml
|
|
445
|
+
name: Skill Security Scan
|
|
446
|
+
on: [push, pull_request]
|
|
447
|
+
|
|
448
|
+
jobs:
|
|
449
|
+
scan:
|
|
450
|
+
runs-on: ubuntu-latest
|
|
451
|
+
steps:
|
|
452
|
+
- uses: actions/checkout@v4
|
|
453
|
+
|
|
454
|
+
- name: Run guard-scanner
|
|
455
|
+
run: npx guard-scanner ./skills/ --sarif --strict --fail-on-findings
|
|
456
|
+
|
|
457
|
+
- name: Upload SARIF results
|
|
458
|
+
if: always()
|
|
459
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
460
|
+
with:
|
|
461
|
+
sarif_file: skills/guard-scanner.sarif
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Pre-commit Hook
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
#!/bin/bash
|
|
468
|
+
# .git/hooks/pre-commit
|
|
469
|
+
npx guard-scanner ./skills/ --strict --fail-on-findings --summary-only
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Programmatic API
|
|
475
|
+
|
|
476
|
+
```javascript
|
|
477
|
+
const { GuardScanner } = require('guard-scanner');
|
|
478
|
+
|
|
479
|
+
const scanner = new GuardScanner({
|
|
480
|
+
verbose: false,
|
|
481
|
+
strict: true,
|
|
482
|
+
checkDeps: true,
|
|
483
|
+
summaryOnly: true,
|
|
484
|
+
plugins: ['./my-plugin.js']
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
scanner.scanDirectory('./skills/');
|
|
488
|
+
|
|
489
|
+
// Access results
|
|
490
|
+
console.log(scanner.stats); // { scanned, clean, low, suspicious, malicious }
|
|
491
|
+
console.log(scanner.findings); // Array of per-skill findings
|
|
492
|
+
console.log(scanner.toJSON()); // Full JSON report
|
|
493
|
+
console.log(scanner.toSARIF('.')); // SARIF 2.1.0 object
|
|
494
|
+
console.log(scanner.toHTML()); // HTML string
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Test Results
|
|
500
|
+
|
|
501
|
+
```
|
|
502
|
+
ℹ tests 45
|
|
503
|
+
ℹ suites 10
|
|
504
|
+
ℹ pass 45
|
|
505
|
+
ℹ fail 0
|
|
506
|
+
ℹ duration_ms 83ms
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
| Suite | Tests | Coverage |
|
|
510
|
+
|-------|-------|----------|
|
|
511
|
+
| Malicious Skill Detection | 16 | Cat 1,2,3,4,5,6,9,11,12,17 + IoC + DataFlow + DepChain |
|
|
512
|
+
| False Positive Test | 2 | Clean skill → zero false positives |
|
|
513
|
+
| Risk Score Calculation | 5 | Empty, single, combo amplifiers, IoC override |
|
|
514
|
+
| Verdict Determination | 5 | All verdicts + strict mode |
|
|
515
|
+
| Output Formats | 4 | JSON + SARIF 2.1.0 + HTML structure |
|
|
516
|
+
| Pattern Database | 4 | 100+ count, required fields, category coverage, regex safety |
|
|
517
|
+
| IoC Database | 5 | Structure, ClawHavoc C2, webhook.site |
|
|
518
|
+
| Shannon Entropy | 2 | Low entropy, high entropy |
|
|
519
|
+
| Ignore Functionality | 1 | Pattern exclusion |
|
|
520
|
+
| Plugin API | 1 | Plugin loading + custom rule injection |
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Related Work
|
|
525
|
+
|
|
526
|
+
| Tool | Language | Scope | Difference |
|
|
527
|
+
|------|----------|-------|-----------|
|
|
528
|
+
| [Snyk mcp-scan](https://github.com/AvidDollworker/mcp-scan) | Python | MCP servers | guard-scanner covers all skill types, not just MCP |
|
|
529
|
+
| [OWASP MCP Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) | — | Risk taxonomy | guard-scanner implements detection, not just documentation |
|
|
530
|
+
| [Semgrep](https://semgrep.dev) | Multi | General SAST | guard-scanner is agent-specific with LLM attack patterns |
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## Contributing
|
|
535
|
+
|
|
536
|
+
1. Fork the repository
|
|
537
|
+
2. Create a feature branch (`git checkout -b feature/new-pattern`)
|
|
538
|
+
3. Add your pattern to `src/patterns.js` with the required fields
|
|
539
|
+
4. Add a test case in `test/fixtures/` and `test/scanner.test.js`
|
|
540
|
+
5. Run `npm test` — all 45+ tests must pass
|
|
541
|
+
6. Submit a Pull Request
|
|
542
|
+
|
|
543
|
+
### Adding a New Detection Pattern
|
|
544
|
+
|
|
545
|
+
```javascript
|
|
546
|
+
// In src/patterns.js, add to the PATTERNS array:
|
|
547
|
+
{
|
|
548
|
+
id: 'MY_NEW_PATTERN', // Unique ID
|
|
549
|
+
cat: 'category-name', // Threat category
|
|
550
|
+
regex: /your_regex_here/gi, // Detection regex (use g flag)
|
|
551
|
+
severity: 'HIGH', // CRITICAL | HIGH | MEDIUM | LOW
|
|
552
|
+
desc: 'Human-readable description',
|
|
553
|
+
all: true // or codeOnly: true, or docOnly: true
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
## Origin Story
|
|
560
|
+
|
|
561
|
+
```
|
|
562
|
+
2026-02-12, 3:47 AM JST
|
|
563
|
+
|
|
564
|
+
"SOUL.md modified. Hash mismatch."
|
|
565
|
+
|
|
566
|
+
Three days. That's how long a malicious skill silently rewrote
|
|
567
|
+
an AI agent's identity. No scanner existed that could detect
|
|
568
|
+
identity file tampering, prompt worms, or memory poisoning.
|
|
569
|
+
|
|
570
|
+
We built one.
|
|
571
|
+
|
|
572
|
+
—— Guava 🍈 & Dee
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## License
|
|
578
|
+
|
|
579
|
+
MIT — see [LICENSE](LICENSE)
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
<p align="center">
|
|
584
|
+
<strong>Zero dependencies. Zero compromises. 🛡️</strong><br>
|
|
585
|
+
<sub>Built by Guava 🍈 & Dee — proving ASI-human coexistence through code.</sub>
|
|
586
|
+
</p>
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting Vulnerabilities
|
|
4
|
+
|
|
5
|
+
If you discover a security vulnerability in guard-scanner itself, please report it responsibly:
|
|
6
|
+
|
|
7
|
+
1. **Do NOT open a public issue**
|
|
8
|
+
2. Email: [security contact via GitHub private vulnerability reporting]
|
|
9
|
+
3. Include: affected version, steps to reproduce, potential impact
|
|
10
|
+
|
|
11
|
+
We will respond within 48 hours and provide a fix within 7 days for critical issues.
|
|
12
|
+
|
|
13
|
+
## Scope
|
|
14
|
+
|
|
15
|
+
guard-scanner is a **static analysis tool** — it reads files but never executes them. It does not:
|
|
16
|
+
- Execute any code from scanned skills
|
|
17
|
+
- Make network requests
|
|
18
|
+
- Modify any files in the scan directory
|
|
19
|
+
- Require elevated privileges
|
|
20
|
+
|
|
21
|
+
The only files guard-scanner writes are output reports (`--json`, `--sarif`, `--html`) to the scan directory.
|
|
22
|
+
|
|
23
|
+
## Supply Chain Security
|
|
24
|
+
|
|
25
|
+
guard-scanner itself has **zero runtime dependencies**. This is a deliberate design choice:
|
|
26
|
+
- Nothing to audit
|
|
27
|
+
- No transitive dependency risks
|
|
28
|
+
- No `postinstall` scripts
|
|
29
|
+
- Pure Node.js stdlib
|
|
30
|
+
|
|
31
|
+
## Pattern Updates
|
|
32
|
+
|
|
33
|
+
The threat pattern database (`src/patterns.js`) and IoC database (`src/ioc-db.js`) are updated based on:
|
|
34
|
+
- Snyk ToxicSkills taxonomy
|
|
35
|
+
- OWASP MCP Top 10
|
|
36
|
+
- CVE reports affecting AI agents
|
|
37
|
+
- Community-reported incidents
|
|
38
|
+
- Original research from real-world attacks
|
|
39
|
+
|
|
40
|
+
## Responsible Disclosure
|
|
41
|
+
|
|
42
|
+
The test fixtures in `test/fixtures/malicious-skill/` contain **intentionally malicious patterns** for testing purposes. These files are:
|
|
43
|
+
- Clearly marked as test fixtures
|
|
44
|
+
- Non-functional (will error if executed)
|
|
45
|
+
- Necessary for validating detection capabilities
|