CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-7RCP-MXPQ-72PJ
4.30.04%

OpenClaw Chutes: The 'Trust Me Bro' OAuth State Bypass

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 18, 2026·5 min read·0 visits

PoC Available

Executive Summary (TL;DR)

OpenClaw tried to make manual OAuth easy by letting users paste just the code. Instead, they broke CSRF protection. Attackers can trick victims into logging into the attacker's account by providing a raw code, which the app blindly accepts.

A logic flaw in OpenClaw's manual OAuth input parsing allowed attackers to bypass state validation by simply providing a bare authorization code. The application helpfully, but insecurely, assumed that any non-URL input was a valid code and automatically attached the expected session state to it, enabling credential substitution attacks.

The Hook: The UX Road to Hell

OAuth is a nightmare. It’s a dance of redirects, tokens, and state parameters that makes even seasoned developers weep. In the world of CLI tools and local agents—like OpenClaw—it gets even messier. You can't always rely on a local web server to catch the callback. Sometimes, you just have to ask the user to copy the URL from their browser and paste it into the terminal.

OpenClaw wanted to make this "manual mode" seamless. Users are lazy; they don't want to copy a full, messy URL like https://api.openclaw.com/callback?code=abc&state=xyz. They just want to copy the code. So, the developers added a convenience feature: if the input doesn't look like a URL, assume it's the auth code.

Sounds friendly, right? It is. It's also a massive security hole. By prioritizing convenience over strict validation, they accidentally created a mechanism to completely bypass the one thing protecting the OAuth flow from forgery: the state parameter.

The Flaw: Assume Nothing, Verify Everything

The vulnerability lives in parseOAuthCallbackInput. The logic was designed with a fallback mechanism. First, it tries to parse the user's input as a full URL. If that fails (because the user pasted a raw string like 4/0AdQt...), it drops into a catch block.

Here is where the logic goes off the rails. Inside the catch block, the code checks if the string looks "safe" (no spaces, no protocol handlers). If it passes this superficial vibe check, the code automatically assigns the expectedState to the input.

Let that sink in. The application essentially says: "I see you didn't provide a state parameter. That's fine, I'll just assume you have the correct one and fill it in for you." This defeats the entire purpose of the state parameter, which exists specifically to prove that the response came from the request this user initiated. By auto-filling it, the application validates its own challenge, effectively talking to itself in a mirror and nodding in agreement.

The Code: The Smoking Gun

Let's look at the crime scene in src/agents/chutes-oauth.ts. This is a textbook example of how a catch block can introduce critical logic flaws.

The Vulnerable Code:

try {
  // Try to parse as a full URL first
  const url = new URL(trimmed);
  return { code: url.searchParams.get("code"), state: url.searchParams.get("state") };
} catch {
  // THE BUG: Fallback for manual pasting
  if (!/\s/.test(trimmed) && !trimmed.includes("://") && trimmed.length > 0) {
    // > [!CAUTION]
    // > The app blindly trusts the input and injects the valid state!
    return { code: trimmed, state: expectedState };
  }
}

The fix is brutal but necessary. It removes the assumption entirely. If the user pastes a raw string, the new code refuses to guess. It enforces that the input must contain the parameters we need.

The Fix (Commit a99ad11):

// New Logic: No more free rides
let url: URL;
try {
  url = new URL(trimmed);
} catch {
  // If it's not a URL, it MUST be a query string with code AND state
  if (!trimmed.includes("?") && !trimmed.includes("=")) {
    return { error: "Paste the full redirect URL (must include code + state)." };
  }
  // ... construct dummy URL to parse parameters ...
}
 
// Explicit validation
if (state !== expectedState) {
  return { error: "OAuth state mismatch - possible CSRF attack." };
}

The Exploit: Credential Substitution

Since this is a client-side tool, we aren't talking about stealing the victim's session in the traditional web sense. We are talking about Credential Substitution (or Login CSRF).

Here is the attack scenario:

  1. The Trap: The attacker initiates an OAuth flow for their own account using OpenClaw. They get a valid authorization code from the provider but do not complete the flow.
  2. The Lure: The attacker contacts a victim (perhaps a developer on the same team) and says, "Hey, the CI agent is failing. Run the setup again, but when it asks for the code, paste this: 4/0Ad...."
  3. The Hook: The victim runs OpenClaw. It prompts for input. The victim pastes the attacker's code.
  4. The Switch: The vulnerable code sees the raw string, says "Looks good!", and attaches the victim's session state to the attacker's code.
  5. The Impact: OpenClaw exchanges the code. The victim is now authenticated as the attacker. Any data the victim pushes, logs, or processes is now being sent to the attacker's account, not the victim's corporate account.

This is particularly dangerous in automation tools ("agents") where the user might not verify the identity of the account they just linked before running a massive batch job.

The Fix: Killing the Magic

The remediation is straightforward: stop trying to be magic. The developers removed the "convenience" path in commit a99ad11a4107ba8eac58f54a3c1a8a0cf5686f47.

Now, users are forced to paste the full URL or a query string that explicitly includes the state. If the state is missing or doesn't match, the flow fails hard.

They also updated the UI prompts from "Paste the redirect URL (or authorization code)" to just "Paste the redirect URL". This is a good lesson in security UX: don't suggest insecure workflows in your prompt text. If you want security, sometimes you have to force the user to do the slightly annoying thing (copying the whole URL) rather than the easy thing.

Official Patches

OpenClawRelease notes for v2026.2.14

Fix Analysis (1)

Technical Appendix

CVSS Score
4.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

OpenClaw Chutes (npm package)OpenClaw CLI Agent

Affected Versions Detail

Product
Affected Versions
Fixed Version
openclaw
openclaw
< 2026.2.142026.2.14
AttributeDetail
CWECWE-352 (CSRF)
Attack VectorNetwork / Social Engineering
CVSS4.3 (Medium)
ImpactCredential Substitution
Exploit StatusPoC Available
Patchv2026.2.14

MITRE ATT&CK Mapping

T1550Use Alternate Authentication Material
Defense Evasion
T1204.001User Execution: Malicious Link
Execution
CWE-352
Cross-Site Request Forgery (CSRF)

The application fails to verify that the state parameter in the OAuth callback matches the state parameter sent in the authorization request when parsing manual input.

Known Exploits & Detection

InternalTheoretical flow demonstrated by reporter @aether-ai-agent

Vulnerability Timeline

Vulnerability discovered by @aether-ai-agent
2026-02-01
Patch released in v2026.2.14
2026-02-14
GHSA Advisory published
2026-02-14

References & Sources

  • [1]GitHub Advisory
  • [2]OAuth 2.0 Threat Model

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.