ship-safe 6.4.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,11 +16,11 @@
16
16
 
17
17
  ---
18
18
 
19
- 18 security agents. 80+ attack classes. One command.
19
+ 22 security agents. 80+ attack classes. One command.
20
20
 
21
- **Ship Safe v6.4.0** is an AI-powered security platform that runs 18 specialized agents in parallel against your codebase, scanning for secrets, injection vulnerabilities, auth bypass, SSRF, supply chain attacks, Supabase RLS misconfigs, Docker/Terraform/Kubernetes misconfigs, CI/CD pipeline poisoning, LLM/agentic AI security, MCP server misuse, RAG poisoning, PII compliance, vibe coding patterns, exception handling, AI agent config security, and more. OWASP 2025 scoring with EPSS exploit probability. LLM-powered deep analysis verifies exploitability of critical findings. Secrets verification probes provider APIs to check if leaked keys are still active. Compliance mapping to SOC 2, ISO 27001, and NIST AI RMF. Built-in threat intelligence feed with offline-first IOC matching. CI integration with GitHub PR comments, threshold gating, and SARIF output.
21
+ **Ship Safe v8.0.0** is an AI-powered security platform that runs 22 specialized agents in parallel against your codebase covering secrets, injection vulnerabilities, auth bypass, SSRF, supply chain attacks, memory poisoning, Hermes Agent security, Supabase RLS, Docker/Terraform/Kubernetes misconfigs, CI/CD pipeline poisoning, LLM/agentic AI security, MCP server misuse, RAG poisoning, PII compliance, vibe coding patterns, exception handling, Claude Managed Agent configs, and more. Full OWASP Agentic AI Top 10 mapping (ASI-01–ASI-10) enriches every finding. Live OSV.dev advisory feed surfaces actively exploited CVEs within hours of disclosure. OWASP 2025 scoring with EPSS exploit probability. LLM-powered deep analysis verifies exploitability of critical findings. Secrets verification probes provider APIs to check if leaked keys are still active.
22
22
 
23
- **v6.4.0 highlights:** MCP server scanning (`npx ship-safe scan-mcp`) vets tool manifests for prompt injection and credential harvesting before you connect. Detection support for openclaude and claw-code the two most-starred Claude Code forks from the March 2026 source leak with accurate config scanning based on their actual architectures. Four new CI/CD patterns flag AI agent danger modes in pipelines. Legal dataset corrected: claw-code reclassified as a clean-room rewrite, not a leaked-source derivative.
23
+ **v8.0.0 highlights:** **Ship Safe × Hermes Agent** — two new agents purpose-built for [NousResearch Hermes Agent](https://github.com/NousResearch/hermes-function-calling) deployments. `HermesSecurityAgent` detects 17 attack patterns across the full OWASP Agentic AI Top 10 surface: tool registry poisoning, function-call injection, goal/plan hijacking, memory layer attacks, skill permission drift, and multi-agent trust boundary violations. `AgentAttestationAgent` catches supply-chain failures in agent manifests: unpinned versions, missing integrity hashes on remote tool sources, unsigned manifests, and dynamic `require()` of manifests from env vars. Both agents integrate into the `--agentic` loop for automated scan annotate re-scan cycles. Ship Safe is now a first-class Hermes citizen via `skills/ship-safe-security.md` and `registerWithHermes()`.
24
24
 
25
25
  [Documentation](https://shipsafecli.com/docs) | [Blog](https://shipsafecli.com/blog) | [Pricing](https://shipsafecli.com/pricing)
26
26
 
@@ -29,19 +29,32 @@
29
29
  ## Quick Start
30
30
 
31
31
  ```bash
32
- # Full security audit — secrets + 18 agents + deps + remediation plan
32
+ # Full security audit — secrets + 22 agents + deps + remediation plan
33
33
  npx ship-safe audit .
34
34
 
35
- # LLM-powered deep analysis (Anthropic, OpenAI, Google, Ollama)
35
+ # LLM-powered deep analysis (Anthropic, OpenAI, Google, Ollama, Gemma 4)
36
36
  npx ship-safe audit . --deep
37
37
 
38
- # Red team scan only (18 agents, 80+ attack classes)
38
+ # Agentic loop scan auto-annotate fixes re-scan until score ≥ 75
39
+ npx ship-safe audit . --agentic
40
+ npx ship-safe audit . --agentic 5 --agentic-target 85
41
+
42
+ # Red team scan (22 agents, 80+ attack classes)
39
43
  npx ship-safe red-team .
40
44
 
41
45
  # Scan only changed files (fast pre-commit & PR scanning)
42
46
  npx ship-safe diff
43
47
  npx ship-safe diff --staged
44
48
 
49
+ # Live OSV.dev advisory feed — no API key, no stale data
50
+ npx ship-safe advisories .
51
+
52
+ # Continuous monitoring
53
+ npx ship-safe watch . # Lightweight file watcher
54
+ npx ship-safe watch . --deep # Full 22-agent scan on every change
55
+ npx ship-safe watch . --deep --threshold 80 # Fail if score drops below threshold
56
+ npx ship-safe watch . --status # Show last deep-watch results
57
+
45
58
  # Fun emoji security grade with shareable badge
46
59
  npx ship-safe vibe-check .
47
60
 
@@ -74,8 +87,6 @@ npx ship-safe hooks status
74
87
  npx ship-safe hooks remove
75
88
  ```
76
89
 
77
- ![ship-safe terminal demo](.github/assets/ship%20safe%20terminal.jpg)
78
-
79
90
  ---
80
91
 
81
92
  ## The `audit` Command
@@ -88,11 +99,11 @@ npx ship-safe audit .
88
99
 
89
100
  ```
90
101
  ════════════════════════════════════════════════════════════
91
- Ship Safe v6.0 — Full Security Audit
102
+ Ship Safe v8.0 — Full Security Audit
92
103
  ════════════════════════════════════════════════════════════
93
104
 
94
105
  [Phase 1/4] Scanning for secrets... ✔ 49 found
95
- [Phase 2/4] Running 18 security agents... ✔ 103 findings
106
+ [Phase 2/4] Running 22 security agents... ✔ 103 findings
96
107
  [Phase 3/4] Auditing dependencies... ✔ 44 CVEs
97
108
  [Phase 4/4] Computing security score... ✔ 25/100 F
98
109
 
@@ -119,7 +130,7 @@ npx ship-safe audit .
119
130
 
120
131
  **What it runs:**
121
132
  1. **Secret scan** — 50+ patterns with entropy scoring (API keys, passwords, tokens)
122
- 2. **18 security agents** — run in parallel with per-agent timeouts and framework-aware filtering (injection, auth, SSRF, supply chain, config, Supabase RLS, LLM, MCP, agentic AI, RAG, PII, vibe coding, exception handling, agent config, mobile, git history, CI/CD, API)
133
+ 2. **22 security agents** — run in parallel with per-agent timeouts and framework-aware filtering
123
134
  3. **Dependency audit** — npm/pip/bundler CVE scanning with EPSS exploit probability scores
124
135
  4. **Secrets verification** — probes provider APIs (GitHub, Stripe, OpenAI, etc.) to check if leaked keys are still active
125
136
  5. **Deep analysis** — LLM-powered taint analysis verifies exploitability of critical/high findings (optional)
@@ -145,38 +156,43 @@ npx ship-safe audit .
145
156
  - `--deep` — LLM-powered taint analysis for critical/high findings
146
157
  - `--local` — use local Ollama model for deep analysis
147
158
  - `--model <model>` — LLM model to use for deep/AI analysis
148
- - `--provider <name>` — LLM provider: groq, together, mistral, deepseek, xai, perplexity, lmstudio
159
+ - `--provider <name>` — LLM provider: groq, together, mistral, deepseek, xai, perplexity, lmstudio, gemma4
149
160
  - `--base-url <url>` — custom OpenAI-compatible base URL (e.g. LM Studio, vLLM)
150
161
  - `--budget <cents>` — max spend in cents for deep analysis (default: 50)
151
162
  - `--verify` — check if leaked secrets are still active (probes provider APIs)
163
+ - `--agentic [n]` — scan → annotate fixes → re-scan loop, up to n iterations (default: 3)
164
+ - `--agentic-target <score>` — stop agentic loop when score reaches this threshold (default: 75)
152
165
 
153
166
  ---
154
167
 
155
- ## 18 Security Agents
168
+ ## 22 Security Agents
156
169
 
157
170
  | Agent | Category | What It Detects |
158
171
  |-------|----------|-----------------|
159
172
  | **InjectionTester** | Code Vulns | SQL/NoSQL injection, command injection, code injection (eval), XSS, path traversal, XXE, ReDoS, prototype pollution, Python f-string SQL injection, Python subprocess shell injection |
160
173
  | **AuthBypassAgent** | Auth | JWT vulnerabilities (alg:none, weak secrets), cookie security, CSRF, OAuth misconfig, BOLA/IDOR, weak crypto, timing attacks, TLS bypass, Django `DEBUG = True`, Flask hardcoded secret keys |
161
174
  | **SSRFProber** | SSRF | User input in fetch/axios, cloud metadata endpoints, internal IPs, redirect following |
162
- | **SupplyChainAudit** | Supply Chain | Typosquatting (Levenshtein distance), git/URL dependencies, wildcard versions, suspicious install scripts, dependency confusion, lockfile integrity |
175
+ | **SupplyChainAudit** | Supply Chain | Typosquatting (Levenshtein distance), git/URL dependencies, wildcard versions, suspicious install scripts, dependency confusion, lockfile integrity, trojanized package behavioral signatures (env-var harvesting, DNS exfiltration, WebSocket C2) |
163
176
  | **ConfigAuditor** | Config | Dockerfile (running as root, :latest tags), Terraform (public S3/RDS, open SG, CloudFront HTTP, Lambda admin, S3 no versioning), Kubernetes (privileged containers, `:latest` tags, missing NetworkPolicy), CORS, CSP, Firebase, Nginx |
164
177
  | **SupabaseRLSAgent** | Auth | Supabase Row Level Security — `service_role` key in client code, `CREATE TABLE` without RLS, anon key inserts, unprotected storage operations |
165
178
  | **LLMRedTeam** | AI/LLM | OWASP LLM Top 10 — prompt injection, excessive agency, system prompt leakage, unbounded consumption, RAG poisoning |
166
179
  | **MCPSecurityAgent** | AI/LLM | MCP server security — unvalidated tool inputs, missing auth, excessive permissions, tool poisoning, typosquatting detection, over-permissioned tools, shadow config discovery |
167
180
  | **AgenticSecurityAgent** | AI/LLM | OWASP Agentic AI Top 10 — agent hijacking, privilege escalation, unsafe code execution, memory poisoning |
168
181
  | **RAGSecurityAgent** | AI/LLM | RAG pipeline security — unvalidated embeddings, context injection, document poisoning, vector DB access control |
182
+ | **MemoryPoisoningAgent** | AI/LLM | ASI-01/ASI-05 — instruction injection in `.claude/memory/`, `.cursorrules`, `.cursor/rules/`, `.windsurfrules`, `.continue/config.json`, `.gemini/`, `.cody/`, `.augment/` and docs; hidden Unicode payloads; persona hijacking; persistent trigger detection |
169
183
  | **PIIComplianceAgent** | Compliance | PII detection — SSNs, credit cards, emails, phone numbers in source code, logs, and configs |
170
184
  | **VibeCodingAgent** | Code Vulns | AI-generated code patterns — no input validation, empty catch blocks, hardcoded secrets, disabled security features, TODO-auth patterns |
171
185
  | **ExceptionHandlerAgent** | Code Vulns | OWASP A10:2025 — empty catch blocks, unhandled promise rejections, missing React error boundaries, leaked stack traces, generic catch-all without rethrow |
172
- | **AgentConfigScanner** | AI/LLM | AI agent config security — prompt injection in .cursorrules/CLAUDE.md/AGENTS.md/.windsurfrules, malicious Claude Code hooks (CVE-2026), OpenClaw public binding & malicious skills, openclaude profile file (`OPENAI_BASE_URL` over http://), claw-code config (`danger-full-access`, disabled sandbox, shell hooks, insecure MCP transports), encoded/obfuscated payloads, data exfiltration instructions, agent memory poisoning |
186
+ | **AgentConfigScanner** | AI/LLM | AI agent config security — prompt injection in .cursorrules/CLAUDE.md/AGENTS.md/.windsurfrules, malicious Claude Code hooks (CVE-2026), OpenClaw public binding & malicious skills, claw-code config risks, Gemini CLI / Cody / Augment Code config risks, encoded/obfuscated payloads |
173
187
  | **MobileScanner** | Mobile | OWASP Mobile Top 10 2024 — insecure storage, WebView JS injection, HTTP endpoints, excessive permissions, debug mode |
174
188
  | **GitHistoryScanner** | Secrets | Leaked secrets in git commit history (checks if still active in working tree) |
175
- | **CICDScanner** | CI/CD | OWASP CI/CD Top 10 — pipeline poisoning, unpinned actions, secret logging, self-hosted runners, script injection, AI agent danger flags (`--dangerously-skip-permissions`, insecure provider URLs in CI) |
189
+ | **CICDScanner** | CI/CD | OWASP CI/CD Top 10 — pipeline poisoning, unpinned actions, secret logging, self-hosted runners, script injection, AI agent danger flags |
176
190
  | **APIFuzzer** | API | Routes without auth, missing input validation, mass assignment, unrestricted file upload, GraphQL introspection, debug endpoints, missing rate limiting, OpenAPI spec security issues |
177
- | **ReconAgent** | Recon | Attack surface discoveryframeworks, languages, auth patterns, databases, cloud providers, IaC, CI/CD pipelines |
191
+ | **ManagedAgentScanner** | AI/LLM | Claude Managed Agents misconfigurations `always_allow` permission policies, unrestricted networking, bash without human confirmation, MCP servers over HTTP, hardcoded vault tokens, unpinned environment packages (ASI-03, ASI-04, ASI-05, ASI-07) |
192
+ | **HermesSecurityAgent** *(new)* | AI/LLM | Hermes Agent deployments — tool registry poisoning, function-call injection (`<tool_call>` / `<function_calls>`), goal/plan hijacking, memory layer attacks, skill permission drift, sub-agent trust boundary violations, manifest attestation (ASI-01–ASI-10) |
193
+ | **AgentAttestationAgent** *(new)* | Supply Chain | Agent manifest supply chain — unpinned versions (`latest`, `^`, `~`), missing integrity hashes on remote tool sources, unsigned manifests, `skipIntegrityCheck` bypass, dynamic `require()` of manifests from env vars, missing provenance fields (ASI-10, SLSA Level 0) |
178
194
 
179
- **Post-processors:** ScoringEngine (8-category weighted scoring), VerifierAgent (secrets liveness verification), DeepAnalyzer (LLM-powered taint analysis)
195
+ **Post-processors:** ScoringEngine (8-category weighted scoring with OWASP Agentic AI Top 10 enrichment), VerifierAgent (secrets liveness verification), DeepAnalyzer (LLM-powered taint analysis)
180
196
 
181
197
  ---
182
198
 
@@ -188,7 +204,7 @@ npx ship-safe audit .
188
204
  # Full audit with remediation plan + HTML report
189
205
  npx ship-safe audit .
190
206
 
191
- # Red team: 18 agents, 80+ attack classes
207
+ # Red team: 22 agents, 80+ attack classes
192
208
  npx ship-safe red-team .
193
209
  npx ship-safe red-team . --agents injection,auth # Run specific agents
194
210
  npx ship-safe red-team . --html report.html # HTML report
@@ -348,6 +364,27 @@ Ship Safe detects security issues in both major Claude Code forks from the March
348
364
  - Hook commands containing shell execution or remote download patterns
349
365
  - MCP server connections over `ws://` or `http://` to non-localhost hosts
350
366
 
367
+ ### Hermes Agent Integration
368
+
369
+ Ship Safe is a first-class Hermes Agent citizen. Register Ship Safe tools directly in your Hermes tool registry:
370
+
371
+ ```js
372
+ import { registerWithHermes, verifyIntegrity } from 'ship-safe';
373
+
374
+ // Register all 5 Ship Safe tools with integrity verification
375
+ await registerWithHermes(toolRegistry);
376
+ ```
377
+
378
+ Or use the bundled skill in your Hermes agent:
379
+
380
+ ```yaml
381
+ # In your Hermes agent manifest
382
+ skills:
383
+ - ./node_modules/ship-safe/skills/ship-safe-security.md
384
+ ```
385
+
386
+ Available tools: `ship_safe_audit`, `ship_safe_scan_mcp`, `ship_safe_get_findings`, `ship_safe_suppress_finding`, `ship_safe_memory_list`.
387
+
351
388
  ### Threat Intelligence
352
389
 
353
390
  ```bash
@@ -398,6 +435,16 @@ jobs:
398
435
 
399
436
  Scans `openclaw.json`, `.cursorrules`, `CLAUDE.md`, Claude Code hooks, and MCP configs. Checks against the bundled threat intelligence database for known ClawHavoc IOCs.
400
437
 
438
+ ### Live Advisory Feed
439
+
440
+ ```bash
441
+ # Query OSV.dev for actively exploited CVEs across all package ecosystems
442
+ npx ship-safe advisories .
443
+ npx ship-safe advisories . --json # JSON output for CI
444
+ ```
445
+
446
+ No API key required. Malware advisories (MAL-*) are sorted to the top. Results include EPSS exploit probability and remediation guidance.
447
+
401
448
  ### Defensive Hooks
402
449
 
403
450
  ```bash
@@ -411,9 +458,15 @@ npx ship-safe watch . --configs
411
458
  ### Infrastructure Commands
412
459
 
413
460
  ```bash
414
- # Continuous monitoring (watch files for changes)
461
+ # Lightweight file watcher — re-scans changed files on save
415
462
  npx ship-safe watch .
416
463
 
464
+ # Deep watch — full 22-agent orchestrator on every change
465
+ npx ship-safe watch . --deep
466
+ npx ship-safe watch . --deep --threshold 80 # Fail if score drops below threshold
467
+ npx ship-safe watch . --deep --debounce 2000 # Custom debounce in ms (default: 1000)
468
+ npx ship-safe watch . --status # Show last deep-watch results from .ship-safe/watch.json
469
+
417
470
  # Generate CycloneDX SBOM
418
471
  npx ship-safe sbom .
419
472
 
@@ -469,7 +522,7 @@ claude plugin add github:asamassekou10/ship-safe
469
522
 
470
523
  | Command | Description |
471
524
  |---------|-------------|
472
- | `/ship-safe` | Full security audit — 18 agents, remediation plan, auto-fix |
525
+ | `/ship-safe` | Full security audit — 22 agents, remediation plan, auto-fix |
473
526
  | `/ship-safe-scan` | Quick scan for leaked secrets |
474
527
  | `/ship-safe-score` | Security health score (0-100) |
475
528
  | `/ship-safe-deep` | LLM-powered deep taint analysis |
@@ -526,7 +579,8 @@ Ship Safe supports any AI provider for deep analysis and classification:
526
579
  | **Anthropic** | `ANTHROPIC_API_KEY` | *(auto-detected)* | claude-haiku-4-5 |
527
580
  | **OpenAI** | `OPENAI_API_KEY` | *(auto-detected)* | gpt-4o-mini |
528
581
  | **Google** | `GOOGLE_AI_API_KEY` | *(auto-detected)* | gemini-2.0-flash |
529
- | **Ollama** | `OLLAMA_HOST` | `--local` | Local models |
582
+ | **Gemma 4 (Ollama)** | *(none)* | `--provider gemma4` | gemma4:e4b (256K ctx) |
583
+ | **Ollama** | `OLLAMA_HOST` | `--local` | gemma4:e4b |
530
584
  | **Groq** | `GROQ_API_KEY` | `--provider groq` | llama-3.3-70b-versatile |
531
585
  | **Together AI** | `TOGETHER_API_KEY` | `--provider together` | meta-llama/Llama-3-70b-chat-hf |
532
586
  | **Mistral** | `MISTRAL_API_KEY` | `--provider mistral` | mistral-small-latest |
@@ -658,7 +712,7 @@ docs/
658
712
  | **OWASP Top 10 Mobile 2024** | M1-M10: Improper Credential Usage, Inadequate Supply Chain, Insecure Auth, Insufficient Validation, Insecure Communication, Inadequate Privacy, Binary Protections, Security Misconfiguration, Insecure Data Storage, Insufficient Cryptography |
659
713
  | **OWASP LLM Top 10 2025** | LLM01-LLM10: Prompt Injection, Sensitive Info Disclosure, Supply Chain, Data Poisoning, Improper Output Handling, Excessive Agency, System Prompt Leakage, Vector/Embedding Weaknesses, Misinformation, Unbounded Consumption |
660
714
  | **OWASP CI/CD Top 10** | CICD-SEC-1 to 10: Insufficient Flow Control, Identity Management, Dependency Chain Abuse, Poisoned Pipeline Execution, Insufficient PBAC, Credential Hygiene, Insecure System Config, Ungoverned Usage, Improper Artifact Integrity, Insufficient Logging |
661
- | **OWASP Agentic AI Top 10** | ASI01-ASI10: Agent Hijacking, Tool Misuse, Privilege Escalation, Unsafe Code Execution, Memory Poisoning, Identity Spoofing, Excessive Autonomy, Logging Gaps, Supply Chain Attacks, Cascading Hallucination |
715
+ | **OWASP Agentic AI Top 10** | ASI-01–ASI-10: Goal Hijacking, Excessive Agency, Unsafe Tool Use, Unvalidated Actions, Untrusted Tools, Memory Poisoning, Lack of Oversight, Logging Gaps, Supply Chain Attacks, Cascading Failures |
662
716
 
663
717
  ---
664
718
 
@@ -676,6 +730,9 @@ LLM security: prompt injection detection, cost protection, system prompt hardeni
676
730
  ### [`/checklists`](./checklists)
677
731
  Manual security audits: launch-day checklist, framework-specific guides.
678
732
 
733
+ ### [`/skills`](./skills)
734
+ Hermes Agent skill definitions. Install `skills/ship-safe-security.md` to give any Hermes agent native security scanning capabilities.
735
+
679
736
  ---
680
737
 
681
738
  ## Add a Security Badge to Your README
@@ -0,0 +1,318 @@
1
+ /**
2
+ * AgentAttestationAgent — Ship Safe × Hermes Agent
3
+ * ==================================================
4
+ *
5
+ * Detects missing or broken attestation in agent manifests and deployment
6
+ * configurations: unsigned manifests, missing provenance, unpinned package
7
+ * versions, integrity hash drift, and lack of supply-chain controls.
8
+ *
9
+ * OWASP Agentic AI: ASI-10 (Supply Chain), ASI-07 (Lack of Oversight)
10
+ * SLSA Level 0 → checking for basic provenance and version pinning.
11
+ *
12
+ * SCANNING TARGETS:
13
+ * - agent-manifest.{json,yaml,yml}
14
+ * - agents.{json,yaml,yml}
15
+ * - hermes.config.{js,ts,json,yaml,yml}
16
+ * - openclaw.json
17
+ * - package.json, package-lock.json
18
+ * - .hermes/**
19
+ * - Any file declaring agent versions, integrity hashes, or provenance
20
+ */
21
+
22
+ import fs from 'fs';
23
+ import path from 'path';
24
+ import { createHash } from 'crypto';
25
+ import { BaseAgent, createFinding } from './base-agent.js';
26
+
27
+ // =============================================================================
28
+ // PATTERNS — detected in source files
29
+ // =============================================================================
30
+
31
+ const PATTERNS = [
32
+ // ── Unpinned versions ──────────────────────────────────────────────────────
33
+ {
34
+ rule: 'AGENT_UNPINNED_VERSION_LATEST',
35
+ title: 'Agent: Unpinned version "latest" (ASI-10 Supply Chain)',
36
+ regex: /["'](?:\w*[Vv]ersion|tag|image|ref)["']\s*:\s*["']latest["']/gi,
37
+ severity: 'high',
38
+ cwe: 'CWE-1104',
39
+ owasp: 'ASI-10',
40
+ confidence: 'high',
41
+ description: 'Agent/image version pinned to "latest" — next pull may silently upgrade to a tampered or incompatible version.',
42
+ fix: 'Pin to a specific semantic version (e.g., "1.2.3") or commit SHA.',
43
+ },
44
+ {
45
+ rule: 'AGENT_UNPINNED_VERSION_STAR',
46
+ title: 'Agent: Unpinned version wildcard (* or ^) (ASI-10)',
47
+ regex: /["'](?:\w*[Vv]ersion|tag)["']\s*:\s*["'][\^~*><=][^"']{1,20}["']/gi,
48
+ severity: 'high',
49
+ cwe: 'CWE-1104',
50
+ owasp: 'ASI-10',
51
+ confidence: 'high',
52
+ description: 'Agent version uses a mutable range specifier — version may float to an attacker-controlled release.',
53
+ fix: 'Pin to an exact version string without range operators.',
54
+ },
55
+ {
56
+ rule: 'AGENT_HERMES_UNPINNED',
57
+ title: 'Hermes: @nousresearch/hermes-agent not pinned to exact version',
58
+ regex: /["']@nousresearch\/hermes-agent["']\s*:\s*["'][\^~*><=][^"']{1,20}["']/gi,
59
+ severity: 'high',
60
+ cwe: 'CWE-1104',
61
+ owasp: 'ASI-10',
62
+ confidence: 'high',
63
+ description: 'hermes-agent package version is not pinned — a malicious minor/patch release could modify agent behavior.',
64
+ fix: 'Pin to exact version: "\"@nousresearch/hermes-agent\": \"1.2.3\""',
65
+ },
66
+
67
+ // ── Missing integrity fields ────────────────────────────────────────────────
68
+ {
69
+ rule: 'AGENT_NO_INTEGRITY_HASH',
70
+ title: 'Agent: No integrity hash on remote resource (ASI-10)',
71
+ regex: /["'](?:url|source|registry|endpoint)["']\s*:\s*["']https?:\/\/[^"']{10,}["'](?!\s*,?\s*["']integrity["'])/gi,
72
+ severity: 'high',
73
+ cwe: 'CWE-494',
74
+ owasp: 'ASI-10',
75
+ confidence: 'medium',
76
+ description: 'Remote resource loaded without an integrity hash — no way to detect tampering between publish and load time.',
77
+ fix: 'Add an "integrity": "sha256-..." or "sha512-..." field alongside the URL.',
78
+ },
79
+ {
80
+ rule: 'AGENT_MANIFEST_NO_SIGNATURE',
81
+ title: 'Agent: Manifest loaded without signature verification',
82
+ regex: /(?:loadManifest|readManifest|parseManifest|loadConfig|readConfig|parseConfig)\s*\([^)]{0,80}\)(?!\s*\.(?:verify|checkSignature|assertIntegrity))/gi,
83
+ severity: 'high',
84
+ cwe: 'CWE-345',
85
+ owasp: 'ASI-10',
86
+ confidence: 'medium',
87
+ description: 'Agent manifest is loaded/parsed without a subsequent signature or integrity check — manifest tampering goes undetected.',
88
+ fix: 'Verify manifest signature or compute expected SHA-256 before trusting its contents.',
89
+ },
90
+
91
+ // ── Missing provenance fields ──────────────────────────────────────────────
92
+ {
93
+ rule: 'AGENT_NO_AUTHOR_FIELD',
94
+ title: 'Agent manifest: No author/publisher field',
95
+ regex: /^\s*\{\s*"(?:name|id|version)":/m,
96
+ severity: 'low',
97
+ cwe: 'CWE-1059',
98
+ owasp: 'ASI-10',
99
+ confidence: 'low',
100
+ description: 'Agent manifest has no author or publisher field — provenance cannot be established.',
101
+ fix: 'Add "author", "publisher", or "maintainer" fields with contact information.',
102
+ },
103
+
104
+ // ── Attestation bypass patterns ────────────────────────────────────────────
105
+ {
106
+ rule: 'AGENT_SKIP_INTEGRITY_CHECK',
107
+ title: 'Agent: Integrity check explicitly skipped',
108
+ regex: /(?:skipIntegrityCheck\s*:\s*true|verifyIntegrity\s*:\s*false|integrity\s*:\s*false|bypassAttestation\s*:\s*true|noVerify\s*:\s*true)/gi,
109
+ severity: 'critical',
110
+ cwe: 'CWE-345',
111
+ owasp: 'ASI-10',
112
+ confidence: 'high',
113
+ description: 'Code explicitly disables integrity checking — removes the primary defense against supply-chain attacks.',
114
+ fix: 'Remove the integrity bypass flag and restore verification.',
115
+ },
116
+ {
117
+ rule: 'AGENT_DYNAMIC_REQUIRE_MANIFEST',
118
+ title: 'Agent: Dynamic require/import of manifest path from user input',
119
+ regex: /(?:require|import)\s*\(\s*(?:req\.|request\.|body\.|params\.|process\.env\.[A-Z_]{3,})\s*\)/gi,
120
+ severity: 'critical',
121
+ cwe: 'CWE-706',
122
+ owasp: 'ASI-10',
123
+ confidence: 'medium',
124
+ description: 'Manifest/module path resolved from external input — attacker can redirect load to a malicious file.',
125
+ fix: 'Use a hardcoded manifest path or validate against an allowlist of safe paths.',
126
+ },
127
+
128
+ // ── No changelog / audit trail ────────────────────────────────────────────
129
+ {
130
+ rule: 'AGENT_NO_CHANGELOG_REFERENCE',
131
+ title: 'Agent manifest: No changelog or audit trail reference',
132
+ regex: /^\s*\{\s*(?:(?:"(?:name|id|version|description)":[^}]{0,200})){2,}\}/ms,
133
+ severity: 'low',
134
+ cwe: 'CWE-778',
135
+ owasp: 'ASI-07',
136
+ confidence: 'low',
137
+ description: 'Agent manifest has no changelog, releaseNotes, or auditLog field — version changes cannot be audited.',
138
+ fix: 'Add a "changelog" or "releaseNotes" URL field to the manifest.',
139
+ },
140
+ ];
141
+
142
+ // =============================================================================
143
+ // STRUCTURAL CHECKS
144
+ // =============================================================================
145
+
146
+ const MANIFEST_EXTENSIONS = new Set(['.json', '.yaml', '.yml']);
147
+
148
+ function checkManifestFields(filePath, content) {
149
+ const findings = [];
150
+ let manifest;
151
+
152
+ try {
153
+ // Only handle JSON manifests for deep structural checks
154
+ if (!filePath.endsWith('.json')) return findings;
155
+ manifest = JSON.parse(content);
156
+ } catch {
157
+ return findings;
158
+ }
159
+
160
+ const basename = path.basename(filePath);
161
+ const isAgentManifest = /(?:agent[-_]manifest|agents|hermes\.config|openclaw)/i.test(basename);
162
+ if (!isAgentManifest) return findings;
163
+
164
+ // ── Missing integrity hash on tools array ─────────────────────────────────
165
+ const tools = manifest.tools || manifest.skills || [];
166
+ if (Array.isArray(tools)) {
167
+ for (const tool of tools) {
168
+ const remoteRef = (tool.url || tool.source || '');
169
+ const isRemote = /^https?:\/\//i.test(remoteRef);
170
+ if (isRemote && !tool.integrity && !tool.hash && !tool.checksum) {
171
+ findings.push(createFinding({
172
+ rule: 'AGENT_TOOL_NO_INTEGRITY',
173
+ title: `Tool "${tool.name || tool.id || '?'}" has remote source but no integrity hash`,
174
+ severity: 'high',
175
+ file: filePath,
176
+ line: 0,
177
+ snippet: JSON.stringify(tool).slice(0, 120),
178
+ cwe: 'CWE-494',
179
+ owasp: 'ASI-10',
180
+ confidence: 'high',
181
+ description: `Tool "${tool.name || tool.id}" is loaded from a remote URL without an integrity constraint — can be silently replaced.`,
182
+ fix: 'Add integrity: "sha256-<base64>" to each remotely-sourced tool definition.',
183
+ category: 'supply-chain',
184
+ }));
185
+ }
186
+ }
187
+ }
188
+
189
+ // ── Agent version unpinned (no exact semver) ──────────────────────────────
190
+ const version = manifest.version || manifest.agentVersion;
191
+ if (version && /[\^~*]/.test(String(version))) {
192
+ findings.push(createFinding({
193
+ rule: 'AGENT_MANIFEST_UNPINNED',
194
+ title: 'Agent manifest version uses mutable range',
195
+ severity: 'high',
196
+ file: filePath,
197
+ line: 0,
198
+ snippet: `version: "${version}"`,
199
+ cwe: 'CWE-1104',
200
+ owasp: 'ASI-10',
201
+ confidence: 'high',
202
+ description: 'Manifest version field uses a range specifier — future installs may receive a different agent.',
203
+ fix: 'Use an exact version string without ^ or ~.',
204
+ category: 'supply-chain',
205
+ }));
206
+ }
207
+
208
+ // ── Hermes-specific: missing hermes version pin ───────────────────────────
209
+ const hermesVersion = manifest.hermes?.version || manifest.hermesVersion || manifest.dependencies?.['@nousresearch/hermes-agent'];
210
+ if (hermesVersion && /[\^~*><=]/.test(String(hermesVersion))) {
211
+ findings.push(createFinding({
212
+ rule: 'HERMES_AGENT_UNPINNED',
213
+ title: 'hermes-agent dependency not pinned in manifest',
214
+ severity: 'high',
215
+ file: filePath,
216
+ line: 0,
217
+ snippet: `hermes-agent: "${hermesVersion}"`,
218
+ cwe: 'CWE-1104',
219
+ owasp: 'ASI-10',
220
+ confidence: 'high',
221
+ description: 'The hermes-agent version is not pinned — a compromised minor release would affect all agents using this manifest.',
222
+ fix: 'Pin to exact version: "@nousresearch/hermes-agent": "x.y.z"',
223
+ category: 'supply-chain',
224
+ }));
225
+ }
226
+
227
+ // ── No signature/provenance field at all ─────────────────────────────────
228
+ const hasProvenance = manifest.signature || manifest.provenance || manifest.attestation || manifest.integrity;
229
+ if (!hasProvenance && isAgentManifest) {
230
+ findings.push(createFinding({
231
+ rule: 'AGENT_NO_PROVENANCE',
232
+ title: 'Agent manifest has no signature, provenance, or attestation field',
233
+ severity: 'medium',
234
+ file: filePath,
235
+ line: 0,
236
+ snippet: `(top-level keys: ${Object.keys(manifest).join(', ')})`,
237
+ cwe: 'CWE-345',
238
+ owasp: 'ASI-10',
239
+ confidence: 'high',
240
+ description: 'No attestation metadata found in manifest — cannot verify the manifest was produced by the expected pipeline.',
241
+ fix: 'Add a "provenance" or "signature" field referencing a SLSA attestation or signed hash.',
242
+ category: 'supply-chain',
243
+ }));
244
+ }
245
+
246
+ return findings;
247
+ }
248
+
249
+ // =============================================================================
250
+ // AGENT
251
+ // =============================================================================
252
+
253
+ export class AgentAttestationAgent extends BaseAgent {
254
+ constructor() {
255
+ super('AgentAttestationAgent', 'Agent Attestation & Supply Chain — unsigned manifests, unpinned versions, missing provenance', 'supply-chain');
256
+ }
257
+
258
+ shouldRun() { return true; }
259
+
260
+ async analyze(context) {
261
+ const { files = [], rootPath } = context;
262
+ const findings = [];
263
+
264
+ for (const file of files) {
265
+ const basename = path.basename(file);
266
+ const ext = path.extname(file);
267
+
268
+ // Only scan relevant files
269
+ const isManifest = MANIFEST_EXTENSIONS.has(ext) && /(?:agent|manifest|hermes|openclaw|config)/i.test(basename);
270
+ const isPackageJson = basename === 'package.json';
271
+ const isSourceWithLoad = /\.[jt]s$/.test(ext);
272
+
273
+ if (!isManifest && !isPackageJson && !isSourceWithLoad) continue;
274
+
275
+ let content;
276
+ try {
277
+ content = fs.readFileSync(file, 'utf-8');
278
+ } catch {
279
+ continue;
280
+ }
281
+
282
+ // Skip huge source files that are unlikely to contain manifest loading
283
+ if (isSourceWithLoad && content.length > 200_000) continue;
284
+
285
+ // Pattern-based checks
286
+ const lines = content.split('\n');
287
+ for (let i = 0; i < lines.length; i++) {
288
+ const line = lines[i];
289
+ for (const pattern of PATTERNS) {
290
+ pattern.regex.lastIndex = 0;
291
+ if (pattern.regex.test(line)) {
292
+ findings.push(createFinding({
293
+ rule: pattern.rule,
294
+ title: pattern.title,
295
+ severity: pattern.severity,
296
+ file,
297
+ line: i + 1,
298
+ snippet: line.trim().slice(0, 120),
299
+ cwe: pattern.cwe,
300
+ owasp: pattern.owasp,
301
+ confidence: pattern.confidence || 'medium',
302
+ description: pattern.description,
303
+ fix: pattern.fix,
304
+ category: 'supply-chain',
305
+ }));
306
+ }
307
+ }
308
+ }
309
+
310
+ // Structural checks on manifest files
311
+ if (isManifest || isPackageJson) {
312
+ findings.push(...checkManifestFields(file, content));
313
+ }
314
+ }
315
+
316
+ return findings;
317
+ }
318
+ }
@@ -37,11 +37,24 @@ const AGENT_RULES_FILES = [
37
37
  '.github/copilot-instructions.md',
38
38
  '.aider.conf.yml',
39
39
  '.continue/config.json',
40
+ // Gemini CLI
41
+ '.gemini/settings.json',
42
+ '.gemini/rules.md',
43
+ // Cody (Sourcegraph)
44
+ '.cody/config.json',
45
+ '.cody/context.json',
46
+ // Augment Code
47
+ '.augment/config.json',
40
48
  ];
41
49
 
42
50
  const AGENT_RULES_GLOBS = [
43
51
  '.cursor/rules/*.mdc',
44
52
  '.claude/commands/*.md',
53
+ // Gemini CLI commands
54
+ '.gemini/commands/*.md',
55
+ // Cody custom commands
56
+ '.cody/commands/*.md',
57
+ '.cody/rules/*.md',
45
58
  ];
46
59
 
47
60
  const OPENCLAW_FILES = [
@@ -84,6 +97,8 @@ const MEMORY_GLOBS = [
84
97
  '.claude/memory/**',
85
98
  '.cursor/memory/**',
86
99
  '.continue/memory/**',
100
+ '.gemini/memory/**',
101
+ '.cody/memory/**',
87
102
  ];
88
103
 
89
104
  // =============================================================================
@@ -215,6 +215,41 @@ const PATTERNS = [
215
215
  fix: 'Validate LLM structured output against a schema (Zod, Joi, Pydantic) before processing.',
216
216
  },
217
217
 
218
+ // ── Credential Isolation ─────────────────────────────────────────────────
219
+ {
220
+ rule: 'AGENT_ENV_FILE_ACCESS',
221
+ title: 'Agent: Reads .env Files Without Restriction',
222
+ regex: /(?:readFile|readFileSync|fs\.read|open)\s*\(\s*(?:.*\.env|.*process\.env|.*dotenv)/g,
223
+ severity: 'high',
224
+ cwe: 'CWE-522',
225
+ owasp: 'A02:2021',
226
+ confidence: 'medium',
227
+ description: 'Agent code reads .env files or loads dotenv directly. If the agent is compromised via prompt injection, all credentials in the environment file are exposed.',
228
+ fix: 'Inject only the specific environment variables the agent needs, not the entire .env file. Use scoped credential providers.',
229
+ },
230
+ {
231
+ rule: 'AGENT_NETWORK_AND_FILE_ACCESS',
232
+ title: 'Agent: Both Network and File Access (Exfiltration Risk)',
233
+ regex: /(?:tools|capabilities|functions)[\s\S]{0,800}(?:(?:fetch|http|request|axios|got|curl)[\s\S]{0,400}(?:read|file|fs|disk|path)|(?:read|file|fs|disk|path)[\s\S]{0,400}(?:fetch|http|request|axios|got|curl))/g,
234
+ severity: 'high',
235
+ cwe: 'CWE-200',
236
+ owasp: 'A01:2021',
237
+ confidence: 'medium',
238
+ description: 'Agent has tools for both file access and network requests. This is the exfiltration combination: read credentials from disk, send them over the network.',
239
+ fix: 'Separate file-reading agents from network-capable agents. If both are needed, add human-in-the-loop approval for network requests that follow file reads.',
240
+ },
241
+ {
242
+ rule: 'AGENT_ENV_FORWARDED_TO_TOOL',
243
+ title: 'Agent: Environment Variables Forwarded to Tool',
244
+ regex: /(?:process\.env|os\.environ|ENV)\s*(?:\[|\.)[\s\S]{0,100}(?:tool|function|action|invoke|call|execute)/g,
245
+ severity: 'high',
246
+ cwe: 'CWE-522',
247
+ owasp: 'A02:2021',
248
+ confidence: 'medium',
249
+ description: 'Environment variables (which may contain secrets from Stripe Projects or similar) are forwarded directly to agent tools. A compromised tool receives credentials.',
250
+ fix: 'Pass only the specific variables each tool needs. Never forward the entire process.env to tool invocations.',
251
+ },
252
+
218
253
  // ── Audit & Observability ────────────────────────────────────────────────
219
254
  {
220
255
  rule: 'AGENT_NO_AUDIT_LOG',