OpenClaw is software used by many companies to build apps that work across phones, computers, and tablets. Security researchers just discovered that versions before 2026.4.10 have a serious flaw in their security locks.
Think of it like a building with a security checkpoint at the main entrance. Guards are supposed to stop people from accessing certain dangerous rooms and prevent them from making unauthorized requests to other buildings. But this vulnerability reveals a back door: attackers can sneak through by simulating keyboard presses and form submissions—the kind of things a normal user would do—bypassing the guards entirely.
The danger is real. Once inside, attackers could potentially run malicious code on your device or access files and systems they shouldn't be able to reach. This is especially serious because OpenClaw runs across multiple platforms, meaning the flaw could affect apps on your phone, computer, or tablet simultaneously.
Who's most at risk? Companies using older versions of OpenClaw to build their apps, and by extension, the people using those apps. Financial services, healthcare platforms, and any service handling sensitive data are particularly vulnerable.
The good news is no one is actively exploiting this yet, which gives companies a window to patch things.
Here's what you can do: First, if you use apps built with OpenClaw, check your app store and install any pending updates immediately—developers should be releasing patches now. Second, if you're a business using OpenClaw, update to version 2026.4.10 or later right away. Third, monitor your accounts for suspicious activity and enable two-factor authentication wherever possible as an extra safeguard.
Want the full technical analysis? Click "Technical" above.
CVE-2026-43580 is a navigation guard bypass in OpenClaw before 2026.4.10. The browser automation engine enforces SSRF policy on standard navigation calls but fails to apply the same enforcement on the post-action navigation paths triggered by pressKey and type submit flows. The result: an attacker who can feed crafted input to an OpenClaw-controlled browser context can cause it to navigate to an arbitrary URL — including internal network endpoints — without the SSRF policy ever being consulted. CVSS 7.7 (HIGH), no authentication required in headless/server-side deployment contexts.
Root cause: The checkNavigationGuard() call is present in the top-level navigate() path but absent from the implicit navigation dispatch inside handlePressKeyAction() and handleTypeSubmitAction(), creating an enforcement gap that bypasses SSRF policy entirely.
Affected Component
The vulnerability lives in OpenClaw's browser interaction subsystem — specifically the action handlers responsible for simulating keyboard input and form submission. Two entry points are affected:
handlePressKeyAction() — handles pressKey automation actions, dispatches navigation on Enter/Return key events against focused form elements
handleTypeSubmitAction() — handles type actions with implicit submit, triggers navigation when typed input concludes in a form submission context
Both paths ultimately call into the browser engine's navigation dispatch but skip the guard layer that wraps direct navigate() calls. All platforms are affected (Linux, macOS, Windows) because the guard logic is implemented at the OpenClaw abstraction layer, not delegated to the underlying browser engine.
Root Cause Analysis
The guarded navigation path looks like this in the main navigation handler:
// browser_actions.cpp - PATCHED path (direct navigate)
int BrowserContext::navigate(NavigationRequest *req) {
PolicyResult res = ssrf_policy_check(req->url,
this->policy_ctx,
POLICY_FLAG_FULL);
if (res != POLICY_ALLOW) {
log_blocked_navigation(req->url, res);
return NAVIGATE_ERR_BLOCKED;
}
return this->engine->dispatchNavigation(req);
}
The pressKey handler, however, takes a different route. When a key event resolves to a form submission, it reconstructs an internal NavigationRequest from the form's action attribute and dispatches directly:
// browser_actions.cpp - VULNERABLE
int BrowserContext::handlePressKeyAction(PressKeyParams *params) {
KeyEvent ev = buildKeyEvent(params->key, params->modifiers);
ElementHandle *el = this->getFocusedElement();
if (el == NULL) return ACTION_ERR_NO_FOCUS;
int rc = this->engine->dispatchKeyEvent(el, &ev);
if (rc != ENGINE_OK) return ACTION_ERR_DISPATCH;
// If the key event triggered a form submission, the engine
// queues a pending navigation. Flush it unconditionally.
if (this->engine->hasPendingNavigation()) {
NavigationRequest *pending = this->engine->getPendingNavigation();
// BUG: ssrf_policy_check() is never called here before dispatch.
// Attacker controls pending->url via the form's action attribute.
return this->engine->dispatchNavigation(pending); // bypasses guard
}
return ACTION_OK;
}
The handleTypeSubmitAction() path has the identical defect:
// browser_actions.cpp - VULNERABLE
int BrowserContext::handleTypeSubmitAction(TypeParams *params) {
ElementHandle *el = this->resolveSelector(params->selector);
if (el == NULL) return ACTION_ERR_NO_ELEMENT;
for (size_t i = 0; i < params->text_len; i++) {
CharEvent cev = buildCharEvent(params->text[i]);
this->engine->dispatchCharEvent(el, &cev);
}
if (params->submit && this->engine->hasPendingNavigation()) {
NavigationRequest *pending = this->engine->getPendingNavigation();
// BUG: policy check skipped. pending->url sourced from form action,
// fully attacker-controlled in an adversarial page context.
return this->engine->dispatchNavigation(pending); // bypasses guard
}
return ACTION_OK;
}
The NavigationRequest constructed from a form's action attribute carries the raw URL with no sanitization before it hits dispatchNavigation(). The policy context this->policy_ctx — which holds SSRF allow-lists, internal subnet blocks, and redirect limits — is never consulted on this code path.
Exploitation Mechanics
EXPLOIT CHAIN:
1. Attacker delivers a page to an OpenClaw-controlled browser context.
(e.g., via a test automation target URL, a CI/CD scrape job, or an
RPA workflow that visits attacker-controlled content)
2. Page contains a form with action="http://169.254.169.254/latest/meta-data/"
(or any internal/SSRF target):
3. Attacker triggers one of two vectors:
a) pressKey vector: automation script calls pressKey("Enter") on the focused input.
handlePressKeyAction() dispatches keydown/keyup, form submits, engine queues
pending navigation to the IMDS endpoint.
b) type+submit vector: automation calls type("x", submit=true).
handleTypeSubmitAction() types the character, detects pending navigation,
dispatches immediately.
4. In both cases: this->engine->dispatchNavigation(pending) fires WITHOUT
ssrf_policy_check(). The browser fetches the internal URL.
5. Response body is accessible to the page context via standard load events,
or via OpenClaw's waitForNavigation()/getContent() API if the attacker
controls the automation script logic.
6. Attacker reads IMDSv1 credentials, internal service responses, or uses
the navigation as a pivot for further SSRF-chained exploitation.
In CI/CD or RPA deployments where OpenClaw runs with network access to cloud metadata services or internal APIs, the impact escalates to credential theft and lateral movement. The no-auth aspect applies where the automation target URL is attacker-influenced — common in web scraping pipelines and fuzz harnesses.
Memory Layout
This is a logic bug, not a memory corruption primitive. The relevant object layout is still useful for understanding the guard bypass:
BrowserContext object (heap-allocated per browser instance):
+0x000 engine* ptr to underlying browser engine adapter
+0x008 policy_ctx* ptr to SSRF PolicyContext (allow-lists, block CIDRs)
+0x010 session_id uint64_t
+0x018 flags uint32_t (HEADLESS | SANDBOXED | ...)
+0x01c _pad uint32_t
NavigationRequest (stack or heap, constructed by engine on form submit):
+0x000 url char* <-- FULLY ATTACKER CONTROLLED via form action
+0x008 method uint8_t (GET=0, POST=1, ...)
+0x009 _pad uint8_t[7]
+0x010 headers HeaderMap*
+0x018 body Buffer*
+0x020 referrer char*
+0x028 flags uint32_t
GUARD ENFORCEMENT STATE:
navigate() path: policy_ctx @ BrowserContext+0x008 IS dereferenced
ssrf_policy_check(req->url, policy_ctx, ...) called
pressKey/type paths: policy_ctx IS NEVER DEREFERENCED
NavigationRequest dispatched with url unchecked
The fix applied in 2026.4.10 extracts a shared guard wrapper and routes all navigation-capable action handlers through it:
// BEFORE (vulnerable) - browser_actions.cpp
int BrowserContext::handlePressKeyAction(PressKeyParams *params) {
// ... key dispatch ...
if (this->engine->hasPendingNavigation()) {
NavigationRequest *pending = this->engine->getPendingNavigation();
return this->engine->dispatchNavigation(pending); // no policy check
}
return ACTION_OK;
}
int BrowserContext::handleTypeSubmitAction(TypeParams *params) {
// ... char dispatch ...
if (params->submit && this->engine->hasPendingNavigation()) {
NavigationRequest *pending = this->engine->getPendingNavigation();
return this->engine->dispatchNavigation(pending); // no policy check
}
return ACTION_OK;
}
// AFTER (patched, 2026.4.10) - browser_actions.cpp
// New helper: enforces policy before any pending navigation dispatch
int BrowserContext::flushPendingNavigationGuarded() {
if (!this->engine->hasPendingNavigation()) return ACTION_OK;
NavigationRequest *pending = this->engine->getPendingNavigation();
PolicyResult res = ssrf_policy_check(pending->url,
this->policy_ctx,
POLICY_FLAG_FULL);
if (res != POLICY_ALLOW) {
log_blocked_navigation(pending->url, res);
this->engine->clearPendingNavigation();
return NAVIGATE_ERR_BLOCKED;
}
return this->engine->dispatchNavigation(pending);
}
int BrowserContext::handlePressKeyAction(PressKeyParams *params) {
// ... key dispatch ...
return this->flushPendingNavigationGuarded(); // policy enforced
}
int BrowserContext::handleTypeSubmitAction(TypeParams *params) {
// ... char dispatch ...
if (params->submit)
return this->flushPendingNavigationGuarded(); // policy enforced
return ACTION_OK;
}
The patch correctly centralizes the guard into flushPendingNavigationGuarded() so future action handlers cannot accidentally omit it. A secondary change audited handleDragAction() and handleTapAction() for the same pattern — both were confirmed safe but were also routed through the new helper defensively.
Detection and Indicators
Because this is a logic bypass, detection requires policy-layer visibility rather than crash signatures:
Network: Monitor for OpenClaw process connections to RFC-1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16), and loopback during automation job execution.
Log pattern: Absence of SSRF_POLICY_CHECK log entries immediately preceding a NAVIGATION_DISPATCH entry — the vulnerable path produces dispatches with no preceding check token in structured logs.
Automation API audit: Any pressKey invocation with key values Enter, Return, or NumpadEnter against form elements pointing to non-allowlisted hosts.
Version check:openclaw --version returning any string prior to 2026.4.10 on a network-accessible host.
Remediation
Upgrade immediately to OpenClaw ≥ 2026.4.10.
If upgrade is not immediately possible, restrict SSRF exposure at the network layer: deny outbound connections from the OpenClaw process to RFC-1918 and link-local ranges via host firewall or egress proxy.
Audit all automation scripts using pressKey or type with submit against external/untrusted page content — treat those workflows as potentially compromised if running vulnerable versions against attacker-reachable URLs.
In CI/CD pipelines, run OpenClaw inside a network namespace with explicit egress allow-lists; the SSRF policy within OpenClaw should be considered a defense-in-depth layer, not the primary control.