Staging Environment: Content and features may be unstable or change without notice.
Advisory details: github_osv / GHSA-7xr2-q9vf-x4r5
Advisory ID github_osv/GHSA-7xr2-q9vf-x4r5
Aliases CVE-2026-35632
Summary OpenClaw: Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013) ### 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). |
Status Published
Exploitability 0.5
Weighted Severity 6.4
Risk 3.2
Affected and Fixed Packages Package Details
Introduced and Fixed Package Commit Patches Package Commit Patches Details
Weaknesses (1)
No exploits are available.

No EPSS data available for this advisory.

Patch URL
There are no known patches.
Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H Found at https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-7xr2-q9vf-x4r5/GHSA-7xr2-q9vf-x4r5.json
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: 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 Found at https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-7xr2-q9vf-x4r5/GHSA-7xr2-q9vf-x4r5.json
Attack Vector (AV) Attack Complexity (AC) Attack Requirements (AT) Privileges Required (PR) User Interaction (UI) Vulnerable System Impact Confidentiality (VC) Vulnerable System Impact Integrity (VI) Vulnerable System Impact Availability (VA) Subsequent System Impact Confidentiality (SC) Subsequent System Impact Integrity (SI) Subsequent System Impact Availability (SA)

network

adjacent

local

physical

low

high

none

present

none

low

high

none

passive

active

high

low

none

high

low

none

high

low

none

high

low

none

high

low

none

high

low

none

Vector: SSVCv2/E:P/A:N/T:T/P:M/B:A/M:M/D:R/2026-04-10T13:59:19Z/

Decision: Track*

Source URL: https://github.com/cisagov/vulnrichment/blob/develop/2026/35xxx/CVE-2026-35632.json

Source Advisory: vulnrichment/CVE-2026-35632

View SSVC decision tree
[{'Exploitation': 'poc'},
 {'Automatable': 'no'},
 {'Technical Impact': 'total'},
 {'Mission Prevalence': 'minimal'},
 {'Public Well-being Impact': 'material'},
 {'Mission & Well-being': 'medium'}]