ship-safe 6.0.0 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
  <img src=".github/assets/logo%20ship%20safe.png" alt="Ship Safe Logo" width="180" />
3
3
  </p>
4
4
  <p align="center"><strong>AI-powered application security platform for developers.</strong></p>
5
+ <p align="center"><a href="https://shipsafecli.com">shipsafecli.com</a></p>
5
6
 
6
7
  <p align="center">
7
8
  <a href="https://www.npmjs.com/package/ship-safe"><img src="https://badge.fury.io/js/ship-safe.svg" alt="npm version" /></a>
@@ -14,32 +15,47 @@
14
15
 
15
16
  ---
16
17
 
17
- 16 security agents. 80+ attack classes. One command.
18
+ 18 security agents. 80+ attack classes. One command.
18
19
 
19
- **Ship Safe v5.0** is an AI-powered security platform that runs 16 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, and more. LLM-powered deep analysis verifies exploitability of critical findings. Secrets verification probes provider APIs to check if leaked keys are still active. A dedicated CI command (`ship-safe ci`) integrates into any pipeline with threshold-based gating and SARIF output.
20
+ **Ship Safe v6.1.1** 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
+
22
+ **v6.1.1 highlights:** Supply chain hardening against the [March 2026 Trivy/CanisterWorm attack chain](https://shipsafecli.com/blog/supply-chain-attacks-2026-how-we-hardened-ship-safe). All GitHub Actions SHA-pinned, `postinstall` scripts disabled in CI, OIDC trusted publishing with provenance, CODEOWNERS on critical paths.
23
+
24
+ [Documentation](https://shipsafecli.com/docs) | [Blog](https://shipsafecli.com/blog) | [Pricing](https://shipsafecli.com/pricing)
20
25
 
21
26
  ---
22
27
 
23
28
  ## Quick Start
24
29
 
25
30
  ```bash
26
- # Full security audit — secrets + 16 agents + deps + remediation plan
31
+ # Full security audit — secrets + 18 agents + deps + remediation plan
27
32
  npx ship-safe audit .
28
33
 
29
34
  # LLM-powered deep analysis (Anthropic, OpenAI, Google, Ollama)
30
35
  npx ship-safe audit . --deep
31
36
 
32
- # Red team scan only (16 agents, 80+ attack classes)
37
+ # Red team scan only (18 agents, 80+ attack classes)
33
38
  npx ship-safe red-team .
34
39
 
40
+ # Scan only changed files (fast pre-commit & PR scanning)
41
+ npx ship-safe diff
42
+ npx ship-safe diff --staged
43
+
44
+ # Fun emoji security grade with shareable badge
45
+ npx ship-safe vibe-check .
46
+
47
+ # Compare your score against industry averages
48
+ npx ship-safe benchmark .
49
+
35
50
  # Quick secret scan
36
51
  npx ship-safe scan .
37
52
 
38
53
  # Security health score (0-100)
39
54
  npx ship-safe score .
40
55
 
41
- # CI/CD pipeline mode — compact output, exit codes, SARIF
56
+ # CI/CD pipeline mode — compact output, exit codes, PR comments
42
57
  npx ship-safe ci .
58
+ npx ship-safe ci . --github-pr
43
59
 
44
60
  # Accept current findings, only report regressions
45
61
  npx ship-safe baseline .
@@ -66,11 +82,11 @@ npx ship-safe audit .
66
82
 
67
83
  ```
68
84
  ════════════════════════════════════════════════════════════
69
- Ship Safe v5.0 — Full Security Audit
85
+ Ship Safe v6.0 — Full Security Audit
70
86
  ════════════════════════════════════════════════════════════
71
87
 
72
88
  [Phase 1/4] Scanning for secrets... ✔ 49 found
73
- [Phase 2/4] Running 16 security agents... ✔ 103 findings
89
+ [Phase 2/4] Running 18 security agents... ✔ 103 findings
74
90
  [Phase 3/4] Auditing dependencies... ✔ 44 CVEs
75
91
  [Phase 4/4] Computing security score... ✔ 25/100 F
76
92
 
@@ -97,14 +113,15 @@ npx ship-safe audit .
97
113
 
98
114
  **What it runs:**
99
115
  1. **Secret scan** — 50+ patterns with entropy scoring (API keys, passwords, tokens)
100
- 2. **16 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, mobile, git history, CI/CD, API)
101
- 3. **Dependency audit** — npm/pip/bundler CVE scanning
116
+ 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)
117
+ 3. **Dependency audit** — npm/pip/bundler CVE scanning with EPSS exploit probability scores
102
118
  4. **Secrets verification** — probes provider APIs (GitHub, Stripe, OpenAI, etc.) to check if leaked keys are still active
103
119
  5. **Deep analysis** — LLM-powered taint analysis verifies exploitability of critical/high findings (optional)
104
- 6. **Score computation** — confidence-weighted scoring across 8 categories (0-100, A-F)
120
+ 6. **Score computation** — OWASP 2025 weighted scoring across 8 categories (0-100, A-F)
105
121
  7. **Context-aware confidence tuning** — downgrades findings in test files, docs, and comments
106
- 8. **Remediation plan** — prioritized fix list grouped by severity
107
- 9. **HTML report** — standalone dark-themed report with code context
122
+ 8. **Compliance mapping** — maps findings to SOC 2 Type II, ISO 27001:2022, and NIST AI Risk Management Framework controls
123
+ 9. **Remediation plan** — prioritized fix list grouped by severity
124
+ 10. **Interactive HTML report** — standalone dark-themed report with severity filtering, search, collapsible findings, compliance summary, and click-to-copy ignore annotations
108
125
 
109
126
  **Flags:**
110
127
  - `--json` — structured JSON output (clean for piping)
@@ -127,21 +144,24 @@ npx ship-safe audit .
127
144
 
128
145
  ---
129
146
 
130
- ## 16 Security Agents
147
+ ## 18 Security Agents
131
148
 
132
149
  | Agent | Category | What It Detects |
133
150
  |-------|----------|-----------------|
134
151
  | **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 |
135
152
  | **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 |
136
153
  | **SSRFProber** | SSRF | User input in fetch/axios, cloud metadata endpoints, internal IPs, redirect following |
137
- | **SupplyChainAudit** | Supply Chain | Typosquatting (Levenshtein distance), git/URL dependencies, wildcard versions, suspicious install scripts, dependency confusion, scoped packages without registry pinning |
154
+ | **SupplyChainAudit** | Supply Chain | Typosquatting (Levenshtein distance), git/URL dependencies, wildcard versions, suspicious install scripts, dependency confusion, lockfile integrity |
138
155
  | **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 |
139
156
  | **SupabaseRLSAgent** | Auth | Supabase Row Level Security — `service_role` key in client code, `CREATE TABLE` without RLS, anon key inserts, unprotected storage operations |
140
157
  | **LLMRedTeam** | AI/LLM | OWASP LLM Top 10 — prompt injection, excessive agency, system prompt leakage, unbounded consumption, RAG poisoning |
141
- | **MCPSecurityAgent** | AI/LLM | MCP server security — unvalidated tool inputs, missing auth, excessive permissions, tool poisoning |
158
+ | **MCPSecurityAgent** | AI/LLM | MCP server security — unvalidated tool inputs, missing auth, excessive permissions, tool poisoning, typosquatting detection, over-permissioned tools, shadow config discovery |
142
159
  | **AgenticSecurityAgent** | AI/LLM | OWASP Agentic AI Top 10 — agent hijacking, privilege escalation, unsafe code execution, memory poisoning |
143
160
  | **RAGSecurityAgent** | AI/LLM | RAG pipeline security — unvalidated embeddings, context injection, document poisoning, vector DB access control |
144
161
  | **PIIComplianceAgent** | Compliance | PII detection — SSNs, credit cards, emails, phone numbers in source code, logs, and configs |
162
+ | **VibeCodingAgent** | Code Vulns | AI-generated code patterns — no input validation, empty catch blocks, hardcoded secrets, disabled security features, TODO-auth patterns |
163
+ | **ExceptionHandlerAgent** | Code Vulns | OWASP A10:2025 — empty catch blocks, unhandled promise rejections, missing React error boundaries, leaked stack traces, generic catch-all without rethrow |
164
+ | **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, encoded/obfuscated payloads, data exfiltration instructions, agent memory poisoning |
145
165
  | **MobileScanner** | Mobile | OWASP Mobile Top 10 2024 — insecure storage, WebView JS injection, HTTP endpoints, excessive permissions, debug mode |
146
166
  | **GitHistoryScanner** | Secrets | Leaked secrets in git commit history (checks if still active in working tree) |
147
167
  | **CICDScanner** | CI/CD | OWASP CI/CD Top 10 — pipeline poisoning, unpinned actions, secret logging, self-hosted runners, script injection |
@@ -160,7 +180,7 @@ npx ship-safe audit .
160
180
  # Full audit with remediation plan + HTML report
161
181
  npx ship-safe audit .
162
182
 
163
- # Red team: 16 agents, 80+ attack classes
183
+ # Red team: 18 agents, 80+ attack classes
164
184
  npx ship-safe red-team .
165
185
  npx ship-safe red-team . --agents injection,auth # Run specific agents
166
186
  npx ship-safe red-team . --html report.html # HTML report
@@ -209,6 +229,28 @@ npx ship-safe baseline --diff
209
229
  npx ship-safe baseline --clear
210
230
  ```
211
231
 
232
+ ### Diff Scanning
233
+
234
+ ```bash
235
+ # Scan only changed files (fast pre-commit & PR scanning)
236
+ npx ship-safe diff # All uncommitted changes
237
+ npx ship-safe diff --staged # Only staged changes
238
+ npx ship-safe diff HEAD~3 # Changes in last 3 commits
239
+ npx ship-safe diff --json # JSON output
240
+ ```
241
+
242
+ ### Vibe Check & Benchmark
243
+
244
+ ```bash
245
+ # Fun emoji security grade
246
+ npx ship-safe vibe-check .
247
+ npx ship-safe vibe-check . --badge # Generate shields.io README badge
248
+
249
+ # Compare your score against industry averages (OWASP, Synopsys, Snyk)
250
+ npx ship-safe benchmark .
251
+ npx ship-safe benchmark . --json # JSON output
252
+ ```
253
+
212
254
  ### CI/CD Pipeline
213
255
 
214
256
  ```bash
@@ -217,6 +259,7 @@ npx ship-safe ci .
217
259
  npx ship-safe ci . --threshold 80 # Custom passing score
218
260
  npx ship-safe ci . --fail-on critical # Fail on severity
219
261
  npx ship-safe ci . --sarif out.sarif # SARIF for GitHub
262
+ npx ship-safe ci . --github-pr # Post results as PR comment
220
263
  ```
221
264
 
222
265
  ### Deep Analysis & Verification
@@ -238,6 +281,52 @@ npx ship-safe audit . --verify
238
281
  npx ship-safe doctor
239
282
  ```
240
283
 
284
+ ### OpenClaw Security
285
+
286
+ ```bash
287
+ # Focused OpenClaw security scan
288
+ npx ship-safe openclaw .
289
+
290
+ # Auto-harden OpenClaw configs (0.0.0.0→127.0.0.1, add auth, ws→wss)
291
+ npx ship-safe openclaw . --fix
292
+
293
+ # Red team: simulate ClawJacked, prompt injection, data exfil attacks
294
+ npx ship-safe openclaw . --red-team
295
+
296
+ # CI preflight — exit non-zero on critical findings
297
+ npx ship-safe openclaw . --preflight
298
+
299
+ # Scan a skill before installing it
300
+ npx ship-safe scan-skill https://clawhub.io/skills/some-skill
301
+ npx ship-safe scan-skill ./local-skill.json
302
+ npx ship-safe scan-skill --all # Scan all skills from openclaw.json
303
+
304
+ # Generate hardened OpenClaw config
305
+ npx ship-safe init --openclaw
306
+
307
+ # Generate Agent Bill of Materials (CycloneDX 1.5)
308
+ npx ship-safe abom .
309
+ ```
310
+
311
+ ### Threat Intelligence
312
+
313
+ ```bash
314
+ # Update threat intel feed (ClawHavoc IOCs, malicious skills, config signatures)
315
+ npx ship-safe update-intel
316
+
317
+ # Ships with offline-first seed data — no internet required for scanning
318
+ ```
319
+
320
+ ### Defensive Hooks
321
+
322
+ ```bash
323
+ # Install Claude Code defensive hooks (blocks curl|bash, exfil domains, rm -rf /)
324
+ npx ship-safe guard --generate-hooks
325
+
326
+ # Watch agent config files for drift (.cursorrules, CLAUDE.md, openclaw.json)
327
+ npx ship-safe watch . --configs
328
+ ```
329
+
241
330
  ### Infrastructure Commands
242
331
 
243
332
  ```bash
@@ -275,7 +364,7 @@ claude plugin add github:asamassekou10/ship-safe
275
364
 
276
365
  | Command | Description |
277
366
  |---------|-------------|
278
- | `/ship-safe` | Full security audit — 16 agents, remediation plan, auto-fix |
367
+ | `/ship-safe` | Full security audit — 18 agents, remediation plan, auto-fix |
279
368
  | `/ship-safe-scan` | Quick scan for leaked secrets |
280
369
  | `/ship-safe-score` | Security health score (0-100) |
281
370
  | `/ship-safe-deep` | LLM-powered deep taint analysis |
@@ -344,12 +433,14 @@ Starts at 100. Each finding deducts points by severity and category, weighted by
344
433
  |----------|--------|----------|------|--------|-----|
345
434
  | Secrets | 15% | -25 | -15 | -5 | -15 |
346
435
  | Code Vulnerabilities | 15% | -20 | -10 | -3 | -15 |
347
- | Dependencies | 15% | -20 | -10 | -5 | -15 |
436
+ | Dependencies | 13% | -20 | -10 | -5 | -13 |
348
437
  | Auth & Access Control | 15% | -20 | -10 | -3 | -15 |
349
- | Configuration | 10% | -15 | -8 | -3 | -10 |
350
- | Supply Chain | 10% | -15 | -8 | -3 | -10 |
438
+ | Configuration | 8% | -15 | -8 | -3 | -8 |
439
+ | Supply Chain | 12% | -15 | -8 | -3 | -12 |
351
440
  | API Security | 10% | -15 | -8 | -3 | -10 |
352
- | AI/LLM Security | 10% | -15 | -8 | -3 | -10 |
441
+ | AI/LLM Security | 12% | -15 | -8 | -3 | -12 |
442
+
443
+ *Weights aligned with OWASP Top 10 2025 risk rankings.*
353
444
 
354
445
  **Grades:** A (90-100), B (75-89), C (60-74), D (40-59), F (0-39)
355
446
 
@@ -411,7 +502,7 @@ jobs:
411
502
  - uses: actions/checkout@v4
412
503
 
413
504
  - name: Security gate
414
- run: npx ship-safe ci . --threshold 75 --sarif results.sarif
505
+ run: npx ship-safe ci . --threshold 75 --sarif results.sarif --github-pr
415
506
 
416
507
  - uses: github/codeql-action/upload-sarif@v3
417
508
  if: always()
@@ -470,6 +561,49 @@ Manual security audits: launch-day checklist, framework-specific guides.
470
561
 
471
562
  ---
472
563
 
564
+ ## Add a Security Badge to Your README
565
+
566
+ Show the world your project is secure. After running `npx ship-safe audit .` or `npx ship-safe vibe-check . --badge`, add one of these to your README:
567
+
568
+ ```markdown
569
+ <!-- Replace GRADE and COLOR with your results -->
570
+ [![Ship Safe](https://img.shields.io/badge/Ship_Safe-A+-22c55e)](https://shipsafecli.com)
571
+ ```
572
+
573
+ | Grade | Badge |
574
+ |-------|-------|
575
+ | A+ | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-A+-22c55e)](https://shipsafecli.com)` |
576
+ | A | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-A-22c55e)](https://shipsafecli.com)` |
577
+ | B | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-B-06b6d4)](https://shipsafecli.com)` |
578
+ | C | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-C-eab308)](https://shipsafecli.com)` |
579
+ | D | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-D-ef4444)](https://shipsafecli.com)` |
580
+ | F | `[![Ship Safe](https://img.shields.io/badge/Ship_Safe-F-dc2626)](https://shipsafecli.com)` |
581
+
582
+ ---
583
+
584
+ ## Supply Chain Hardening
585
+
586
+ Ship Safe practices what it preaches. Our own supply chain is hardened against the [2026 Trivy/CanisterWorm attack chain](https://shipsafecli.com/blog/supply-chain-attacks-2026-how-we-hardened-ship-safe):
587
+
588
+ | Defense | What It Blocks |
589
+ |---------|---------------|
590
+ | All GitHub Actions pinned to full commit SHAs | Tag repointing (Trivy-style) |
591
+ | `permissions: contents: read` in CI | Excessive token scope |
592
+ | `npm ci --ignore-scripts` in all pipelines | CanisterWorm postinstall propagation |
593
+ | OIDC trusted publishing with provenance | Stolen npm token publishing |
594
+ | CODEOWNERS on `action.yml`, `.github/`, `package.json` | Unauthorized changes to critical paths |
595
+ | Strict `files` allowlist in package.json | Accidental inclusion of secrets/configs |
596
+ | Self-scanning with ship-safe in CI | Malicious code injection |
597
+ | 5 direct dependencies | Minimal transitive attack surface |
598
+
599
+ Verify provenance on any Ship Safe release:
600
+
601
+ ```bash
602
+ npm audit signatures
603
+ ```
604
+
605
+ ---
606
+
473
607
  ## Contributing
474
608
 
475
609
  1. Fork the repo
@@ -504,4 +638,4 @@ MIT - Use it, share it, secure your stuff.
504
638
 
505
639
  ---
506
640
 
507
- **Ship fast. Ship safe.**
641
+ **Ship fast. Ship safe.** — [shipsafecli.com](https://shipsafecli.com)
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Agent Bill of Materials (ABOM) Generator
3
+ * ==========================================
4
+ *
5
+ * Generates an Agent-focused BOM in CycloneDX 1.5 format.
6
+ * Lists all AI agent components: MCP servers, OpenClaw skills,
7
+ * agent config files, LLM providers.
8
+ *
9
+ * This complements the SBOMGenerator (software dependencies)
10
+ * with agent-specific component inventory for compliance and
11
+ * supply chain visibility.
12
+ */
13
+
14
+ import fs from 'fs';
15
+ import path from 'path';
16
+ import fg from 'fast-glob';
17
+
18
+ // Agent config files to discover (from AgentConfigScanner)
19
+ const AGENT_CONFIG_FILES = [
20
+ '.cursorrules', '.windsurfrules', 'CLAUDE.md', 'AGENTS.md',
21
+ '.github/copilot-instructions.md', '.aider.conf.yml', '.continue/config.json',
22
+ ];
23
+
24
+ const MCP_CONFIG_FILES = [
25
+ 'mcp.json', '.cursor/mcp.json', '.vscode/mcp.json',
26
+ 'claude_desktop_config.json', '.claude/settings.json',
27
+ ];
28
+
29
+ const OPENCLAW_FILES = ['openclaw.json', 'openclaw.config.json', 'clawhub.json'];
30
+
31
+ const LLM_ENV_VARS = [
32
+ 'OPENAI_API_KEY', 'ANTHROPIC_API_KEY', 'GOOGLE_AI_API_KEY',
33
+ 'AZURE_OPENAI_API_KEY', 'OLLAMA_HOST', 'GROQ_API_KEY',
34
+ 'MISTRAL_API_KEY', 'COHERE_API_KEY',
35
+ ];
36
+
37
+ export class ABOMGenerator {
38
+ /**
39
+ * Generate a CycloneDX 1.5 ABOM.
40
+ * @param {string} rootPath — Project root directory
41
+ * @returns {object} — CycloneDX JSON with agent components
42
+ */
43
+ generate(rootPath) {
44
+ const components = [];
45
+ let componentIndex = 0;
46
+
47
+ // ── MCP Servers ──────────────────────────────────────────────────────────
48
+ for (const rel of MCP_CONFIG_FILES) {
49
+ const full = path.join(rootPath, rel);
50
+ if (!fs.existsSync(full)) continue;
51
+ try {
52
+ const data = JSON.parse(fs.readFileSync(full, 'utf-8'));
53
+ const servers = data.mcpServers || data.servers || {};
54
+ for (const [name, config] of Object.entries(servers)) {
55
+ components.push({
56
+ 'bom-ref': `agent-${componentIndex++}`,
57
+ type: 'framework',
58
+ name,
59
+ version: config.version || 'unknown',
60
+ description: `MCP server from ${rel}`,
61
+ purl: config.command ? `pkg:mcp/${encodeURIComponent(name)}` : undefined,
62
+ properties: [
63
+ { name: 'agent:type', value: 'mcp-server' },
64
+ { name: 'agent:source', value: rel },
65
+ { name: 'agent:command', value: config.command || 'N/A' },
66
+ { name: 'agent:transport', value: config.transport || 'stdio' },
67
+ ],
68
+ });
69
+ }
70
+ } catch { /* skip */ }
71
+ }
72
+
73
+ // ── OpenClaw Skills ──────────────────────────────────────────────────────
74
+ for (const rel of OPENCLAW_FILES) {
75
+ const full = path.join(rootPath, rel);
76
+ if (!fs.existsSync(full)) continue;
77
+ try {
78
+ const data = JSON.parse(fs.readFileSync(full, 'utf-8'));
79
+ const skills = data.skills || [];
80
+ for (const skill of skills) {
81
+ const skillName = typeof skill === 'string' ? skill : skill.name || skill.id || 'unnamed';
82
+ const skillSource = typeof skill === 'object' ? (skill.source || skill.url || 'local') : 'config';
83
+ components.push({
84
+ 'bom-ref': `agent-${componentIndex++}`,
85
+ type: 'library',
86
+ name: skillName,
87
+ version: (typeof skill === 'object' ? skill.version : null) || 'unknown',
88
+ description: `OpenClaw skill from ${rel}`,
89
+ purl: `pkg:openclaw/${encodeURIComponent(skillName)}`,
90
+ properties: [
91
+ { name: 'agent:type', value: 'openclaw-skill' },
92
+ { name: 'agent:source', value: skillSource },
93
+ { name: 'agent:verified', value: String(typeof skill === 'object' ? !!skill.verified : false) },
94
+ ],
95
+ });
96
+ }
97
+
98
+ // Record OpenClaw config itself
99
+ components.push({
100
+ 'bom-ref': `agent-${componentIndex++}`,
101
+ type: 'data',
102
+ name: `openclaw-config:${rel}`,
103
+ version: data.version || '1.0.0',
104
+ description: `OpenClaw gateway configuration`,
105
+ properties: [
106
+ { name: 'agent:type', value: 'openclaw-config' },
107
+ { name: 'agent:host', value: data.host || 'localhost' },
108
+ { name: 'agent:auth', value: data.auth ? 'enabled' : 'disabled' },
109
+ ],
110
+ });
111
+ } catch { /* skip */ }
112
+ }
113
+
114
+ // ── Agent Config Files ───────────────────────────────────────────────────
115
+ for (const rel of AGENT_CONFIG_FILES) {
116
+ const full = path.join(rootPath, rel);
117
+ if (!fs.existsSync(full)) continue;
118
+ try {
119
+ const stat = fs.statSync(full);
120
+ components.push({
121
+ 'bom-ref': `agent-${componentIndex++}`,
122
+ type: 'data',
123
+ name: `agent-config:${rel}`,
124
+ version: stat.mtime.toISOString().split('T')[0],
125
+ description: `AI agent instruction file`,
126
+ properties: [
127
+ { name: 'agent:type', value: 'agent-rules' },
128
+ { name: 'agent:file', value: rel },
129
+ { name: 'agent:size', value: String(stat.size) },
130
+ ],
131
+ });
132
+ } catch { /* skip */ }
133
+ }
134
+
135
+ // ── Glob-based config files ──────────────────────────────────────────────
136
+ try {
137
+ const globs = ['.cursor/rules/*.mdc', '.openclaw/**/*.json', '.claude/commands/*.md'];
138
+ const found = fg.sync(globs, { cwd: rootPath, absolute: true, dot: true });
139
+ for (const full of found) {
140
+ const rel = path.relative(rootPath, full).replace(/\\/g, '/');
141
+ try {
142
+ const stat = fs.statSync(full);
143
+ components.push({
144
+ 'bom-ref': `agent-${componentIndex++}`,
145
+ type: 'data',
146
+ name: `agent-config:${rel}`,
147
+ version: stat.mtime.toISOString().split('T')[0],
148
+ description: `AI agent configuration file`,
149
+ properties: [
150
+ { name: 'agent:type', value: 'agent-config' },
151
+ { name: 'agent:file', value: rel },
152
+ ],
153
+ });
154
+ } catch { /* skip */ }
155
+ }
156
+ } catch { /* skip */ }
157
+
158
+ // ── LLM Providers ────────────────────────────────────────────────────────
159
+ for (const envVar of LLM_ENV_VARS) {
160
+ if (process.env[envVar]) {
161
+ const provider = envVar.replace(/_API_KEY$/, '').replace(/_HOST$/, '').toLowerCase();
162
+ components.push({
163
+ 'bom-ref': `agent-${componentIndex++}`,
164
+ type: 'service',
165
+ name: `llm-provider:${provider}`,
166
+ version: 'detected',
167
+ description: `LLM provider detected via ${envVar} environment variable`,
168
+ properties: [
169
+ { name: 'agent:type', value: 'llm-provider' },
170
+ { name: 'agent:env-var', value: envVar },
171
+ { name: 'agent:key-present', value: 'true' },
172
+ ],
173
+ });
174
+ }
175
+ }
176
+
177
+ // ── Build CycloneDX BOM ──────────────────────────────────────────────────
178
+ return {
179
+ bomFormat: 'CycloneDX',
180
+ specVersion: '1.5',
181
+ serialNumber: `urn:uuid:${this._uuid()}`,
182
+ version: 1,
183
+ metadata: {
184
+ timestamp: new Date().toISOString(),
185
+ tools: [{ vendor: 'ship-safe', name: 'ship-safe-abom', version: '6.1.0' }],
186
+ component: this._getProjectMeta(rootPath),
187
+ lifecycles: [{ phase: 'build' }],
188
+ },
189
+ components,
190
+ compositions: [{
191
+ aggregate: 'incomplete',
192
+ assemblies: components.map(c => c['bom-ref']),
193
+ }],
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Generate ABOM and write to file.
199
+ */
200
+ generateToFile(rootPath, outputPath) {
201
+ const bom = this.generate(rootPath);
202
+ fs.writeFileSync(outputPath, JSON.stringify(bom, null, 2));
203
+ return outputPath;
204
+ }
205
+
206
+ _getProjectMeta(rootPath) {
207
+ try {
208
+ const pkgPath = path.join(rootPath, 'package.json');
209
+ if (fs.existsSync(pkgPath)) {
210
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
211
+ return { type: 'application', name: pkg.name || path.basename(rootPath), version: pkg.version || '0.0.0' };
212
+ }
213
+ } catch { /* skip */ }
214
+ return { type: 'application', name: path.basename(rootPath), version: '0.0.0' };
215
+ }
216
+
217
+ _uuid() {
218
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
219
+ const r = Math.random() * 16 | 0;
220
+ return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
221
+ });
222
+ }
223
+ }
224
+
225
+ export default ABOMGenerator;