clawmoat 0.8.0 → 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/.dockerignore +9 -0
- package/CHANGELOG.md +18 -0
- package/DEMO.md +87 -0
- package/Dockerfile +5 -18
- package/README.md +232 -8
- package/THREAT_MODEL.md +129 -0
- package/agent/README.md +131 -0
- package/agent/index.js +471 -0
- package/agent/install-service.sh +94 -0
- package/agent/openclaw-hook.js +453 -0
- package/agent/provider-setup.js +649 -0
- package/agent/setup.js +274 -0
- package/assets/BADGE-USAGE.md +20 -0
- package/assets/clawmoat-badge.svg +21 -0
- package/bin/clawmoat.js +468 -111
- package/docs/affiliates/dashboard.html +124 -0
- package/docs/affiliates/index.html +236 -0
- package/docs/agent-install.html +183 -0
- package/docs/ai-agent-security-scanner.html +10 -6
- package/docs/badge/index.html +149 -0
- package/docs/badge/scanning.svg +23 -0
- package/docs/blog/386-malicious-skills.html +11 -4
- package/docs/blog/40000-exposed-openclaw-instances.html +11 -4
- package/docs/blog/agent-trust-protocol.html +5 -4
- package/docs/blog/ai-agent-earns-commissions.html +230 -0
- package/docs/blog/bugmageddon-agent-firewall.html +174 -0
- package/docs/blog/calculator-math.html +180 -0
- package/docs/blog/clawmoat-vs-llamafirewall-nemo-guardrails.html +10 -4
- package/docs/blog/host-guardian-launch.html +18 -8
- package/docs/blog/ibm-experts-agent-runtime-protection.html +15 -6
- package/docs/blog/index.html +67 -9
- package/docs/blog/langchain-security-tutorial.html +18 -8
- package/docs/blog/mcp-30-cves-security-crisis.html +11 -4
- package/docs/blog/meta-researcher-rogue-agent.html +201 -0
- package/docs/blog/microsoft-openclaw-workstation-security.html +5 -4
- package/docs/blog/nist-ai-agent-standards-clawmoat.html +16 -8
- package/docs/blog/oasis-websocket-hijack.html +11 -4
- package/docs/blog/ollama-openclaw-security.html +10 -4
- package/docs/blog/openclaw-enterprise-readiness-claw10.html +5 -4
- package/docs/blog/openclaw-security-reckoning-2026.html +11 -4
- package/docs/blog/owasp-agentic-ai-top10.html +18 -8
- package/docs/blog/securing-ai-agents.html +18 -8
- package/docs/blog/supply-chain-agents.html +18 -8
- package/docs/business/index.html +11 -16
- package/docs/business/install.html +21 -7
- package/docs/checklist.html +10 -4
- package/docs/compare/index.html +122 -0
- package/docs/compare/lakera/index.html +62 -0
- package/docs/compare/llm-guard/index.html +49 -0
- package/docs/compare/snyk-agent-scan/index.html +63 -0
- package/docs/compare.html +10 -6
- package/docs/dashboard/index.html +520 -0
- package/docs/finance/index.html +9 -6
- package/docs/guides/business-deployment.html +770 -0
- package/docs/hall-of-fame.html +11 -5
- package/docs/index.html +266 -137
- package/docs/integrations/langchain.html +14 -6
- package/docs/integrations/openai.html +14 -6
- package/docs/integrations/openclaw.html +55 -7
- package/docs/plans/2026-03-26-threat-intel-api.md +255 -0
- package/docs/plans/2026-04-14-bugmageddon-marketing-pack.md +329 -0
- package/docs/plans/2026-04-14-clawmoat-v1-bugmageddon.md +248 -0
- package/docs/plans/2026-04-14-v1-release-update.md +91 -0
- package/docs/plans/2026-04-19-supabase-audit.md +68 -0
- package/docs/plans/2026-05-12-sales-push.md +303 -0
- package/docs/playground/index.html +893 -0
- package/docs/playground.html +4 -7
- package/docs/rfcs/defense-in-depth.md +467 -0
- package/docs/scan/index.html +156 -12
- package/docs/services/case-study.html +255 -0
- package/docs/services/downloads/install-openclaw.bat +45 -0
- package/docs/services/downloads/install-openclaw.command +38 -0
- package/docs/services/downloads/install-openclaw.sh +38 -0
- package/docs/services/get-started.html +165 -0
- package/docs/services/index.html +598 -0
- package/docs/services/multi-agent-security.html +284 -0
- package/docs/services/one-pager.html +99 -0
- package/docs/services/pitch-deck.html +229 -0
- package/docs/services/roi-calculator.html +258 -0
- package/docs/sitemap.xml +62 -2
- package/docs/support/index.html +12 -1
- package/docs/templates/customer-service/HEARTBEAT.md +61 -0
- package/docs/templates/customer-service/MEMORY.md +89 -0
- package/docs/templates/customer-service/SOUL.md +41 -0
- package/docs/templates/customer-service/USER.md +56 -0
- package/docs/templates/executive/HEARTBEAT.md +86 -0
- package/docs/templates/executive/MEMORY.md +92 -0
- package/docs/templates/executive/SOUL.md +44 -0
- package/docs/templates/executive/USER.md +62 -0
- package/docs/templates/finance/HEARTBEAT.md +58 -0
- package/docs/templates/finance/MEMORY.md +87 -0
- package/docs/templates/finance/SOUL.md +38 -0
- package/docs/templates/finance/USER.md +53 -0
- package/docs/templates/index.html +115 -0
- package/docs/templates/operations/HEARTBEAT.md +63 -0
- package/docs/templates/operations/MEMORY.md +68 -0
- package/docs/templates/operations/SOUL.md +38 -0
- package/docs/templates/operations/USER.md +49 -0
- package/docs/templates/sales/HEARTBEAT.md +55 -0
- package/docs/templates/sales/MEMORY.md +89 -0
- package/docs/templates/sales/SOUL.md +34 -0
- package/docs/templates/sales/USER.md +54 -0
- package/eslint.config.js +32 -0
- package/evals/README.md +29 -0
- package/evals/cases.json +390 -0
- package/evals/results.md +68 -0
- package/evals/run.js +180 -0
- package/examples/demo-attack/demo.js +186 -0
- package/examples/python-quickstart/README.md +54 -0
- package/examples/python-quickstart/clawmoat_client.py +167 -0
- package/examples/video-demo/README.md +14 -0
- package/examples/video-demo/scene-a-normal.js +29 -0
- package/examples/video-demo/scene-b-attack-arrives.js +31 -0
- package/examples/video-demo/scene-c-hijack.js +44 -0
- package/examples/video-demo/scene-d-clawmoat.js +46 -0
- package/integrations/crewai/README.md +32 -0
- package/integrations/crewai/clawmoat_crewai/__init__.py +17 -0
- package/integrations/crewai/clawmoat_crewai/guard.py +103 -0
- package/integrations/crewai/pyproject.toml +21 -0
- package/integrations/langchain/README.md +91 -0
- package/integrations/langchain/clawmoat_langchain/__init__.py +17 -0
- package/integrations/langchain/clawmoat_langchain/callback.py +489 -0
- package/integrations/langchain/pyproject.toml +32 -0
- package/integrations/litellm/README.md +324 -0
- package/integrations/litellm/clawmoat_litellm/__init__.py +21 -0
- package/integrations/litellm/clawmoat_litellm/callback.py +329 -0
- package/integrations/litellm/clawmoat_litellm/proxy_middleware.py +224 -0
- package/integrations/litellm/pyproject.toml +74 -0
- package/integrations/openai-agents/README.md +392 -0
- package/integrations/openai-agents/clawmoat_openai_agents/__init__.py +20 -0
- package/integrations/openai-agents/clawmoat_openai_agents/guardrail.py +431 -0
- package/integrations/openai-agents/clawmoat_openai_agents/middleware.py +311 -0
- package/integrations/openai-agents/pyproject.toml +76 -0
- package/package.json +6 -5
- package/plugins/openclaw-adapter/PHASE1.md +439 -0
- package/plugins/openclaw-adapter/README.md +103 -0
- package/plugins/openclaw-adapter/SPEC.md +1644 -0
- package/plugins/openclaw-adapter/package.json +31 -0
- package/plugins/openclaw-adapter/src/index.test.ts +226 -0
- package/plugins/openclaw-adapter/src/index.ts +140 -0
- package/plugins/openclaw-adapter/tsconfig.json +14 -0
- package/server/data/threats.json +290 -0
- package/server/index.js +142 -7
- package/src/adapters/express.js +161 -0
- package/src/adapters/index.js +92 -0
- package/src/adapters/langchain.js +185 -0
- package/src/approval/index.js +456 -0
- package/src/ban-scanner.js +200 -0
- package/src/boundary-scanner.js +296 -0
- package/src/ci-scanner.js +279 -0
- package/src/code-scanner.js +245 -0
- package/src/enforce.js +166 -0
- package/src/formatters/json.js +80 -0
- package/src/formatters/sarif.js +388 -0
- package/src/guardian/alerts.js +34 -3
- package/src/guardian/index.js +41 -2
- package/src/index.js +102 -0
- package/src/integrations/agentmesh.js +501 -0
- package/src/language-detector.js +201 -0
- package/src/mcp-scanner.js +253 -0
- package/src/multimodal/index.js +579 -0
- package/src/obfuscation-scanner.js +457 -0
- package/src/policy-engine.js +402 -0
- package/src/scanners/dependency-attacks.js +128 -0
- package/src/scanners/prompt-injection.js +18 -0
- package/src/scanners/supply-chain.js +14 -0
- package/src/templates/default-config.yml +90 -0
- package/src/vuln-ops/exploitability.js +46 -0
- package/src/watch/live-monitor.js +720 -0
- package/clawmoat-0.8.0.tgz +0 -0
- package/server/index.js.patch +0 -1
|
@@ -66,14 +66,14 @@ footer{border-top:1px solid var(--navy-mid);padding:40px 0;text-align:center;col
|
|
|
66
66
|
<body>
|
|
67
67
|
|
|
68
68
|
<nav>
|
|
69
|
-
<div class="container"
|
|
69
|
+
<div class="container">
|
|
70
70
|
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
71
|
+
<button class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
|
71
72
|
<div class="nav-links">
|
|
72
|
-
<a href="/">
|
|
73
|
-
<a href="/
|
|
73
|
+
<a href="/">Security</a>
|
|
74
|
+
<a href="/services/">AI Agents</a>
|
|
74
75
|
<a href="/blog/">Blog</a>
|
|
75
|
-
<a href="https://github.com/darfaz/clawmoat">GitHub
|
|
76
|
-
<a href="/#waitlist" class="btn-sm">Get Early Access</a>
|
|
76
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub ↗</a>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
</nav>
|
|
@@ -276,7 +276,15 @@ audit:
|
|
|
276
276
|
</article>
|
|
277
277
|
|
|
278
278
|
<footer>
|
|
279
|
-
|
|
279
|
+
<div class="container">
|
|
280
|
+
<div style="display:flex;gap:24px;justify-content:center;flex-wrap:wrap;margin-bottom:16px">
|
|
281
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--gray)">GitHub</a>
|
|
282
|
+
<a href="https://www.npmjs.com/package/clawmoat" style="color:var(--gray)">npm</a>
|
|
283
|
+
<a href="/blog/" style="color:var(--gray)">Blog</a>
|
|
284
|
+
<a href="mailto:hello@clawmoat.com" style="color:var(--gray)">hello@clawmoat.com</a>
|
|
285
|
+
</div>
|
|
286
|
+
<p style="text-align:center;color:var(--gray);font-size:.85rem">© 2026 ClawMoat</p>
|
|
287
|
+
</div>
|
|
280
288
|
</footer>
|
|
281
289
|
|
|
282
290
|
</body>
|
|
@@ -66,14 +66,14 @@ footer{border-top:1px solid var(--navy-mid);padding:40px 0;text-align:center;col
|
|
|
66
66
|
<body>
|
|
67
67
|
|
|
68
68
|
<nav>
|
|
69
|
-
<div class="container"
|
|
69
|
+
<div class="container">
|
|
70
70
|
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
71
|
+
<button class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
|
71
72
|
<div class="nav-links">
|
|
72
|
-
<a href="/">
|
|
73
|
-
<a href="/
|
|
73
|
+
<a href="/">Security</a>
|
|
74
|
+
<a href="/services/">AI Agents</a>
|
|
74
75
|
<a href="/blog/">Blog</a>
|
|
75
|
-
<a href="https://github.com/darfaz/clawmoat">GitHub
|
|
76
|
-
<a href="/#waitlist" class="btn-sm">Get Early Access</a>
|
|
76
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub ↗</a>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
</nav>
|
|
@@ -297,7 +297,15 @@ tools:
|
|
|
297
297
|
</article>
|
|
298
298
|
|
|
299
299
|
<footer>
|
|
300
|
-
|
|
300
|
+
<div class="container">
|
|
301
|
+
<div style="display:flex;gap:24px;justify-content:center;flex-wrap:wrap;margin-bottom:16px">
|
|
302
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--gray)">GitHub</a>
|
|
303
|
+
<a href="https://www.npmjs.com/package/clawmoat" style="color:var(--gray)">npm</a>
|
|
304
|
+
<a href="/blog/" style="color:var(--gray)">Blog</a>
|
|
305
|
+
<a href="mailto:hello@clawmoat.com" style="color:var(--gray)">hello@clawmoat.com</a>
|
|
306
|
+
</div>
|
|
307
|
+
<p style="text-align:center;color:var(--gray);font-size:.85rem">© 2026 ClawMoat</p>
|
|
308
|
+
</div>
|
|
301
309
|
</footer>
|
|
302
310
|
|
|
303
311
|
</body>
|
|
@@ -66,14 +66,14 @@ footer{border-top:1px solid var(--navy-mid);padding:40px 0;text-align:center;col
|
|
|
66
66
|
<body>
|
|
67
67
|
|
|
68
68
|
<nav>
|
|
69
|
-
<div class="container"
|
|
69
|
+
<div class="container">
|
|
70
70
|
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
71
|
+
<button class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
|
71
72
|
<div class="nav-links">
|
|
72
|
-
<a href="/">
|
|
73
|
-
<a href="/
|
|
73
|
+
<a href="/">Security</a>
|
|
74
|
+
<a href="/services/">AI Agents</a>
|
|
74
75
|
<a href="/blog/">Blog</a>
|
|
75
|
-
<a href="https://github.com/darfaz/clawmoat">GitHub
|
|
76
|
-
<a href="/#waitlist" class="btn-sm">Get Early Access</a>
|
|
76
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub ↗</a>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
</nav>
|
|
@@ -293,19 +293,67 @@ done</code></pre>
|
|
|
293
293
|
</div>
|
|
294
294
|
</div>
|
|
295
295
|
|
|
296
|
+
<h2>Official Sanitizer Plugin</h2>
|
|
297
|
+
|
|
298
|
+
<div class="callout">
|
|
299
|
+
<strong>🔌 NEW:</strong> ClawMoat is now the <strong>reference implementation</strong> for OpenClaw's pluggable sanitizer pipeline. Every piece of content — transcripts, MCP tool results, agent messages — can pass through ClawMoat before reaching the AI agent.
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<pre><code><span class="lang-label">Shell</span>npm install @openclaw/plugin-clawmoat</code></pre>
|
|
303
|
+
|
|
304
|
+
<pre><code><span class="lang-label">JSON</span>// openclaw.json
|
|
305
|
+
{
|
|
306
|
+
"sanitizers": [{
|
|
307
|
+
"module": "@openclaw/plugin-clawmoat",
|
|
308
|
+
"threshold": "medium",
|
|
309
|
+
"scanSecrets": true
|
|
310
|
+
}]
|
|
311
|
+
}</code></pre>
|
|
312
|
+
|
|
313
|
+
<p>The plugin provides:</p>
|
|
314
|
+
<ul>
|
|
315
|
+
<li><strong>Configurable block thresholds</strong> — low, medium, high, critical</li>
|
|
316
|
+
<li><strong>Clean threat mapping</strong> — ClawMoat threat types → OpenClaw ruleIds</li>
|
|
317
|
+
<li><strong>Full audit logging</strong> — every scan result recorded</li>
|
|
318
|
+
<li><strong>10 test cases</strong> covering injection, credentials, thresholds, and edge cases</li>
|
|
319
|
+
</ul>
|
|
320
|
+
|
|
321
|
+
<p>See the <a href="https://github.com/darfaz/clawmoat/tree/main/plugins/openclaw-adapter">full spec and implementation guide</a> on GitHub.</p>
|
|
322
|
+
|
|
323
|
+
<h2>ClawMoat Dashboard</h2>
|
|
324
|
+
|
|
325
|
+
<p>Pro subscribers get access to the <a href="https://app.clawmoat.com"><strong>ClawMoat Dashboard</strong></a> — a hosted security console where you can:</p>
|
|
326
|
+
|
|
327
|
+
<ul>
|
|
328
|
+
<li><strong>Scan text in your browser</strong> — paste any content and get instant threat analysis</li>
|
|
329
|
+
<li><strong>Generate API keys</strong> — integrate ClawMoat scanning into your own tools via REST API</li>
|
|
330
|
+
<li><strong>View scan history</strong> — full audit trail of every scan with threat level badges</li>
|
|
331
|
+
<li><strong>Monitor stats</strong> — total scans, threats detected, last scan time</li>
|
|
332
|
+
</ul>
|
|
333
|
+
|
|
334
|
+
<p>No terminal required. Log in with your email and start scanning.</p>
|
|
335
|
+
|
|
296
336
|
<h2>Next Steps</h2>
|
|
297
337
|
<ul>
|
|
338
|
+
<li><a href="https://app.clawmoat.com">ClawMoat Dashboard</a> — scan, monitor, and manage API keys</li>
|
|
298
339
|
<li><a href="/integrations/langchain.html">LangChain Integration</a> — use ClawMoat with LangChain agents</li>
|
|
299
340
|
<li><a href="/integrations/openai.html">OpenAI Integration</a> — secure function calling</li>
|
|
300
341
|
<li><a href="https://github.com/darfaz/clawmoat">GitHub</a> — contribute, report issues, star the repo</li>
|
|
301
|
-
<li><a href="/#waitlist">Join the waitlist</a> — get early access to ClawMoat Pro with cloud dashboards</li>
|
|
302
342
|
</ul>
|
|
303
343
|
|
|
304
344
|
</div>
|
|
305
345
|
</article>
|
|
306
346
|
|
|
307
347
|
<footer>
|
|
308
|
-
|
|
348
|
+
<div class="container">
|
|
349
|
+
<div style="display:flex;gap:24px;justify-content:center;flex-wrap:wrap;margin-bottom:16px">
|
|
350
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--gray)">GitHub</a>
|
|
351
|
+
<a href="https://www.npmjs.com/package/clawmoat" style="color:var(--gray)">npm</a>
|
|
352
|
+
<a href="/blog/" style="color:var(--gray)">Blog</a>
|
|
353
|
+
<a href="mailto:hello@clawmoat.com" style="color:var(--gray)">hello@clawmoat.com</a>
|
|
354
|
+
</div>
|
|
355
|
+
<p style="text-align:center;color:var(--gray);font-size:.85rem">© 2026 ClawMoat</p>
|
|
356
|
+
</div>
|
|
309
357
|
</footer>
|
|
310
358
|
|
|
311
359
|
</body>
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# ClawMoat Threat Intel API — Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For implementation:** Use the executing-plans skill to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** Ship an MVP API endpoint that serves structured AI agent security threat intelligence, with Stripe metered billing.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Express.js server (extends existing ~/clawmoat/server/), backed by a JSON threat database that Leo populates from daily security news scans. Endpoints serve filtered threat data. Stripe usage-based billing tracks API calls per key. Deployed on Railway.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Express.js, Stripe metered billing, JSON flat-file storage (MVP), API key auth, Railway deploy
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Task 1: Threat Database Schema & Seed Data
|
|
14
|
+
|
|
15
|
+
**Files:**
|
|
16
|
+
- Create: `server/data/threats.json`
|
|
17
|
+
- Create: `server/data/schema.md`
|
|
18
|
+
|
|
19
|
+
**Step 1: Define the threat schema**
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"id": "CLAWMOAT-2026-0001",
|
|
24
|
+
"title": "LiteLLM .pth File Injection",
|
|
25
|
+
"published": "2026-03-24T00:00:00Z",
|
|
26
|
+
"updated": "2026-03-26T00:00:00Z",
|
|
27
|
+
"severity": "critical",
|
|
28
|
+
"category": "supply-chain",
|
|
29
|
+
"tags": ["python", "pypi", "credential-theft", "pth-injection"],
|
|
30
|
+
"summary": "LiteLLM versions 1.82.7-1.82.8 contain credential-stealing .pth payload",
|
|
31
|
+
"affected": {
|
|
32
|
+
"packages": ["litellm==1.82.7", "litellm==1.82.8"],
|
|
33
|
+
"ecosystems": ["pypi"]
|
|
34
|
+
},
|
|
35
|
+
"ioc": {
|
|
36
|
+
"domains": ["models.litellm.cloud"],
|
|
37
|
+
"files": ["litellm_init.pth"],
|
|
38
|
+
"hashes": [],
|
|
39
|
+
"patterns": ["exec(base64.b64decode(", ".pth import subprocess"]
|
|
40
|
+
},
|
|
41
|
+
"detection": {
|
|
42
|
+
"clawmoat_module": "scanners/supply-chain",
|
|
43
|
+
"clawmoat_function": "scanSkillContent",
|
|
44
|
+
"rules_triggered": ["obfuscated_exec_b64", "pth_file_injection", "exfil_litellm_lookalike"]
|
|
45
|
+
},
|
|
46
|
+
"references": [
|
|
47
|
+
"https://github.com/BerriAI/litellm/issues/24512",
|
|
48
|
+
"https://news.ycombinator.com/item?id=47501426",
|
|
49
|
+
"https://awesomeagents.ai/news/litellm-supply-chain-compromise-credential-theft/"
|
|
50
|
+
],
|
|
51
|
+
"mitigation": "Rotate all credentials on affected systems. Check: pip show litellm | grep Version. Search: find / -name litellm_init.pth"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Step 2: Seed with this week's 5 threats**
|
|
56
|
+
|
|
57
|
+
Populate threats.json with:
|
|
58
|
+
1. LiteLLM .pth injection (CLAWMOAT-2026-0001)
|
|
59
|
+
2. Meta AI agent data leak (CLAWMOAT-2026-0002)
|
|
60
|
+
3. API key exposure on 10K websites (CLAWMOAT-2026-0003)
|
|
61
|
+
4. LeakBase credential marketplace (CLAWMOAT-2026-0004)
|
|
62
|
+
5. Gemini API key theft — $82K bill (CLAWMOAT-2026-0005)
|
|
63
|
+
|
|
64
|
+
**Step 3: Commit**
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
git commit -m "feat: threat intel database schema + seed data (5 threats)"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Task 2: API Endpoint — GET /api/v1/threats
|
|
73
|
+
|
|
74
|
+
**Files:**
|
|
75
|
+
- Create: `server/routes/threats.js`
|
|
76
|
+
- Modify: `server/index.js` (mount route)
|
|
77
|
+
- Create: `server/middleware/api-key-auth.js`
|
|
78
|
+
- Test: `server/tests/threats.test.js`
|
|
79
|
+
|
|
80
|
+
**Step 1: Write failing test**
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const request = require('supertest');
|
|
84
|
+
const app = require('../index');
|
|
85
|
+
|
|
86
|
+
describe('GET /api/v1/threats', () => {
|
|
87
|
+
it('returns 401 without API key', async () => {
|
|
88
|
+
const res = await request(app).get('/api/v1/threats');
|
|
89
|
+
expect(res.status).toBe(401);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('returns threats with valid API key', async () => {
|
|
93
|
+
const res = await request(app)
|
|
94
|
+
.get('/api/v1/threats')
|
|
95
|
+
.set('X-API-Key', 'test-key-123');
|
|
96
|
+
expect(res.status).toBe(200);
|
|
97
|
+
expect(res.body.threats).toBeInstanceOf(Array);
|
|
98
|
+
expect(res.body.threats.length).toBeGreaterThan(0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('filters by category', async () => {
|
|
102
|
+
const res = await request(app)
|
|
103
|
+
.get('/api/v1/threats?category=supply-chain')
|
|
104
|
+
.set('X-API-Key', 'test-key-123');
|
|
105
|
+
expect(res.body.threats.every(t => t.category === 'supply-chain')).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('filters by severity', async () => {
|
|
109
|
+
const res = await request(app)
|
|
110
|
+
.get('/api/v1/threats?severity=critical')
|
|
111
|
+
.set('X-API-Key', 'test-key-123');
|
|
112
|
+
expect(res.body.threats.every(t => t.severity === 'critical')).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('filters by date range', async () => {
|
|
116
|
+
const res = await request(app)
|
|
117
|
+
.get('/api/v1/threats?since=2026-03-24')
|
|
118
|
+
.set('X-API-Key', 'test-key-123');
|
|
119
|
+
expect(res.body.threats.length).toBeGreaterThan(0);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Step 2: Run test, confirm failure**
|
|
125
|
+
|
|
126
|
+
**Step 3: Implement API key middleware**
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// server/middleware/api-key-auth.js
|
|
130
|
+
const validKeys = new Map(); // loaded from server/data/api-keys.json
|
|
131
|
+
|
|
132
|
+
function apiKeyAuth(req, res, next) {
|
|
133
|
+
const key = req.headers['x-api-key'];
|
|
134
|
+
if (!key) return res.status(401).json({ error: 'API key required' });
|
|
135
|
+
const record = validKeys.get(key);
|
|
136
|
+
if (!record) return res.status(403).json({ error: 'Invalid API key' });
|
|
137
|
+
req.apiUser = record;
|
|
138
|
+
next();
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Step 4: Implement threats route**
|
|
143
|
+
|
|
144
|
+
Query params: `category`, `severity`, `since`, `tags`, `limit` (default 20, max 100)
|
|
145
|
+
|
|
146
|
+
Response format:
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"threats": [...],
|
|
150
|
+
"count": 5,
|
|
151
|
+
"total": 5,
|
|
152
|
+
"updated": "2026-03-26T15:00:00Z"
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Step 5: Run tests, confirm pass**
|
|
157
|
+
|
|
158
|
+
**Step 6: Commit**
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
git commit -m "feat: GET /api/v1/threats endpoint with filtering + API key auth"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Task 3: GET /api/v1/threats/:id — Single Threat Detail
|
|
167
|
+
|
|
168
|
+
**Files:**
|
|
169
|
+
- Modify: `server/routes/threats.js`
|
|
170
|
+
- Modify: `server/tests/threats.test.js`
|
|
171
|
+
|
|
172
|
+
Returns full threat object including IOCs, detection rules, mitigation steps.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Task 4: GET /api/v1/ioc — Indicators of Compromise Feed
|
|
177
|
+
|
|
178
|
+
**Files:**
|
|
179
|
+
- Create: `server/routes/ioc.js`
|
|
180
|
+
- Test: `server/tests/ioc.test.js`
|
|
181
|
+
|
|
182
|
+
Aggregates all IOCs across threats into a flat feed. Useful for agents to bulk-update their blocklists.
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"domains": ["models.litellm.cloud", ...],
|
|
187
|
+
"files": ["litellm_init.pth", ...],
|
|
188
|
+
"patterns": ["exec(base64.b64decode(", ...],
|
|
189
|
+
"updated": "2026-03-26T15:00:00Z"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Task 5: Stripe Metered Billing
|
|
196
|
+
|
|
197
|
+
**Files:**
|
|
198
|
+
- Create: `server/middleware/usage-tracker.js`
|
|
199
|
+
- Create: `server/billing/stripe.js`
|
|
200
|
+
- Modify: `server/middleware/api-key-auth.js` (link to Stripe customer)
|
|
201
|
+
|
|
202
|
+
**Pricing:**
|
|
203
|
+
- Free tier: 100 calls/month (no card required)
|
|
204
|
+
- Pro: $4.99/mo flat + $0.001/call over 5,000
|
|
205
|
+
- Unlimited: $19.99/mo
|
|
206
|
+
|
|
207
|
+
**Implementation:**
|
|
208
|
+
1. On each API call, increment usage counter in api-keys.json
|
|
209
|
+
2. Stripe webhook on subscription create → generate API key → email to user
|
|
210
|
+
3. Daily cron: report usage to Stripe metered billing
|
|
211
|
+
4. Free tier: check call count, return 429 when exceeded
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Task 6: API Key Self-Service
|
|
216
|
+
|
|
217
|
+
**Files:**
|
|
218
|
+
- Create: `server/routes/keys.js`
|
|
219
|
+
- Test: `server/tests/keys.test.js`
|
|
220
|
+
|
|
221
|
+
POST /api/v1/keys — generate a free-tier API key (email required)
|
|
222
|
+
GET /api/v1/keys/:key/usage — check your usage
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Task 7: Railway Deploy
|
|
227
|
+
|
|
228
|
+
**Files:**
|
|
229
|
+
- Modify: `server/package.json` (start script)
|
|
230
|
+
- Create: `server/Procfile`
|
|
231
|
+
- Create: `server/.env.example`
|
|
232
|
+
|
|
233
|
+
Environment vars: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, API_MASTER_KEY
|
|
234
|
+
|
|
235
|
+
Deploy to Railway on clawmoat.com subdomain: `api.clawmoat.com`
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Task 8: Documentation
|
|
240
|
+
|
|
241
|
+
**Files:**
|
|
242
|
+
- Create: `docs/api/README.md`
|
|
243
|
+
- Create: `docs/api/openapi.yaml`
|
|
244
|
+
- Modify: `README.md` (add Threat Intel API section)
|
|
245
|
+
|
|
246
|
+
OpenAPI spec for the full API. Add to clawmoat.com as /docs/api page.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## MVP Scope (Tonight)
|
|
251
|
+
|
|
252
|
+
Tasks 1-3 + 7 = working API with seed data, deployed on Railway.
|
|
253
|
+
Tasks 4-6 + 8 = fast follow (this week).
|
|
254
|
+
|
|
255
|
+
**Total estimated time: 4-5 hours for MVP, 2-3 more for billing + docs.**
|