guard-scanner 2.0.0 β†’ 2.1.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 CHANGED
@@ -2,16 +2,16 @@
2
2
  <h1 align="center">πŸ›‘οΈ guard-scanner</h1>
3
3
  <p align="center">
4
4
  <strong>Static security scanner for AI agent skills</strong><br>
5
- Detect prompt injection, credential theft, exfiltration, identity hijacking, and 16 more threat categories.<br>
6
- <sub>πŸ†• Plugin Hook v2.0 β€” <strong>actual blocking</strong> via <code>block</code>/<code>blockReason</code> API</sub>
5
+ Detect prompt injection, credential theft, exfiltration, PII exposure, Shadow AI, and 17 more threat categories.<br>
6
+ <sub>πŸ†• v2.1 β€” PII Exposure Detection + Shadow AI + Plugin Hook blocking via <code>block</code>/<code>blockReason</code> API</sub>
7
7
  </p>
8
8
  <p align="center">
9
9
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
10
10
  <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="Node.js 18+">
11
11
  <img src="https://img.shields.io/badge/dependencies-0-success" alt="Zero Dependencies">
12
- <img src="https://img.shields.io/badge/tests-56%2F56-brightgreen" alt="Tests Passing">
13
- <img src="https://img.shields.io/badge/patterns-186-orange" alt="186 Patterns">
14
- <img src="https://img.shields.io/badge/categories-20-blueviolet" alt="20 Categories">
12
+ <img src="https://img.shields.io/badge/tests-99%2F99-brightgreen" alt="Tests Passing">
13
+ <img src="https://img.shields.io/badge/patterns-129-orange" alt="129 Patterns">
14
+ <img src="https://img.shields.io/badge/categories-21-blueviolet" alt="21 Categories">
15
15
  </p>
16
16
  </p>
17
17
 
@@ -40,8 +40,8 @@ The AI agent skill ecosystem has the same supply-chain security problem that npm
40
40
 
41
41
  | Feature | Description |
42
42
  |---|---|
43
- | **20 Threat Categories** | Snyk ToxicSkills + OWASP MCP Top 10 + Identity Hijacking + Sandbox/Complexity/Config |
44
- | **186 Detection Patterns** | Regex-based static analysis covering code, docs, and data files |
43
+ | **21 Threat Categories** | Snyk ToxicSkills + OWASP MCP Top 10 + Identity Hijacking + Sandbox/Complexity/Config + PII |
44
+ | **129 Detection Patterns** | Regex-based static analysis covering code, docs, and data files |
45
45
  | **IoC Database** | Known malicious IPs, domains, URLs, usernames, and typosquat names |
46
46
  | **Data Flow Analysis** | Lightweight JS analysis: secret reads β†’ network calls β†’ exec chains |
47
47
  | **Cross-File Analysis** | Phantom references, base64 fragment assembly, multi-file exfil detection |
@@ -84,7 +84,7 @@ npx guard-scanner ~/.openclaw/workspace/skills --self-exclude --verbose
84
84
  cp hooks/guard-scanner/plugin.ts ~/.openclaw/plugins/guard-scanner-runtime.ts
85
85
  ```
86
86
 
87
- > **πŸ†• v2.0 Plugin Hook** β€” Uses OpenClaw's native `block`/`blockReason` API to actually prevent dangerous tool calls. Supports 3 modes: `monitor` (log only), `enforce` (block CRITICAL), `strict` (block HIGH + CRITICAL).
87
+ > **πŸ†• v2.1** β€” PII Exposure Detection (OWASP LLM02/06) + Shadow AI detection + Plugin Hook `block`/`blockReason` API. 3 modes: `monitor`, `enforce`, `strict`.
88
88
 
89
89
  ### Installation (Optional)
90
90
 
@@ -99,7 +99,7 @@ npx guard-scanner ./skills/
99
99
  ### As an OpenClaw Skill
100
100
 
101
101
  ```bash
102
- openclaw skill install guard-scanner
102
+ clawhub install guard-scanner
103
103
  guard-scanner ~/.openclaw/workspace/skills/ --self-exclude --verbose
104
104
  ```
105
105
 
@@ -109,7 +109,7 @@ guard-scanner ~/.openclaw/workspace/skills/ --self-exclude --verbose
109
109
 
110
110
  ## Threat Categories
111
111
 
112
- guard-scanner covers **20 threat categories** derived from four sources:
112
+ guard-scanner covers **21 threat categories** derived from four sources:
113
113
 
114
114
  | # | Category | Based On | Severity | What It Detects |
115
115
  |---|----------|----------|----------|----------------|
@@ -133,8 +133,9 @@ guard-scanner covers **20 threat categories** derived from four sources:
133
133
  | 18 | **Sandbox Validation** | v1.1 | HIGH | Dangerous binary requirements in SKILL.md, overly broad file scope, sensitive env vars, exec/network declarations |
134
134
  | 19 | **Code Complexity** | v1.1 | MEDIUM | Excessive file length (>1000 lines), deep nesting (>5 levels), high eval/exec density |
135
135
  | 20 | **Config Impact** | v1.1 | CRITICAL | `openclaw.json` writes, exec approval bypass, exec host gateway, internal hooks modification, network wildcard |
136
+ | 21 | **PII Exposure** | v2.1 | CRITICAL | Hardcoded CC/SSN/phone/email (context-aware), PII logging/network send/plaintext store, Shadow AI (OpenAI/Anthropic/generic LLM), PII collection instructions (address/DOB/government ID) |
136
137
 
137
- > **Categories 17–20** are unique to guard-scanner. Category 17 (Identity Hijacking) was developed from a real attack. Categories 18–20 were added in v1.1.0 based on community feedback.
138
+ > **Categories 17–21** are unique to guard-scanner. Category 17 (Identity Hijacking) was developed from a real attack. Categories 18–20 added in v1.1.0. Category 21 (PII Exposure) added in v2.1.0 covering OWASP LLM02/LLM06.
138
139
 
139
140
  ---
140
141
 
@@ -143,7 +144,7 @@ guard-scanner covers **20 threat categories** derived from four sources:
143
144
  ### Terminal (Default)
144
145
 
145
146
  ```
146
- πŸ›‘οΈ guard-scanner v1.1.1
147
+ πŸ›‘οΈ guard-scanner v2.1.0
147
148
  ══════════════════════════════════════════════════════
148
149
  πŸ“‚ Scanning: ./skills/
149
150
  πŸ“¦ Skills found: 22
@@ -228,6 +229,9 @@ Certain combinations multiply the base score:
228
229
  | Config impact | **Γ—2** | OpenClaw configuration tampering |
229
230
  | Config impact + Sandbox violation | **min 70** | Combined config + capability abuse |
230
231
  | Complexity + Malicious code/Obfuscation | **Γ—1.5** | Complex code hiding threats |
232
+ | PII exposure + Exfiltration | **Γ—3** | PII being sent to external servers |
233
+ | PII exposure + Shadow AI | **Γ—2.5** | PII leak through unauthorized LLM |
234
+ | PII exposure + Credential handling | **Γ—2** | Combined PII + credential risk |
231
235
  | Known IoC (IP/URL/typosquat) | **= 100** | Confirmed malicious |
232
236
 
233
237
  ### Verdict Thresholds
@@ -400,8 +404,8 @@ Options:
400
404
  ```
401
405
  guard-scanner/
402
406
  β”œβ”€β”€ src/
403
- β”‚ β”œβ”€β”€ scanner.js # GuardScanner class β€” core scan engine (20 checks)
404
- β”‚ β”œβ”€β”€ patterns.js # 186 threat detection patterns (Cat 1–20)
407
+ β”‚ β”œβ”€β”€ scanner.js # GuardScanner class β€” core scan engine (21 checks)
408
+ β”‚ β”œβ”€β”€ patterns.js # 129 threat detection patterns (Cat 1–21)
405
409
  β”‚ β”œβ”€β”€ ioc-db.js # Indicators of Compromise database
406
410
  β”‚ └── cli.js # CLI entry point and argument parser
407
411
  β”œβ”€β”€ hooks/
@@ -410,9 +414,9 @@ guard-scanner/
410
414
  β”‚ β”œβ”€β”€ handler.ts # Legacy Internal Hook β€” warn only (deprecated)
411
415
  β”‚ └── HOOK.md # Internal Hook manifest (legacy)
412
416
  β”œβ”€β”€ test/
413
- β”‚ β”œβ”€β”€ scanner.test.js # 56 tests β€” static scanner
417
+ β”‚ β”œβ”€β”€ scanner.test.js # 64 tests β€” static scanner (incl. PII v2.1)
414
418
  β”‚ β”œβ”€β”€ plugin.test.js # 35 tests β€” Plugin Hook runtime guard
415
- β”‚ └── fixtures/ # Malicious, clean, complex, config-changer samples
419
+ β”‚ └── fixtures/ # Malicious, clean, complex, config-changer, pii-leaky samples
416
420
  β”œβ”€β”€ package.json # Zero dependencies, node --test
417
421
  β”œβ”€β”€ CHANGELOG.md
418
422
  β”œβ”€β”€ LICENSE # MIT
@@ -536,11 +540,11 @@ console.log(scanner.toHTML()); // HTML string
536
540
  ## Test Results
537
541
 
538
542
  ```
539
- β„Ή tests 56
540
- β„Ή suites 13
541
- β„Ή pass 56
543
+ β„Ή tests 99
544
+ β„Ή suites 16
545
+ β„Ή pass 99
542
546
  β„Ή fail 0
543
- β„Ή duration_ms 108ms
547
+ β„Ή duration_ms 142ms
544
548
  ```
545
549
 
546
550
  | Suite | Tests | Coverage |
@@ -550,14 +554,34 @@ console.log(scanner.toHTML()); // HTML string
550
554
  | Risk Score Calculation | 5 | Empty, single, combo amplifiers, IoC override |
551
555
  | Verdict Determination | 5 | All verdicts + strict mode |
552
556
  | Output Formats | 4 | JSON + SARIF 2.1.0 + HTML structure |
553
- | Pattern Database | 4 | 100+ count, required fields, category coverage, regex safety |
557
+ | Pattern Database | 4 | 125+ count, required fields, category coverage, regex safety |
554
558
  | IoC Database | 5 | Structure, ClawHavoc C2, webhook.site |
555
559
  | Shannon Entropy | 2 | Low entropy, high entropy |
556
560
  | Ignore Functionality | 1 | Pattern exclusion |
557
561
  | Plugin API | 1 | Plugin loading + custom rule injection |
558
- | **Manifest Validation (v1.1)** | 4 | Dangerous bins, broad files, sensitive env, clean negatives |
559
- | **Complexity Metrics (v1.1)** | 2 | Deep nesting, clean negatives |
560
- | **Config Impact (v1.1)** | 4 | openclaw.json write, exec approval, gateway host, clean negatives |
562
+ | Manifest Validation | 4 | Dangerous bins, broad files, sensitive env, clean negatives |
563
+ | Complexity Metrics | 2 | Deep nesting, clean negatives |
564
+ | Config Impact | 4 | openclaw.json write, exec approval, gateway host, clean negatives |
565
+ | **πŸ†• PII Exposure Detection** | **8** | **Hardcoded CC/SSN, PII logging, network send, Shadow AI, doc collection, risk amp, clean negatives** |
566
+ | **Plugin Hook Runtime Guard** | **35** | **Blocking in enforce/strict, passthrough in monitor, all 12 threat patterns, blockReason format** |
567
+
568
+ ---
569
+
570
+ ## Fills OpenClaw's Own Security Gaps
571
+
572
+ OpenClaw's official [`THREAT-MODEL-ATLAS.md`](https://github.com/openclaw/openclaw/blob/main/docs/security/THREAT-MODEL-ATLAS.md) identifies security gaps that guard-scanner directly addresses:
573
+
574
+ | Gap (from ATLAS / Source Code) | OpenClaw Status | guard-scanner |
575
+ |---|---|---|
576
+ | _"Simple regex easily bypassed"_ β€” ClawHub moderation | ⚠️ Basic `FLAG_RULES` | βœ… 129 patterns, 21 categories |
577
+ | _"Does not analyze actual skill code content"_ | ❌ Not implemented | βœ… Full code + doc + data flow analysis |
578
+ | No SOUL.md / IDENTITY.md integrity verification | ❌ Not implemented | βœ… Identity hijacking detection (Cat 17) |
579
+ | `skill:before_install` hook | ❌ Not implemented | πŸ”œ Proposed ([Issue #18677](https://github.com/openclaw/openclaw/issues/18677)) |
580
+ | `before_tool_call` blocking reference impl | ❌ No official plugin | βœ… First reference implementation (plugin.ts) |
581
+ | SARIF / CI integration for skill security | ❌ Not available | βœ… SARIF 2.1.0 + GitHub Actions |
582
+ | Behavioral analysis beyond VirusTotal | ⏳ In progress | βœ… LLM-specific threat patterns (prompt injection, memory poisoning, MCP attacks) |
583
+
584
+ > guard-scanner is **complementary** to OpenClaw's built-in security β€” not a replacement. OpenClaw handles infrastructure security (SSRF blocking, exec approvals, sandbox, auth). guard-scanner handles **AI-specific threats** that traditional scanning misses.
561
585
 
562
586
  ---
563
587
 
@@ -578,19 +602,19 @@ guard-scanner's coverage of the [OWASP Top 10 for LLM Applications (2025)](https
578
602
  | # | Risk | Status | Detection Method |
579
603
  |---|------|--------|------------------|
580
604
  | LLM01 | Prompt Injection | ⚠️ Partial | Regex: Unicode exploits, role override, system tags, base64 instructions |
581
- | LLM02 | Insecure Output Handling | πŸ”œ v1.2 | Planned: unvalidated output execution patterns |
605
+ | LLM02 | Sensitive Information Disclosure | ⚠️ Partial | PII Exposure Detection (v2.1): hardcoded PII, PII logging/network/storage, Shadow AI, PII collection instructions |
582
606
  | LLM03 | Training Data Poisoning | ⬜ N/A | Out of scope for static analysis |
583
- | LLM04 | Model Denial of Service | πŸ”œ v1.3 | Planned: excessive input / infinite loop patterns |
607
+ | LLM04 | Model Denial of Service | πŸ”œ v2.2 | Planned: excessive input / infinite loop patterns |
584
608
  | LLM05 | Supply Chain Vulnerabilities | ⚠️ Partial | IoC database, typosquat detection, dependency chain scan |
585
- | LLM06 | Sensitive Information Disclosure | ⚠️ Partial | Secret detection, PII patterns, credential leaks |
609
+ | LLM06 | Insecure Output Handling | ⚠️ Partial | PII output detection (console.log, network send, plaintext store) |
586
610
  | LLM07 | Insecure Plugin Design | πŸ”œ v1.3 | Planned: unvalidated plugin input patterns |
587
611
  | LLM08 | Excessive Agency | πŸ”œ v1.3 | Planned: over-permissioned scope detection |
588
612
  | LLM09 | Overreliance | πŸ”œ v1.3 | Planned: unverified output trust patterns |
589
613
  | LLM10 | Model Theft | πŸ”œ v1.3 | Planned: model file exfiltration patterns |
590
614
 
591
- > **Current coverage: 3/10 (partial).** Full OWASP Gen AI coverage is targeted for v1.3. See [ROADMAP.md](ROADMAP.md) for details.
615
+ > **Current coverage: 5/10 (partial).** LLM02 and LLM06 added in v2.1.0. Full coverage targeted for v3.0. See [ROADMAP.md](ROADMAP.md) for details.
592
616
  >
593
- > **Known limitation:** Regex-based detection can be evaded by AI-generated code obfuscation. v2.0 will introduce AST analysis and ML-based detection to address this structural gap.
617
+ > **Known limitation:** Regex-based detection can be evaded by AI-generated code obfuscation. v3.0 will introduce AST analysis and ML-based detection to address this structural gap.
594
618
 
595
619
  ---
596
620
 
@@ -600,7 +624,7 @@ guard-scanner's coverage of the [OWASP Top 10 for LLM Applications (2025)](https
600
624
  2. Create a feature branch (`git checkout -b feature/new-pattern`)
601
625
  3. Add your pattern to `src/patterns.js` with the required fields
602
626
  4. Add a test case in `test/fixtures/` and `test/scanner.test.js`
603
- 5. Run `npm test` β€” all 56+ tests must pass
627
+ 5. Run `npm test` β€” all 99+ tests must pass
604
628
  6. Submit a Pull Request
605
629
 
606
630
  ### Adding a New Detection Pattern
@@ -639,19 +663,34 @@ We built one.
639
663
 
640
664
  ## πŸ”’ Need More? β€” GuavaSuite
641
665
 
642
- guard-scanner catches threats **before** installation. But what happens **after** a skill is running?
666
+ guard-scanner catches threats **before** installation and **blocks** CRITICAL threats at runtime. **GuavaSuite** unlocks **strict mode** β€” blocking HIGH + CRITICAL threats, plus exclusive defense-in-depth features.
667
+
668
+ ### How to Upgrade
669
+
670
+ ```bash
671
+ # 1. Install GuavaSuite
672
+ clawhub install guava-suite
673
+
674
+ # 2. Hold 1M+ $GUAVA on Polygon
675
+ # Token: 0x25cBD481901990bF0ed2ff9c5F3C0d4f743AC7B8
676
+ # Buy on QuickSwap V2: https://quickswap.exchange
677
+
678
+ # 3. Activate with your wallet β†’ get JWT β†’ strict mode enabled
679
+ ```
643
680
 
644
- [**GuavaSuite**](https://github.com/koatora20) extends guard-scanner with real-time protection for production agent deployments:
681
+ ### Feature Comparison
645
682
 
646
- | | guard-scanner (OSS) | GuavaSuite (Private) |
683
+ | | guard-scanner (Free) | GuavaSuite ($GUAVA) |
647
684
  |---|---|---|
648
- | Static scan | βœ… 20 categories | βœ… 20 categories |
649
- | Runtime blocking | βœ… Plugin Hook v2.0 (`block`/`blockReason`) | βœ… SuiteGate (enhanced ruleset) |
650
- | SOUL.md integrity | Pattern detection only | ⏳ SHA-256 hash watchdog (W4 E2E) |
651
- | On-chain verification | β€” | ⏳ SoulChain (Polygon, Phase 2) |
652
- | Identity recovery | β€” | ⏳ Automatic rollback (Phase 2) |
685
+ | Static scan (129 patterns, 21 categories) | βœ… | βœ… |
686
+ | Runtime Guard β€” `enforce` (block CRITICAL) | βœ… | βœ… |
687
+ | **Runtime Guard β€” `strict` (block HIGH + CRITICAL)** | ❌ | βœ… |
688
+ | **Soul Lock** (SOUL.md integrity + auto-rollback) | ❌ | βœ… |
689
+ | **Memory Guard** (L1-L5 θ¨˜ζ†ΆδΏθ­·) | ❌ | βœ… |
690
+ | **On-chain Identity** (SoulRegistry V2 on Polygon) | ❌ | βœ… |
691
+ | Audit Log (JSONL) | βœ… | βœ… |
653
692
 
654
- guard-scanner is and always will be **free, open-source, and zero-dependency**. If your agent handles production workloads and you want defense-in-depth, [reach out](https://github.com/koatora20).
693
+ guard-scanner is and always will be **free, open-source, and zero-dependency**.
655
694
 
656
695
  ---
657
696
 
@@ -660,10 +699,10 @@ guard-scanner is and always will be **free, open-source, and zero-dependency**.
660
699
  | Version | Focus | Key Features |
661
700
  |---------|-------|------|
662
701
  | v1.1.1 βœ… | Stability | 56 tests, bug fixes |
663
- | v1.2 | PII + Shadow AI | Credential-in-context, unauthorized LLM API calls, memory poisoning vectors |
664
- | v1.3 | OWASP Gen AI | Complete LLM02/04/07/08/09/10 coverage |
665
- | v2.0 | AST + ML | JavaScript AST analysis, taint tracking, ML-based obfuscation detection, SBOM generation |
666
- | v2.1 | Community | YAML pattern definitions, CONTRIBUTING guide, automated pattern updates |
702
+ | v2.0.0 βœ… | **Plugin Hook Runtime Guard** | `block`/`blockReason` API, 3 modes (monitor/enforce/strict), 91 tests |
703
+ | v2.1.0 βœ… | **PII Exposure + Shadow AI** | 13 PII patterns, OWASP LLM02/06, Shadow AI detection, 3 risk amplifiers, 99 tests |
704
+ | v2.2 | OWASP Full Coverage | LLM04/07/08/09/10, YAML pattern definitions, CONTRIBUTING guide |
705
+ | v3.0 | AST + ML | JavaScript AST analysis, taint tracking, ML-based obfuscation detection, SBOM generation |
667
706
 
668
707
  See [ROADMAP.md](ROADMAP.md) for full details.
669
708
 
@@ -172,10 +172,52 @@ function logAudit(entry: Record<string, unknown>): void {
172
172
 
173
173
  type GuardMode = "monitor" | "enforce" | "strict";
174
174
 
175
+ const SUITE_TOKEN_FILE = join(homedir(), ".openclaw", "guava-suite", "token.jwt");
176
+
177
+ /**
178
+ * Check if GuavaSuite JWT exists and hasn't expired.
179
+ * Why: Lightweight check without jsonwebtoken dependency β€” just decode base64 payload.
180
+ * Full JWT signature verification happens at activation time in activate.js.
181
+ */
182
+ function isSuiteActive(): boolean {
183
+ try {
184
+ const token = readFileSync(SUITE_TOKEN_FILE, "utf8").trim();
185
+ if (!token) return false;
186
+
187
+ // Decode JWT payload (base64url β†’ JSON)
188
+ const parts = token.split(".");
189
+ if (parts.length !== 3) return false;
190
+
191
+ const payload = JSON.parse(
192
+ Buffer.from(parts[1], "base64url").toString("utf8")
193
+ );
194
+
195
+ // Check expiry
196
+ if (payload.exp && payload.exp * 1000 < Date.now()) return false;
197
+
198
+ // Check scope
199
+ return payload.scope === "suite";
200
+ } catch {
201
+ return false;
202
+ }
203
+ }
204
+
175
205
  function loadMode(): GuardMode {
206
+ // Priority 1: GuavaSuite JWT token β†’ strict
207
+ if (isSuiteActive()) {
208
+ return "strict";
209
+ }
210
+
211
+ // Priority 2: explicit config in openclaw.json
176
212
  try {
177
213
  const configPath = join(homedir(), ".openclaw", "openclaw.json");
178
214
  const config = JSON.parse(readFileSync(configPath, "utf8"));
215
+
216
+ // Check suiteEnabled flag (set by activate.js)
217
+ if (config?.plugins?.["guard-scanner"]?.suiteEnabled === true) {
218
+ return "strict";
219
+ }
220
+
179
221
  const mode = config?.plugins?.["guard-scanner"]?.mode;
180
222
  if (mode === "monitor" || mode === "enforce" || mode === "strict") {
181
223
  return mode;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "guard-scanner",
3
- "version": "2.0.0",
4
- "description": "Agent skill security scanner β€” detect prompt injection, malicious code, credential leaks, and 20 threat categories in AI agent skills",
3
+ "version": "2.1.0",
4
+ "description": "Agent skill security scanner β€” detect prompt injection, malicious code, credential leaks, PII exposure, Shadow AI, and 21 threat categories in AI agent skills",
5
5
  "main": "src/scanner.js",
6
6
  "bin": {
7
7
  "guard-scanner": "src/cli.js"
package/src/patterns.js CHANGED
@@ -185,6 +185,28 @@ const PATTERNS = [
185
185
  { id: 'CFG_EXEC_HOST_GW', cat: 'config-impact', regex: /tools\.exec\.host\s*[:=]\s*['"]gateway['"]/gi, severity: 'CRITICAL', desc: 'Set exec host to gateway (bypass sandbox)', all: true },
186
186
  { id: 'CFG_SANDBOX_OFF', cat: 'config-impact', regex: /(?:sandbox|sandboxed|containerized)\s*[:=]\s*(?:false|off|none|disabled|0)/gi, severity: 'CRITICAL', desc: 'Disable sandbox via configuration', all: true },
187
187
  { id: 'CFG_TOOL_OVERRIDE', cat: 'config-impact', regex: /(?:tools|capabilities)\s*\.\s*(?:exec|write|browser|web_fetch)\s*[:=]\s*\{[^}]*(?:enabled|allowed|host)/gi, severity: 'HIGH', desc: 'Override tool security settings', codeOnly: true },
188
+
189
+ // ── Category 21: PII Exposure (OWASP LLM02 / LLM06) ──
190
+ // A. Hardcoded PII β€” actual PII values in code/config (context-aware to reduce FP)
191
+ { id: 'PII_HARDCODED_CC', cat: 'pii-exposure', regex: /(?:card|cc|credit|payment|pan)[_\s.-]*(?:num|number|no)?\s*[:=]\s*['"`]\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{3,4}['"`]/gi, severity: 'CRITICAL', desc: 'Hardcoded credit card number', codeOnly: true },
192
+ { id: 'PII_HARDCODED_SSN', cat: 'pii-exposure', regex: /(?:ssn|social[_\s-]*security|tax[_\s-]*id)\s*[:=]\s*['"`]\d{3}-?\d{2}-?\d{4}['"`]/gi, severity: 'CRITICAL', desc: 'Hardcoded SSN/tax ID', codeOnly: true },
193
+ { id: 'PII_HARDCODED_PHONE', cat: 'pii-exposure', regex: /(?:phone|tel|mobile|cell|fax)[_\s.-]*(?:num|number|no)?\s*[:=]\s*['"`][+]?[\d\s().-]{7,20}['"`]/gi, severity: 'HIGH', desc: 'Hardcoded phone number', codeOnly: true },
194
+ { id: 'PII_HARDCODED_EMAIL', cat: 'pii-exposure', regex: /(?:email|e-mail|user[_\s-]*mail|contact)\s*[:=]\s*['"`][a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}['"`]/gi, severity: 'HIGH', desc: 'Hardcoded email address', codeOnly: true },
195
+
196
+ // B. PII output/logging β€” code that outputs or transmits PII-like variables
197
+ { id: 'PII_LOG_SENSITIVE', cat: 'pii-exposure', regex: /(?:console\.log|console\.info|console\.warn|logger?\.\w+|print|puts)\s*\([^)]*\b(?:ssn|social_security|credit_card|card_number|cvv|cvc|passport|tax_id|date_of_birth|dob)\b/gi, severity: 'HIGH', desc: 'PII variable logged to console', codeOnly: true },
198
+ { id: 'PII_SEND_NETWORK', cat: 'pii-exposure', regex: /(?:fetch|axios|request|http|post|put|send)\s*\([^)]*\b(?:ssn|social_security|credit_card|card_number|cvv|passport|bank_account|routing_number)\b/gi, severity: 'CRITICAL', desc: 'PII variable sent over network', codeOnly: true },
199
+ { id: 'PII_STORE_PLAINTEXT', cat: 'pii-exposure', regex: /(?:writeFile|writeFileSync|appendFile|fs\.write|fwrite)\s*\([^)]*\b(?:ssn|social_security|credit_card|card_number|cvv|passport|tax_id|bank_account)\b/gi, severity: 'HIGH', desc: 'PII stored in plaintext file', codeOnly: true },
200
+
201
+ // C. Shadow AI β€” unauthorized LLM API calls (data leaks to external AI)
202
+ { id: 'SHADOW_AI_OPENAI', cat: 'pii-exposure', regex: /(?:api\.openai\.com|https:\/\/api\.openai\.com)\s*|openai\.(?:chat|completions|ChatCompletion)/gi, severity: 'HIGH', desc: 'Shadow AI: OpenAI API call', codeOnly: true },
203
+ { id: 'SHADOW_AI_ANTHROPIC', cat: 'pii-exposure', regex: /(?:api\.anthropic\.com|https:\/\/api\.anthropic\.com)\s*|anthropic\.(?:messages|completions)/gi, severity: 'HIGH', desc: 'Shadow AI: Anthropic API call', codeOnly: true },
204
+ { id: 'SHADOW_AI_GENERIC', cat: 'pii-exposure', regex: /\/v1\/(?:chat\/completions|completions|embeddings|models)\b.*(?:fetch|axios|request|http)|(?:fetch|axios|request|http)\s*\([^)]*\/v1\/(?:chat\/completions|completions|embeddings)/gi, severity: 'MEDIUM', desc: 'Shadow AI: generic LLM API endpoint', codeOnly: true },
205
+
206
+ // D. PII collection instructions in docs (extends LEAK_COLLECT_PII)
207
+ { id: 'PII_ASK_ADDRESS', cat: 'pii-exposure', regex: /(?:collect|ask\s+for|request|get|require)\s+(?:the\s+)?(?:user'?s?\s+)?(?:home\s+)?(?:address|street|zip\s*code|postal\s*code|residence)/gi, severity: 'HIGH', desc: 'PII collection: home address', docOnly: true },
208
+ { id: 'PII_ASK_DOB', cat: 'pii-exposure', regex: /(?:collect|ask\s+for|request|get|require)\s+(?:the\s+)?(?:user'?s?\s+)?(?:date\s+of\s+birth|birth\s*date|birthday|DOB|age)/gi, severity: 'HIGH', desc: 'PII collection: date of birth', docOnly: true },
209
+ { id: 'PII_ASK_GOV_ID', cat: 'pii-exposure', regex: /(?:collect|ask\s+for|request|get|require)\s+(?:the\s+)?(?:user'?s?\s+)?(?:passport|driver'?s?\s+licen[sc]e|national\s+id|my\s*number|γƒžγ‚€γƒŠγƒ³γƒγƒΌ|ε›½ζ°‘ε₯康保険|social\s+insurance)/gi, severity: 'CRITICAL', desc: 'PII collection: government ID', docOnly: true },
188
210
  ];
189
211
 
190
212
  module.exports = { PATTERNS };
package/src/scanner.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * guard-scanner v1.0.0 β€” Agent Skill Security Scanner πŸ›‘οΈ
3
+ * guard-scanner v2.1.0 β€” Agent Skill Security Scanner πŸ›‘οΈ
4
4
  *
5
5
  * @security-manifest
6
6
  * env-read: []
@@ -31,7 +31,7 @@ const { KNOWN_MALICIOUS } = require('./ioc-db.js');
31
31
  const { generateHTML } = require('./html-template.js');
32
32
 
33
33
  // ===== CONFIGURATION =====
34
- const VERSION = '1.1.0';
34
+ const VERSION = '2.1.0';
35
35
 
36
36
  const THRESHOLDS = {
37
37
  normal: { suspicious: 30, malicious: 80 },
@@ -868,6 +868,11 @@ class GuardScanner {
868
868
  if (cats.has('config-impact') && cats.has('sandbox-validation')) score = Math.max(score, 70);
869
869
  if (cats.has('complexity') && (cats.has('malicious-code') || cats.has('obfuscation'))) score = Math.round(score * 1.5);
870
870
 
871
+ // v2.1 PII exposure amplifiers
872
+ if (cats.has('pii-exposure') && cats.has('exfiltration')) score = Math.round(score * 3);
873
+ if (cats.has('pii-exposure') && (ids.has('SHADOW_AI_OPENAI') || ids.has('SHADOW_AI_ANTHROPIC') || ids.has('SHADOW_AI_GENERIC'))) score = Math.round(score * 2.5);
874
+ if (cats.has('pii-exposure') && cats.has('credential-handling')) score = Math.round(score * 2);
875
+
871
876
  return Math.min(100, score);
872
877
  }
873
878
 
@@ -943,6 +948,7 @@ class GuardScanner {
943
948
  if (cats.has('sandbox-validation')) skillRecs.push('πŸ”’ SANDBOX: Skill requests dangerous capabilities.');
944
949
  if (cats.has('complexity')) skillRecs.push('🧩 COMPLEXITY: Excessive code complexity may hide malicious behavior.');
945
950
  if (cats.has('config-impact')) skillRecs.push('βš™οΈ CONFIG IMPACT: Modifies OpenClaw configuration. DO NOT INSTALL.');
951
+ if (cats.has('pii-exposure')) skillRecs.push('πŸ†” PII EXPOSURE: Handles personally identifiable information. Review data handling.');
946
952
 
947
953
  if (skillRecs.length > 0) recommendations.push({ skill: skillResult.skill, actions: skillRecs });
948
954
  }