CVE-2026-35632: OpenClaw Symlink Traversal Vulnerability

MODERATE
Advisory Identifier: GHSA-7xr2-q9vf-x4r5
CVSS 7.1
CWE-61
Published
Advisory Summary

CVE-2026-35632 is a MODERATE (CVSS 7.1) symlink traversal vulnerability (CWE-61: UNIX Symbolic Link (Symlink) Following) affecting OpenClaw libraries in the npm ecosystem. The issue involves symlink traversal via identity.md appendfile in agents.create/update (incomplete fix for cve-2026-32013). Remediation is available in the latest vendor maintenance releases.

CVE-2026-35632 at a Glance

CVE Identifier CVE-2026-35632
GHSA Identifier GHSA-7xr2-q9vf-x4r5
Severity MODERATE
CVSS v3.1 Base Score 7.1
CWE Classification CWE-61: UNIX Symbolic Link (Symlink) Following
Affected Product OpenClaw
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 7.1

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H).

Attack Vector Local (AV:L)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity High (I:H)
Availability High (A:H)

How to Fix CVE-2026-35632

To remediate this vulnerability, upgrade all affected OpenClaw dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

openclaw fixed: Latest secure release
npm install openclaw@Latest secure release
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls openclaw

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-35632, inspect your project dependencies using npm:

npm ls openclaw

Analyze the terminal output to locate any version of OpenClaw in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.

Note: The npm ls openclaw command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-61: UNIX Symbolic Link (Symlink) Following, where the product, when opening a file or directory, does not sufficiently account for when the file is a symbolic link that resolves to a target outside of the intended control sphere. this could allow an attacker to cause the product to operate on unauthorized files. In OpenClaw, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary The patch for CVE-2026-32013 introduced symlink resolution and workspace boundary enforcement for `agents.files.get` and `agents.files.set`. However, two other handlers in the same file (`agents.create` and `agents.update`) still use raw `fs.appendFile` on the `IDENTITY.md` file **without any symlink containment check**. An attacker who can place a symlink in the agent workspace can hijack the `IDENTITY.md` path to append attacker-controlled content to arbitrary files on the system. ### Details In `src/gateway/server-methods/agents.ts`, the `agents.create` handler constructs the identity path and appends agent metadata without verifying symlinks: ```typescript // agents.create — line 283-291 const identityPath = path.join(workspaceDir, DEFAULT_IDENTITY_FILENAME); const lines = [ "", `- Name: ${safeName}`, ...(emoji ? [`- Emoji: ${sanitizeIdentityLine(emoji)}`] : []), ...(avatar ? [`- Avatar: ${sanitizeIdentityLine(avatar)}`] : []), "", ]; await fs.appendFile(identityPath, lines.join("\n"), "utf-8"); // ← NO SYMLINK CHECK ``` The `agents.update` handler has the same issue at line 348-349: ```typescript // agents.update — line 348-349 const identityPath = path.join(workspace, DEFAULT_IDENTITY_FILENAME); await fs.appendFile(identityPath, `\n- Avatar: ${sanitizeIdentityLine(avatar)}\n`, "utf-8"); // ← NO SYMLINK CHECK ``` `fs.appendFile` follows symlinks by default. If the `IDENTITY.md` file in the workspace is a symlink pointing to a sensitive file (e.g., `/etc/crontab`, `~/.bashrc`, or `~/.ssh/authorized_keys`), calling `agents.create` will append the agent identity metadata to that file. The `ensureAgentWorkspace` function (called at line 274 before the append) uses exclusive-create mode (`flag: 'wx'`) for `IDENTITY.md`. If a symlink already exists at that path, the `EEXIST` error is silently caught, and the subsequent `fs.appendFile` follows the symlink. **Attack flow:** ``` 1. Attacker plants symlink: workspace/IDENTITY.md → /etc/crontab 2. ensureAgentWorkspace skips creation (EEXIST from symlink) 3. fs.appendFile follows symlink → writes to /etc/crontab 4. Attacker-controlled content (name, emoji, avatar) injected into crontab → RCE ``` ### PoC **Prerequisites:** Docker and Python 3 installed. **Step 1: Build and start the test environment.** ```bash cd llm-enhance/cve-finding/RCE/CVE-2026-32013-identity-appendFile-variant-exp/ docker compose up -d --build sleep 3 ``` **Step 2: Run the exploit.** ```bash python3 poc_exploit.py ``` This script: 1. Plants a symlink `IDENTITY.md → /etc/target-file.txt` inside the agent workspace 2. Calls the `agents.create` API endpoint via HTTP POST 3. Verifies that the agent identity metadata was appended to `/etc/target-file.txt` **Step 3: Run the control experiment.** ```bash python3 control-patched_realpath.py ``` **Step 4: Cleanup.** ```bash docker compose down ``` ### Log of Evidence **Exploit output:** ``` === CVE-2026-32013 Variant: Symlink Traversal via IDENTITY.md appendFile === [*] Planting symlink: IDENTITY.md -> /etc/target-file.txt [*] Symlink: lrwxrwxrwx 1 root root 20 /workspaces/evil-agent/IDENTITY.md -> /etc/target-file.txt [*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT [*] Calling agents.create with name='evil-agent'... [*] API response: {'ok': True, 'agentId': 'evil-agent', 'workspace': '/workspaces/evil-agent'} [*] /etc/target-file.txt after exploit: ORIGINAL_SENSITIVE_CONTENT - Name: evil-agent - Emoji: 💀 - Avatar: evil.png [+] SUCCESS! Symlink traversal confirmed. [+] fs.appendFile followed IDENTITY.md symlink and wrote to /etc/target-file.txt [+] Attacker-controlled content injected into arbitrary file. ``` **Control output:** ``` === CONTROL: Patched agents.create blocks symlink traversal === [*] Planting symlink: IDENTITY.md -> /etc/target-file.txt [*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT [*] Calling PATCHED agents.create with name='safe-agent'... [*] API response: {'ok': False, 'error': 'symlink_traversal_blocked', 'realPath': '/etc/target-file.txt'} [*] /etc/target-file.txt after patched call: ORIGINAL_SENSITIVE_CONTENT [+] CONTROL PASSED: Patched endpoint detected and blocked symlink traversal. [+] /etc/target-file.txt remains unchanged. ``` ### Impact An attacker who can plant a symlink in the agent workspace directory can use the `agents.create` or `agents.update` gateway API to **append attacker-controlled content to arbitrary files** on the system. If the target file is: - `/etc/crontab` or user crontab → **Remote Code Execution** - `~/.bashrc` or `~/.profile` → **Persistent code execution on login** - `~/.ssh/authorized_keys` → **Unauthorized SSH access** - Application configuration files → **Service disruption** The attacker-controlled content includes the agent name (arbitrary string), emoji, and avatar fields, which are only lightly sanitized (whitespace normalization via `sanitizeIdentityLine`). ### Affected products - **Ecosystem**: npm - **Package name**: openclaw - **Affected versions**: <= 2026.2.22 - **Patched versions**: None ### Occurrences | Permalink | Description | | :--- | :--- | | [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291) | `agents.create` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. | | [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349) | `agents.update` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. | | [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274) | `ensureAgentWorkspace` is called before append, but its exclusive-create (`wx`) flag silently skips existing symlinks (EEXIST). |

CVE-2026-35632 Affected OpenClaw Versions

1 component(s)
Product / Package Ecosystem Affected Versions Fixed Version
openclaw
npm
≤ 2026.2.22

References

Frequently Asked Questions

What is CVE-2026-35632?
CVE-2026-35632 is a security vulnerability in OpenClaw involving Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013) under CWE-61: UNIX Symbolic Link (Symlink) Following.
Which OpenClaw versions are affected?
Affected versions include releases prior to current release patches across affected packages: openclaw.
What version fixes CVE-2026-35632?
Upgrading to current release patches (or the latest patched release for your respective branch) resolves the vulnerability.
Is openclaw affected?
Yes, openclaw is affected in releases prior to Latest secure release. Upgrade your dependency to Latest secure release or later.
What is the CVSS score of CVE-2026-35632?
CVE-2026-35632 has a CVSS v3.1 base score of 7.1 (MODERATE) with vector string CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H.
What CWE is associated with CVE-2026-35632?
CVE-2026-35632 is classified under CWE-61: UNIX Symbolic Link (Symlink) Following (The product, when opening a file or directory, does not sufficiently account for when the file is a symbolic link that resolves to a target outside of the intended control sphere. This could allow an attacker to cause the product to operate on unauthorized files.).
How can I check npm dependencies for CVE-2026-35632?
Run the dependency tree command: 'npm ls openclaw'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-7xr2-q9vf-x4r5",
  "modified" : "2026-04-18T00:43:06Z",
  "published" : "2026-03-26T21:49:25Z",
  "aliases" : [ "CVE-2026-35632" ],
  "summary" : "OpenClaw: Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013)",
  "details" : "### Summary\n\nThe patch for CVE-2026-32013 introduced symlink resolution and workspace boundary enforcement for `agents.files.get` and `agents.files.set`. However, two other handlers in the same file (`agents.create` and `agents.update`) still use raw `fs.appendFile` on the `IDENTITY.md` file **without any symlink containment check**. An attacker who can place a symlink in the agent workspace can hijack the `IDENTITY.md` path to append attacker-controlled content to arbitrary files on the system.\n\n### Details\n\nIn `src/gateway/server-methods/agents.ts`, the `agents.create` handler constructs the identity path and appends agent metadata without verifying symlinks:\n\n```typescript\n// agents.create — line 283-291\nconst identityPath = path.join(workspaceDir, DEFAULT_IDENTITY_FILENAME);\nconst lines = [\n  \"\",\n  `- Name: ${safeName}`,\n  ...(emoji ? [`- Emoji: ${sanitizeIdentityLine(emoji)}`] : []),\n  ...(avatar ? [`- Avatar: ${sanitizeIdentityLine(avatar)}`] : []),\n  \"\",\n];\nawait fs.appendFile(identityPath, lines.join(\"\\n\"), \"utf-8\"); // ← NO SYMLINK CHECK\n```\n\nThe `agents.update` handler has the same issue at line 348-349:\n\n```typescript\n// agents.update — line 348-349\nconst identityPath = path.join(workspace, DEFAULT_IDENTITY_FILENAME);\nawait fs.appendFile(identityPath, `\\n- Avatar: ${sanitizeIdentityLine(avatar)}\\n`, \"utf-8\"); // ← NO SYMLINK CHECK\n```\n\n`fs.appendFile` follows symlinks by default. If the `IDENTITY.md` file in the workspace is a symlink pointing to a sensitive file (e.g., `/etc/crontab`, `~/.bashrc`, or `~/.ssh/authorized_keys`), calling `agents.create` will append the agent identity metadata to that file.\n\nThe `ensureAgentWorkspace` function (called at line 274 before the append) uses exclusive-create mode (`flag: 'wx'`) for `IDENTITY.md`. If a symlink already exists at that path, the `EEXIST` error is silently caught, and the subsequent `fs.appendFile` follows the symlink.\n\n**Attack flow:**\n```\n1. Attacker plants symlink: workspace/IDENTITY.md → /etc/crontab\n2. ensureAgentWorkspace skips creation (EEXIST from symlink)\n3. fs.appendFile follows symlink → writes to /etc/crontab\n4. Attacker-controlled content (name, emoji, avatar) injected into crontab → RCE\n```\n\n### PoC\n\n**Prerequisites:** Docker and Python 3 installed.\n\n**Step 1: Build and start the test environment.**\n```bash\ncd llm-enhance/cve-finding/RCE/CVE-2026-32013-identity-appendFile-variant-exp/\ndocker compose up -d --build\nsleep 3\n```\n\n**Step 2: Run the exploit.**\n```bash\npython3 poc_exploit.py\n```\n\nThis script:\n1. Plants a symlink `IDENTITY.md → /etc/target-file.txt` inside the agent workspace\n2. Calls the `agents.create` API endpoint via HTTP POST\n3. Verifies that the agent identity metadata was appended to `/etc/target-file.txt`\n\n**Step 3: Run the control experiment.**\n```bash\npython3 control-patched_realpath.py\n```\n\n**Step 4: Cleanup.**\n```bash\ndocker compose down\n```\n\n### Log of Evidence\n\n**Exploit output:**\n```\n=== CVE-2026-32013 Variant: Symlink Traversal via IDENTITY.md appendFile ===\n[*] Planting symlink: IDENTITY.md -> /etc/target-file.txt\n[*] Symlink: lrwxrwxrwx 1 root root 20 /workspaces/evil-agent/IDENTITY.md -> /etc/target-file.txt\n[*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT\n\n[*] Calling agents.create with name='evil-agent'...\n[*] API response: {'ok': True, 'agentId': 'evil-agent', 'workspace': '/workspaces/evil-agent'}\n\n[*] /etc/target-file.txt after exploit:\n    ORIGINAL_SENSITIVE_CONTENT\n\n- Name: evil-agent\n- Emoji: 💀\n- Avatar: evil.png\n\n[+] SUCCESS! Symlink traversal confirmed.\n[+] fs.appendFile followed IDENTITY.md symlink and wrote to /etc/target-file.txt\n[+] Attacker-controlled content injected into arbitrary file.\n```\n\n**Control output:**\n```\n=== CONTROL: Patched agents.create blocks symlink traversal ===\n[*] Planting symlink: IDENTITY.md -> /etc/target-file.txt\n[*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT\n\n[*] Calling PATCHED agents.create with name='safe-agent'...\n[*] API response: {'ok': False, 'error': 'symlink_traversal_blocked', 'realPath': '/etc/target-file.txt'}\n\n[*] /etc/target-file.txt after patched call: ORIGINAL_SENSITIVE_CONTENT\n\n[+] CONTROL PASSED: Patched endpoint detected and blocked symlink traversal.\n[+] /etc/target-file.txt remains unchanged.\n```\n\n### Impact\n\nAn attacker who can plant a symlink in the agent workspace directory can use the `agents.create` or `agents.update` gateway API to **append attacker-controlled content to arbitrary files** on the system. If the target file is:\n\n- `/etc/crontab` or user crontab → **Remote Code Execution**\n- `~/.bashrc` or `~/.profile` → **Persistent code execution on login**\n- `~/.ssh/authorized_keys` → **Unauthorized SSH access**\n- Application configuration files → **Service disruption**\n\nThe attacker-controlled content includes the agent name (arbitrary string), emoji, and avatar fields, which are only lightly sanitized (whitespace normalization via `sanitizeIdentityLine`).\n\n### Affected products\n- **Ecosystem**: npm\n- **Package name**: openclaw\n- **Affected versions**: <= 2026.2.22\n- **Patched versions**: None\n\n### Occurrences\n\n| Permalink | Description |\n| :--- | :--- |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291) | `agents.create` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349) | `agents.update` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274) | `ensureAgentWorkspace` is called before append, but its exclusive-create (`wx`) flag silently skips existing symlinks (EEXIST). |",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
  }, {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "openclaw"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "last_affected" : "2026.2.22"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/openclaw/openclaw/security/advisories/GHSA-7xr2-q9vf-x4r5"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-35632"
  }, {
    "type" : "ADVISORY",
    "url" : "https://github.com/advisories/GHSA-fgvx-58p6-gjwc"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/openclaw/openclaw"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349"
  }, {
    "type" : "WEB",
    "url" : "https://www.vulncheck.com/advisories/openclaw-symlink-traversal-via-identity-md-appendfile-in-agents-create-update"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-61" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-03-26T21:49:25Z",
    "nvd_published_at" : null
  }
}