Feb 18, 2026·5 min read·3 visits
OpenClaw's Gateway allowed dynamic loading of JS modules via configuration without path validation. Attackers can point the `module` parameter to any file on disk, leading to RCE. Fixed in v2026.2.14.
OpenClaw, a personal AI assistant framework, shipped with a critical oversight in its Gateway component. By prioritizing flexibility over security, the developers allowed the application's hook system to dynamically import JavaScript modules based on user-supplied configuration paths. This effectively turned the 'transform' feature into a gateway for Remote Code Execution (RCE), allowing attackers with configuration access to load arbitrary code from the filesystem.
OpenClaw is designed to be your personal AI butler, and like any good butler, it needs to know how to handle messages from the outside world. To do this, it employs a Gateway component that listens for webhooks.
But raw webhooks are messy. Developers realized that users might want to massage that data before the AI processes it. Enter Hook Transforms. This feature allows users to specify a logic module to 'transform' incoming data. It sounds innocent enough: you point the config to a script, and the Gateway runs it.
Here is where the architecture gets shaky. Instead of sandboxing this logic or restricting it to a safe list of pre-approved transformers, the system was built to dynamically import() whatever path the configuration provided. It’s the classic 'flexibility vs. security' trade-off, and in this case, security lost badly.
The vulnerability (GHSA-V6C6-VQQG-W888) is a textbook case of CWE-73 (External Control of File Name or Path) meeting CWE-94 (Code Injection).
In the Node.js ecosystem, the import() function is powerful. It doesn't just read a file; it executes it within the runtime. When the OpenClaw Gateway processes a hook configuration, it reads a field called module. The code assumed that because this configuration arguably comes from an 'admin' (or at least someone with access to the management API), it must be safe.
The flaw lies in src/gateway/hooks-mapping.ts and src/hooks/loader.ts. The application took the string value of module, resolved it relative to the current working directory (or sometimes just took it as is), and fed it directly into the module loader. There were no checks for:
../../): Allowing the user to climb out of the intended directory./tmp/evil.js): Allowing loading from anywhere in the filesystem.This meant if an attacker could modify the gateway config—perhaps via a default-credentialed API or a secondary SSRF—they could force the Node process to execute any JavaScript file they could plant on the disk.
The fix in version v2026.2.14 is robust because it doesn't just patch the hole; it introduces a strict schema validation layer using the Zod library. The developers realized that trying to sanitize paths with regex is a losing game, so they moved to a 'deny-all, allow-some' approach.
Here is the vulnerable logic conceptualized:
// THE VULNERABLE WAY
const modulePath = config.transform.module;
// No validation? YOLO.
const handler = await import(modulePath);The patch (Commit 35c0e66ed057f1a9f7ad2515fdcef516bd6584ce) introduces SafeRelativeModulePathSchema. Look at how aggressive the validation is now:
// THE FIX (Simplified)
const isSafeRelativeModulePath = (path: string) => {
// 1. No absolute paths
if (pathIsAbsolute(path)) return false;
// 2. No home directory shortcuts
if (path.startsWith('~')) return false;
// 3. No protocol wrappers (file://)
if (path.includes(':')) return false;
// 4. No traversal sequences
if (path.includes('..')) return false;
return true;
};Furthermore, the system now enforces a root jail. Modules must reside within ~/.openclaw/hooks/transforms. If the resolved path falls outside this directory, the loader throws an error. They effectively built a chroot jail for module loading.
Let's assume we have access to the OpenClaw management API. We want to achieve Remote Code Execution. The attack chain involves two steps: planting a payload (or finding a useful gadget) and triggering the load.
Step 1: The Configuration Payload
We send a request to update the Gateway configuration. We define a new hook mapping for the path /pwn, but we point the transformer to a malicious file we've managed to drop in /tmp (or a log file we've poisoned).
{
"hooks": {
"mappings": [{
"match": { "path": "pwn" },
"action": "agent",
"transform": {
"module": "../../../../../../tmp/shell.mjs"
}
}]
}
}Step 2: The Trigger
We simply trigger the webhook. The Gateway matches the path /pwn, sees the transform rule, and attempts to load the module.
curl -X POST http://target-openclaw:3000/hooks/pwnStep 3: Execution
OpenClaw executes:
await import('/app/../../../../../../tmp/shell.mjs')
The Node.js process loads our script. Since this happens in the main thread, we have full access to the application's memory, environment variables (secrets!), and the underlying OS shell.
This is a "Game Over" vulnerability. Because OpenClaw is an AI assistant, it likely holds significant privileges.
The severity is mitigated only by the fact that the attacker needs access to the configuration API first. However, in many self-hosted instances, this API might be exposed to the internal network without authentication.
If you are running OpenClaw, check your version immediately. If it is prior to v2026.2.14, you are vulnerable.
Remediation Steps:
v2026.2.14.config.json or database for any suspicious hook mappings. Look for module paths containing .. or pointing to /tmp.The patch effectively neutralizes the threat by enforcing strict path validation. Even if an attacker modifies the config, the loader will refuse to touch files outside the designated hooks/transforms directory.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenClaw OpenClaw | < 2026.2.14 | 2026.2.14 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-73 / CWE-94 |
| Attack Vector | Network (Configuration API) |
| CVSS | 9.1 (Critical) |
| Impact | Remote Code Execution (RCE) |
| Exploit Status | PoC Available (Patch Tests) |
| Platform | Node.js / TypeScript |