Skip to content

Commit a4633df

Browse files

File tree

5 files changed

+233
-47
lines changed

5 files changed

+233
-47
lines changed

advisories/github-reviewed/2026/03/GHSA-7xr2-q9vf-x4r5/GHSA-7xr2-q9vf-x4r5.json

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-7xr2-q9vf-x4r5",
4-
"modified": "2026-03-26T21:49:25Z",
4+
"modified": "2026-04-18T00:43:06Z",
55
"published": "2026-03-26T21:49:25Z",
6-
"aliases": [],
6+
"aliases": [
7+
"CVE-2026-35632"
8+
],
79
"summary": "OpenClaw: Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013)",
810
"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). |",
911
"severity": [
1012
{
1113
"type": "CVSS_V3",
1214
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
15+
},
16+
{
17+
"type": "CVSS_V4",
18+
"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"
1319
}
1420
],
1521
"affected": [
@@ -38,6 +44,10 @@
3844
"type": "WEB",
3945
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-7xr2-q9vf-x4r5"
4046
},
47+
{
48+
"type": "ADVISORY",
49+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35632"
50+
},
4151
{
4252
"type": "ADVISORY",
4353
"url": "https://github.com/advisories/GHSA-fgvx-58p6-gjwc"
@@ -57,13 +67,17 @@
5767
{
5868
"type": "WEB",
5969
"url": "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349"
70+
},
71+
{
72+
"type": "WEB",
73+
"url": "https://www.vulncheck.com/advisories/openclaw-symlink-traversal-via-identity-md-appendfile-in-agents-create-update"
6074
}
6175
],
6276
"database_specific": {
6377
"cwe_ids": [
6478
"CWE-61"
6579
],
66-
"severity": "HIGH",
80+
"severity": "MODERATE",
6781
"github_reviewed": true,
6882
"github_reviewed_at": "2026-03-26T21:49:25Z",
6983
"nvd_published_at": null
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-pmf3-2q63-jmp6",
4+
"modified": "2026-04-18T00:42:18Z",
5+
"published": "2026-04-10T00:30:30Z",
6+
"withdrawn": "2026-04-18T00:42:18Z",
7+
"aliases": [],
8+
"summary": "Duplicate Advisory: OpenClaw: Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013)",
9+
"details": "## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-7xr2-q9vf-x4r5. This link is maintained to preserve external references.\n\n## Original Description\nOpenClaw through 2026.2.22 contains a symlink traversal vulnerability in agents.create and agents.update handlers that use fs.appendFile on IDENTITY.md without symlink containment checks. Attackers with workspace access can plant symlinks to append attacker-controlled content to arbitrary files, enabling remote code execution via crontab injection or unauthorized access via SSH key manipulation.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
14+
},
15+
{
16+
"type": "CVSS_V4",
17+
"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X"
18+
}
19+
],
20+
"affected": [
21+
{
22+
"package": {
23+
"ecosystem": "npm",
24+
"name": "openclaw"
25+
},
26+
"ranges": [
27+
{
28+
"type": "ECOSYSTEM",
29+
"events": [
30+
{
31+
"introduced": "0"
32+
},
33+
{
34+
"last_affected": "2026.2.22"
35+
}
36+
]
37+
}
38+
]
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-7xr2-q9vf-x4r5"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35632"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://www.vulncheck.com/advisories/openclaw-symlink-traversal-via-identity-md-appendfile-in-agents-create-update"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-61"
58+
],
59+
"severity": "MODERATE",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-04-18T00:42:18Z",
62+
"nvd_published_at": "2026-04-09T22:16:32Z"
63+
}
64+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-xr93-pcq3-pxf8",
4+
"modified": "2026-04-18T00:42:05Z",
5+
"published": "2026-04-18T00:42:05Z",
6+
"aliases": [
7+
"CVE-2026-40881"
8+
],
9+
"summary": "Zebra: addr/addrv2 Deserialization Resource Exhaustion",
10+
"details": "# CVE-2026-40881: addr/addrv2 Deserialization Resource Exhaustion\n\n## Summary\n\nWhen deserializing `addr` or `addrv2` messages, which contain vectors of addresses, Zebra would fully deserialize them up to a maximum length (over 233,000) that was derived from the 2 MiB message size limit. This is much larger than the actual limit of 1,000 messages from the specification. Zebra would eventually check that limit but, at that point, the memory for the larger vector was already allocated. An attacker could cause out-of-memory aborts in Zebra by sending multiple such messages over different connections.\n\n## Severity\n\n**Moderate** - This is a Denial of Service Vulnerability that could allow an attacker to crash a Zebra node.\n\n## Affected Versions\n\nAll Zebra versions prior to **version 4.3.1**.\n\n## Description\n\nThe vulnerability exists in the `read_addr/addrv2` functions in `codec.rs`. It deserializes a vector of addresses with the `zcash_deserialize()` trait method, which uses as a upper bound the result of `T::max_allocation()`. For theses types, it was derived from dividing the max message size (2 MiB) by the minimum serialized size of one entry. For AddrV1: 2_097_152 / 30 = 69,904. For AddrV2: 2_097_152 / 9 = 233,016. Only after deserialization was the `MAX_ADDRS_IN_MESSAGE = 1000` limit checked.\n\nAn attacker could exploit this by:\n1. Creating `addr` or `addrv2` messages with a large number of entries.\n2. Submitting them to a Zebra node, possibly through multiple connections, to attempt to get Zebra into an out-of-memory state.\n\n## Impact\n\n**Denial of Service**\n\n* **Attack Vector:** Network.\n* **Effect:** Zebra node crash.\n* **Scope:** Any impacted Zebra node.\n\n## Fixed Versions\n\nThis issue is fixed in **Zebra 4.3.1**. \n\nThe fix changes the `max_allocation()` method for the relevant types to return 1,000, thus blocking larger values prior to deserialization.\n\n## Mitigation\n\nUsers should upgrade to **Zebra 4.3.1** or later immediately. \n\nThere are no known workarounds for this issue. Immediate upgrade is the only way to ensure the node remains not vulnerable to the denial of service attack.\n\n## Credits\n\nThanks @Zk-nd3r for finding and reporting the issue, and suggesting the fix.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "crates.io",
21+
"name": "zebrad"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "4.3.1"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "crates.io",
40+
"name": "zebra-network"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"fixed": "5.0.1"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/ZcashFoundation/zebra/security/advisories/GHSA-xr93-pcq3-pxf8"
61+
},
62+
{
63+
"type": "PACKAGE",
64+
"url": "https://github.com/ZcashFoundation/zebra"
65+
}
66+
],
67+
"database_specific": {
68+
"cwe_ids": [
69+
"CWE-770"
70+
],
71+
"severity": "MODERATE",
72+
"github_reviewed": true,
73+
"github_reviewed_at": "2026-04-18T00:42:05Z",
74+
"nvd_published_at": null
75+
}
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-xvj8-ph7x-65gf",
4+
"modified": "2026-04-18T00:41:54Z",
5+
"published": "2026-04-18T00:41:54Z",
6+
"aliases": [
7+
"CVE-2026-40880"
8+
],
9+
"summary": "Zebra: Cached Mempool Verification Bypasses Consensus Rules for Ahead-of-Tip Blocks",
10+
"details": "# CVE-2026-40880: Cached Mempool Verification Bypasses Consensus Rules for Ahead-of-Tip Blocks\n\n## Summary\n\nA logic error in Zebra's transaction verification cache could allow a malicious miner to induce a consensus split. By carefully submitting a transaction that is valid for height `H+1` but invalid for `H+2` and then mining that transaction in a block at height `H+2`, a miner could cause vulnerable Zebra nodes to accept an invalid block, leading to a consensus split from the rest of the Zcash network.\n\n## Severity\n\nHigh - This is a Consensus Vulnerability that could allow a malicious miner to induce network partitioning, service disruption, and potential double-spend attacks against affected nodes.\n\n## Affected Versions\n\nAll Zebra versions prior to version 4.3.1. (Some older versions are not affected but are no longer supported by the network)\n\n## Description\n\nThe vulnerability exists due to a performance optimization whose goal is to improve performance of transaction validation if the transaction was previously accepted into the mempool (and thus was verified as valid). That however did not take into account that a transaction can be valid for a specific height, but invalid at higher heights; for example, it can contain an expiry height, a lock time, and it is always bound to a network upgrade, all of which are height-dependant.\n\nAn attacker (specifically a malicious miner) could exploit this by (e.g. in the expiry height case):\n\n- Submitting a transaction with expiry height `H+1` (where `H` is the height of the current tip)\n- Mining a block `H+1`, and a block `H+2` that contains that same transaction, and submitting block `H+2` before `H+1`\n- Zebra nodes would accept `H+2` as valid (pending contextual verification) and wait for block `H+1`; when it arrives, Zebra would commit both blocks even if `H+2` contains an expired transaction\n- Other nodes (like `zcashd` or `zebrad` nodes without that transaction in their mempool) reject the block, resulting in a chain fork where the poisoned Zebra node is isolated.\n\n## Impact\n\n**Consensus Failure**\n\n**Attack Vector**: Network (specifically via a malicious miner).\n**Effect**: Network partition/consensus split.\n**Scope**: Any Zebra node utilizing the transaction verification cache optimization for V5 transactions.\n\n## Fixed Versions\n\nThis issue is fixed in **Zebra 4.3.1**.\n\nWe removed the performance optimization altogether, since we deemed it too risky.\n\nThe fix ensures that verification is only skipped if the transaction's full integrity—including authorization data—is validated against the mempool entry.\n\n## Mitigation\n\nUsers should upgrade to Zebra 4.3.0 or later immediately.\n\nThere are no known workarounds for this issue. Immediate upgrade is the only way to ensure the node remains on the correct consensus path and is protected against malicious chain forks.\n\n## Credits\n\nThanks to @sangsoo-osec for a thorough advisory submission that noticed the lock time issue, and to @shieldedonly with an also thorough advisory (that was submitted while we were working on the first one) who noticed that the issue applied to other aspects of the transaction validation.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "crates.io",
21+
"name": "zebra-consensus"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "5.0.2"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "crates.io",
40+
"name": "zebrad"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"fixed": "4.3.1"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/ZcashFoundation/zebra/security/advisories/GHSA-xvj8-ph7x-65gf"
61+
},
62+
{
63+
"type": "PACKAGE",
64+
"url": "https://github.com/ZcashFoundation/zebra"
65+
}
66+
],
67+
"database_specific": {
68+
"cwe_ids": [
69+
"CWE-1025"
70+
],
71+
"severity": "HIGH",
72+
"github_reviewed": true,
73+
"github_reviewed_at": "2026-04-18T00:41:54Z",
74+
"nvd_published_at": null
75+
}
76+
}

0 commit comments

Comments
 (0)