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-659F-22XC-98F2

GHSA-659F-22XC-98F2: Path Traversal via Symbolic Links in OpenClaw Webhook Transforms

Alon Barad
Alon Barad
Software Engineer

Mar 4, 2026·6 min read·15 visits

Executive Summary (TL;DR)

OpenClaw's webhook transform loader failed to resolve symbolic links, allowing attackers to bypass directory restrictions. By linking a valid path to an external malicious file, attackers could achieve Remote Code Execution. The issue was patched by enforcing `realpath` verification on module paths.

A critical path traversal vulnerability exists in the OpenClaw infrastructure, specifically within the webhook transform module loader. The vulnerability arises from improper resolution of symbolic links when validating module paths against a restricted directory allowlist. By creating a symbolic link within the allowed directory that points to a file outside of it, an attacker can bypass the containment check and force the application to load and execute arbitrary JavaScript or TypeScript files from the filesystem. This flaw allows for Remote Code Execution (RCE) if an attacker can introduce a symbolic link into the configured transforms directory.

Vulnerability Overview

The OpenClaw platform provides a webhook gateway that allows users to define "transform" modules. These modules are JavaScript or TypeScript files used to process incoming webhook payloads before they are forwarded to their final destination. To ensure security, the system enforces a containment policy, requiring that all transform modules reside within a specific directory, typically defined in hooks.transformsDir.

The vulnerability, identified as GHSA-659F-22XC-98F2, resides in the logic responsible for enforcing this containment. The validation mechanism relied solely on lexical path analysis to determine if a requested module path was inside the authorized directory. Lexical analysis treats paths as strings and does not query the filesystem to determine the actual physical location of the file.

Consequently, the system failed to detect symbolic links (symlinks) that traverse out of the allowed directory. If an attacker can create a symlink within the transformsDir that points to a file elsewhere on the system (such as /tmp/malicious.js or system configuration files), the lexical check would pass because the symlink's path string appears valid. When the application subsequently loads the module using Node.js's dynamic import() or require(), the runtime follows the symlink and executes the target code, resulting in arbitrary code execution or information disclosure.

Root Cause Analysis

The root cause of this vulnerability is the use of path.relative() for security boundary checks without resolving the canonical path of the input. This is a classic instance of CWE-59: Improper Link Resolution Before File Access.

The vulnerable code essentially performed the following check:

  1. Resolve the absolute path of the allowed directory (base).
  2. Resolve the absolute path of the requested module string (target).
  3. Calculate the relative path from base to target.
  4. Verify that the relative path does not start with ...

While this logic correctly handles directory traversal characters (e.g., ../../etc/passwd) in the string itself, it ignores the filesystem layer. In Unix-like systems, a file at /app/hooks/transforms/link.js can be a symbolic link to /etc/passwd.

From the perspective of path.resolve and path.relative, /app/hooks/transforms/link.js is strictly inside /app/hooks/transforms. The standard library's path manipulation functions operate on the abstract string representation of the path. They do not stat the file or check for inode redirection. The security check therefore validated the pointer (the symlink name) rather than the destination (the actual file). When the runtime later accessed the file to load the code, the operating system resolved the link, effectively bypassing the application's intended sandbox.

Code Analysis

The remediation involved moving from a lexical check to a physical filesystem check using fs.realpath. The following analysis highlights the critical changes in src/gateway/hooks-mapping.ts.

Vulnerable Logic

The original implementation relied on path.resolve and path.relative. Note the absence of filesystem calls (fs.*) in the validation phase:

// VULNERABLE IMPLEMENTATION
function resolveContainedPath(baseDir: string, target: string, label: string): string {
  const base = path.resolve(baseDir);
  const resolved = resolvePath(base, target);
  
  // BUG: Lexical check only. If 'resolved' is a symlink, 
  // path.relative calculates the distance to the link, not the target.
  const relative = path.relative(base, resolved);
  if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
    throw new Error(`${label} module path must be within ${base}`);
  }
  return resolved;
}

Patched Logic

The fix introduces safeRealpathSync to resolve the canonical path (stripping away symlinks) before performing the containment check. It also includes resolveExistingAncestor to handle cases where the full path might not exist yet but the traversal occurs in a parent directory.

// PATCHED IMPLEMENTATION
function resolveContainedPath(baseDir: string, target: string, label: string): string {
  const base = path.resolve(baseDir);
  // ... (initial resolution)
 
  // 1. Resolve the real physical path of the base directory
  const baseRealpath = safeRealpathSync(base);
  
  // 2. Resolve the real physical path of the target (or its nearest existing ancestor)
  const existingAncestor = resolveExistingAncestor(resolved);
  const existingAncestorRealpath = existingAncestor ? safeRealpathSync(existingAncestor) : null;
  
  // 3. Verify the physical path is contained within the physical base
  if (
    baseRealpath &&
    existingAncestorRealpath &&
    escapesBase(baseRealpath, existingAncestorRealpath) // Uses path.relative on realpaths
  ) {
    throw new Error(`${label} module path must be within ${base}: ${target}`);
  }
  return resolved;
}

The function escapesBase (helper) re-implements the path.relative check, but because it is now fed the output of fs.realpathSync, the check validates the true location of the file on the disk.

Exploitation & Proof of Concept

To exploit this vulnerability, an attacker requires the ability to create a symbolic link within the configured transformsDir. This could be achieved via a separate file upload vulnerability, compromised developer credentials, or a misconfigured NFS/shared mount.

The following steps demonstrate the attack vector using the provided test case data:

  1. Preparation: The attacker places a malicious JavaScript file outside the restricted directory. For example, /tmp/pwn.mjs containing export default () => process.exit(1) or a reverse shell payload.
  2. Link Creation: The attacker creates a symlink inside the allowed directory (e.g., openclaw/hooks/transforms/innocent.mjs) pointing to /tmp/pwn.mjs.
  3. Trigger: The attacker configures a webhook mapping to use the transform module innocent.mjs.
  4. Execution: OpenClaw validates innocent.mjs. The lexical check confirms it is inside transforms. The loader imports innocent.mjs, forcing Node.js to read and execute /tmp/pwn.mjs.

Official PoC (TypeScript):

// Source: src/gateway/hooks-mapping.test.ts
it.runIf(process.platform !== "win32")(
  "rejects transform module symlink escape outside transformsDir",
  () => {
    // Setup directories
    const configDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-config-"));
    const transformsRoot = path.join(configDir, "hooks", "transforms");
    
    // Create malicious module outside allowed root
    const outsideDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-outside-"));
    const outsideModule = path.join(outsideDir, "evil.mjs");
    fs.writeFileSync(outsideModule, 'export default () => ({ kind: "wake" });');
 
    // Create Symlink inside allowed root -> outside module
    fs.symlinkSync(outsideModule, path.join(transformsRoot, "linked.mjs"));
 
    // Attempt to load
    expect(() =>
      resolveHookMappings(
        { /* ... config using "linked.mjs" ... */ },
        { configDir },
      ),
    ).toThrow(/must be within/);
  },
);

Impact Assessment

The primary impact of this vulnerability is Remote Code Execution (RCE). By successfully loading a module outside the intended directory, an attacker can execute arbitrary code within the context of the OpenClaw application process. This allows for full compromise of the application, access to secrets (database credentials, API keys), and potentially lateral movement within the hosting infrastructure.

While the vulnerability requires the prerequisite of file system manipulation (creating the symlink), this is a common capability in shared development environments or systems allowing user-uploaded content.

Risk Breakdown:

  • Confidentiality: Critical. Attackers can read any file the Node.js process has access to by loading it as a module or using the RCE to read the file system.
  • Integrity: Critical. Attackers can modify application state, intercept webhooks, or alter data in transit.
  • Availability: High. Malicious modules can crash the process or consume resources.

Official Patches

GitHubCommit f4dd057 implementing realpath resolution

Fix Analysis (1)

Technical Appendix

CVSS Score
8.1/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Affected Systems

OpenClaw Webhook Gateway

Affected Versions Detail

Product
Affected Versions
Fixed Version
OpenClaw
OpenClaw
< 2026-02-222026-02-22 Patch
AttributeDetail
CWE IDCWE-59 (Improper Link Resolution)
Attack VectorLocal / Network (via Configuration)
CVSS (Est.)8.1 (High)
ImpactRemote Code Execution (RCE)
Exploit StatusPoC Available
PlatformNode.js / TypeScript

MITRE ATT&CK Mapping

T1210Exploitation of Remote Services
Lateral Movement
T1059Command and Scripting Interpreter
Execution
T1574Hijack Execution Flow
Persistence
CWE-59
Improper Link Resolution Before File Access ('Link Following')

Known Exploits & Detection

GitHub Repository TestsOfficial unit test demonstrating symlink escape in hooks-mapping.test.ts

Vulnerability Timeline

Vulnerability Disclosed
2026-02-22
Patch Committed
2026-02-22

References & Sources

  • [1]GHSA-659F-22XC-98F2 Advisory
  • [2]OpenClaw Repository

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.

More Reports

•8 days ago•CVE-2026-9354
6.9

CVE-2026-9354: Arbitrary Mass Mention Bypass in NousResearch hermes-agent Slack and Mattermost Adapters

A vulnerability in the Slack and Mattermost platform adapters for NousResearch hermes-agent permits an unauthenticated remote attacker to execute arbitrary mass mentions. By leveraging prompt injection, an attacker can bypass output sanitization logic and trigger workspace-wide notification exhaustion.

Alon Barad
Alon Barad
37 views•6 min read
•9 days ago•CVE-2026-9306
6.3

CVE-2026-9306: Unauthenticated Insecure Direct Object Reference (IDOR) in QuantumNous new-api Midjourney Relay

CVE-2026-9306 is a critical unauthenticated Insecure Direct Object Reference (IDOR) vulnerability located in the QuantumNous new-api application, affecting versions up to and including 0.12.1. The flaw is caused by improper middleware ordering combined with a lack of object-level authorization checks. This allows remote, unauthenticated attackers to retrieve sensitive Midjourney images belonging to other users by supplying a valid task identifier.

Amit Schendel
Amit Schendel
16 views•5 min read
•10 days ago•GHSA-GGXF-37HM-9WQF
6.5

GHSA-GGXF-37HM-9WQF: Session Leakage via Unsafe Challenge Path Parsing in instagrapi

The instagrapi library prior to version 2.6.9 contains an improper input validation vulnerability within its challenge handling mechanism. Maliciously crafted server responses can manipulate the client into forwarding session cookies and credentials to an external attacker-controlled domain.

Amit Schendel
Amit Schendel
21 views•6 min read
•10 days ago•GHSA-QQQM-5547-774X
9.1

GHSA-QQQM-5547-774X: Unauthenticated Path Traversal in FileBrowser Quantum PATCH Handler

GHSA-QQQM-5547-774X is a critical path traversal vulnerability in the FileBrowser Quantum application, specifically within the Go backend package. The vulnerability resides in the HTTP handler responsible for processing bulk file modifications via the public API. Unauthenticated attackers can exploit an order-of-operations flaw in the path sanitization logic to bypass intended directory restrictions. This allows adversaries to arbitrarily read, move, and overwrite files on the underlying filesystem by supplying specially crafted HTTP PATCH requests.

Alon Barad
Alon Barad
11 views•6 min read
•10 days ago•CVE-2026-8723
5.3

CVE-2026-8723: Synchronous Denial of Service in qs npm Package via TypeError

The qs query string parsing and serialization library for Node.js is vulnerable to a synchronous Denial of Service (DoS) attack. The vulnerability manifests as a process-terminating TypeError when processing arrays with null or undefined elements under specific configuration parameters.

Amit Schendel
Amit Schendel
38 views•7 min read
•10 days ago•GHSA-7M8F-HGJQ-8GC9
7.5

GHSA-7M8F-HGJQ-8GC9: Pre-Authentication Denial of Service via Insecure Deserialization Order in aiosend

The aiosend library prior to version 3.0.6 contains a pre-authentication Denial of Service (DoS) vulnerability in its webhook handling mechanism. The software processes and deserializes incoming JSON payloads before verifying the cryptographic signature, allowing unauthenticated attackers to exhaust server CPU and memory resources by sending large, complex payloads.

Amit Schendel
Amit Schendel
4 views•6 min read