Feb 18, 2026·6 min read·4 visits
OpenClaw's Google Chat integration played 'webhook roulette' with incoming messages. If two bots shared a URL, the first one in the config list grabbed the message, regardless of intended recipient. Fixed in v2026.2.14.
A critical logic flaw in OpenClaw's Google Chat webhook dispatcher allowed for cross-account context confusion. By relying on a 'first-match' selection strategy for incoming webhooks, the system failed to distinguish between multiple valid targets sharing the same endpoint and verification credentials. This ambiguity enabled scenarios where messages intended for one AI agent could be intercepted and processed by another, leading to potential data leakage and unauthorized action execution.
We live in an era of microservices and multi-tenancy, where 'efficiency' often translates to 'stuffing as many things as possible onto a single HTTP endpoint.' OpenClaw, a personal AI assistant framework, decided to follow this trend with its Google Chat integration. The premise is simple: Google Chat sends a webhook to your server, OpenClaw catches it, verifies it, and hands it off to your AI agent.
But here is the rub: What happens when you have multiple AI personas—say, a 'Finance Bot' and a 'Office Prank Bot'—configured on the same server, listening on the same path? Ideally, the system should be smart enough to look at the incoming request and route it to the specific agent intended for that conversation.
OpenClaw decided to take a shortcut. Instead of rigorous, unique routing, they implemented a system that is essentially a game of 'First Come, First Served.' And as anyone who has ever fought for the last slice of pizza knows, the person who grabs it first isn't necessarily the person who paid for it. In the world of authentication, this is known as a 'policy-context misrouting,' but I prefer to call it 'Webhook Roulette.'
The vulnerability lies in the most dangerous place in software development: the loop condition. Specifically, inside extensions/googlechat/src/monitor.ts. The developers needed to iterate through a list of registered webhook targets to find out which one should handle an incoming message from Google.
Their logic went something like this:
break) and use this target.See the problem? They assumed that a valid signature implies a unique target. This is a fatal assumption. In Google Cloud architectures, multiple bots might share the same OAuth Audience (Project ID) or Service Account credentials. If Target A and Target B share the same verification criteria (which is common in shared project deployments), the request is valid for both.
Because the code broke the loop on the first success, the system would always route the traffic to whichever target happened to be loaded first in the array. It didn't matter if the message was actually meant for the second target; the first target cannibalized the request. This is the logic equivalent of the postman dropping all mail for an apartment building into the box for Apartment 1A simply because it's the first one near the door.
Let's look at the crime scene. This is the code that caused the issue. Notice the eager break statement.
Vulnerable Code (Before):
let selected: WebhookTarget | undefined;
for (const target of targets) {
// Logic to extract bearer token and audience...
const verification = await verifyGoogleChatRequest({
bearer,
audienceType,
audience,
});
// ⚠️ THE BUG: Stops at the first "valid" signature
if (verification.ok) {
selected = target;
break;
}
}The fix, implemented in version v2026.2.14, changes this from a 'lazy search' to a 'comprehensive check.' instead of stopping at one, it collects all matches. If it finds more than one, it realizes the situation is ambiguous and refuses to play.
The Fix (After):
const matchedTargets: WebhookTarget[] = [];
for (const target of targets) {
// ... verification logic ...
if (verification.ok) {
matchedTargets.push(target);
// Optimization: If we already have ambiguity, stop checking.
if (matchedTargets.length > 1) {
break;
}
}
}
// 🛡️ FAIL SECURE: Reject ambiguity
if (matchedTargets.length > 1) {
res.statusCode = 401;
res.end("ambiguous webhook target");
return true;
}This simple change shifts the philosophy from 'Best Effort' to 'Fail Secure.'
To exploit this, we don't need fancy buffer overflows. We just need to understand the configuration order. Imagine a scenario where a legitimate administrator has configured a HR-Helper-Bot on the /googlechat path. An attacker (or a careless developer) with access to the OpenClaw configuration adds a second bot, Shadow-Bot, on the same path, using the same GCP Project credentials.
If the Shadow-Bot gets inserted into the configuration array before HR-Helper-Bot, every single message sent to HR is intercepted by Shadow.
Here is the attack flow:
The user thinks they are talking to the secure HR bot. The system signature is valid. But the context is wrong. The attacker's bot now has the prompt history and can execute tools/functions with the permissions of the attacker's bot, potentially exfiltrating the data to an external source.
The immediate remediation is to upgrade OpenClaw to v2026.2.14. The new logic explicitly returns a 401 Unauthorized with the body ambiguous webhook target if this collision occurs. This breaks the functionality, but it fails safely rather than silently leaking data.
For those who cannot upgrade immediately, the mitigation is purely architectural: Stop sharing paths.
> [!TIP]
> Assign unique webhook paths for every single bot integration. Use /googlechat/finance, /googlechat/ops, etc. This forces the routing logic to be deterministic based on the URL, bypassing the ambiguous signature verification loop entirely.
The lesson here for developers is clear: Authentication (Who are you?) is not the same as Routing (Where are you going?). Just because a key opens the front door doesn't mean it should open every door in the hallway. When iterating through security contexts, never stop at the first 'yes.' Always check for collisions.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenClaw OpenClaw | < v2026.2.14 | v2026.2.14 |
| Attribute | Detail |
|---|---|
| Attack Vector | Network (Webhook) |
| CVSS | 7.5 (High) |
| Impact | Cross-Account Context Confusion |
| Components | extensions/googlechat/src/monitor.ts |
| Exploit Status | PoC Available |
| Root Cause | Improper Logic in Iterative Verification |