GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Common Weakness Enumeration

CWE-61

Allowed

UNIX Symbolic Link (Symlink) Following

Abstraction: Compound · Status: Incomplete

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.

301 vulnerabilities reference this CWE, most recent first.

GHSA-F794-5JV7-7672

Vulnerability from github – Published: 2026-09-02 14:35 – Updated: 2026-09-02 14:35
VLAI
Summary
NLTK: Downloader.download follows hardlinks and overwrites outside-root files
Details

Summary

NLTK's downloader now blocks symlink escapes during ZIP extraction, but it still treats pre-existing hardlinks inside the install tree as ordinary in-root files. A normal package install can therefore overwrite an outside-root inode through that hardlink.

Details

  • Vulnerability type: Filesystem containment bypass
  • Affected component: nltk.downloader.Downloader.download, nltk.downloader.Downloader.incr_download
  • Affected versions: Published 3.9.4 and current source v3.10.0-rc2 both reproduced for the extraction-stage overwrite.
  • Patched versions: 3.10.3
  • Root cause: The downloader validates traversal and symlink conditions but does not reject pre-existing hardlink aliases inside the install tree.

The install flow correctly rejects a pre-existing symlink at an extraction target, yet it accepts a pre-existing hardlink at the same path. When the package is installed, extracted member data is written through the hardlink and mutates the outside inode.

PoC

Preconditions - The attacker can plant files inside a writable shared downloader root on the same filesystem as the target file.

Steps 1. Prepare a downloader root and create a hardlink inside it that points to an outside target file. 2. Confirm a symlink at the same path is rejected as a negative control. 3. Run a normal Downloader.download() package install whose extracted member lands on the hardlink path. 4. Observe the outside target file is overwritten while the downloader still reports the package as installed.

Minimal reproducible excerpt

extract_hardlink_before ORIGINAL
extract_hardlink_after PWNED
extract_hardlink_status installed

Impact

A shared or attacker-influenced downloader directory can be turned into an overwrite primitive against same-filesystem files outside the intended install root.

Remediation

Treat pre-existing hardlinks as unsafe in extraction targets, verify that each write path stays within the intended install tree at the inode level, and add regression tests that pair hardlinks with existing symlink controls.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.10.2"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "nltk"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.10.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-81727"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61",
      "CWE-73"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-02T14:35:41Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nNLTK\u0027s downloader now blocks symlink escapes during ZIP extraction, but it still treats pre-existing hardlinks inside the install tree as ordinary in-root files. A normal package install can therefore overwrite an outside-root inode through that hardlink.\n\n### Details\n\n- **Vulnerability type:** Filesystem containment bypass\n- **Affected component:** `nltk.downloader.Downloader.download`, `nltk.downloader.Downloader.incr_download`\n- **Affected versions:** Published `3.9.4` and current source `v3.10.0-rc2` both reproduced for the extraction-stage overwrite.\n- **Patched versions:** 3.10.3\n- **Root cause:** The downloader validates traversal and symlink conditions but does not reject pre-existing hardlink aliases inside the install tree.\n\nThe install flow correctly rejects a pre-existing symlink at an extraction target, yet it accepts a pre-existing hardlink at the same path. When the package is installed, extracted member data is written through the hardlink and mutates the outside inode.\n\n### PoC\n\n**Preconditions**\n- The attacker can plant files inside a writable shared downloader root on the same filesystem as the target file.\n\n**Steps**\n1. Prepare a downloader root and create a hardlink inside it that points to an outside target file.\n2. Confirm a symlink at the same path is rejected as a negative control.\n3. Run a normal `Downloader.download()` package install whose extracted member lands on the hardlink path.\n4. Observe the outside target file is overwritten while the downloader still reports the package as installed.\n\n**Minimal reproducible excerpt**\n\n```text\nextract_hardlink_before ORIGINAL\nextract_hardlink_after PWNED\nextract_hardlink_status installed\n```\n\n### Impact\n\nA shared or attacker-influenced downloader directory can be turned into an overwrite primitive against same-filesystem files outside the intended install root.\n\n### Remediation\n\nTreat pre-existing hardlinks as unsafe in extraction targets, verify that each write path stays within the intended install tree at the inode level, and add regression tests that pair hardlinks with existing symlink controls.",
  "id": "GHSA-f794-5jv7-7672",
  "modified": "2026-09-02T14:35:41Z",
  "published": "2026-09-02T14:35:41Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/security/advisories/GHSA-f794-5jv7-7672"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-81727"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/pull/3797"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/commit/9e6d5f05902b9aaa1221a0a565448d17a9c9b3e8"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nltk/nltk"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/releases/tag/v3.10.3"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-3741.yaml"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/nltk-before-3.10.3-hardlink-file-overwrite-via-downloader"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "NLTK: Downloader.download follows hardlinks and overwrites outside-root files"
}

GHSA-FV94-QVG8-XQPW

Vulnerability from github – Published: 2026-04-02 21:23 – Updated: 2026-05-06 19:11
VLAI
Summary
OpenClaw: SSH sandbox tar upload follows symlinks, enabling arbitrary file write on remote host
Details

Summary

SSH sandbox tar upload follows symlinks, enabling arbitrary file write on remote host

Current Maintainer Triage

  • Status: open
  • Normalized severity: high
  • Assessment: Real in shipped v2026.3.28: SSH sandbox tar upload lacked pre-upload symlink escape rejection until 3d5af14984 on 2026-03-31; maintainers already accepted it and the fix is unreleased.

Affected Packages / Versions

  • Package: openclaw (npm)
  • Latest published npm version: 2026.3.31
  • Vulnerable version range: <=2026.3.28
  • Patched versions: >= 2026.3.31
  • First stable tag containing the fix: v2026.3.31

Fix Commit(s)

  • 3d5af14984ac1976c747a8e11581d697bd0829dc — 2026-03-31T19:56:45+09:00

OpenClaw thanks @AntAISecurityLab for reporting.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2026.3.28"
      },
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.3.31"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41364"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-02T21:23:32Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\nSSH sandbox tar upload follows symlinks, enabling arbitrary file write on remote host\n\n## Current Maintainer Triage\n- Status: open\n- Normalized severity: high\n- Assessment: Real in shipped v2026.3.28: SSH sandbox tar upload lacked pre-upload symlink escape rejection until 3d5af14984 on 2026-03-31; maintainers already accepted it and the fix is unreleased.\n\n## Affected Packages / Versions\n- Package: `openclaw` (npm)\n- Latest published npm version: `2026.3.31`\n- Vulnerable version range: `\u003c=2026.3.28`\n- Patched versions: `\u003e= 2026.3.31`\n- First stable tag containing the fix: `v2026.3.31`\n\n## Fix Commit(s)\n- `3d5af14984ac1976c747a8e11581d697bd0829dc` \u2014 2026-03-31T19:56:45+09:00\n\nOpenClaw thanks @AntAISecurityLab for reporting.",
  "id": "GHSA-fv94-qvg8-xqpw",
  "modified": "2026-05-06T19:11:31Z",
  "published": "2026-04-02T21:23:32Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-fv94-qvg8-xqpw"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41364"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/3d5af14984ac1976c747a8e11581d697bd0829dc"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/openclaw/openclaw"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/releases/tag/v2026.3.31"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-arbitrary-file-write-via-symlink-following-in-ssh-sandbox-tar-upload"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "OpenClaw: SSH sandbox tar upload follows symlinks, enabling arbitrary file write on remote host"
}

GHSA-G2WF-V8Q9-85JJ

Vulnerability from github – Published: 2022-05-24 19:07 – Updated: 2022-08-06 00:00
VLAI
Details

Absolute Path Traversal vulnerability in FileviewDoc in QSAN Storage Manager allows remote authenticated attackers access arbitrary files by injecting the Symbolic Link following the Url path parameter.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-32509"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-07-07T14:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Absolute Path Traversal vulnerability in FileviewDoc in QSAN Storage Manager allows remote authenticated attackers access arbitrary files by injecting the Symbolic Link following the Url path parameter.",
  "id": "GHSA-g2wf-v8q9-85jj",
  "modified": "2022-08-06T00:00:52Z",
  "published": "2022-05-24T19:07:03Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32509"
    },
    {
      "type": "WEB",
      "url": "https://www.twcert.org.tw/tw/cp-132-4865-0c967-1.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-G6QJ-9F49-6C8C

Vulnerability from github – Published: 2025-04-03 09:32 – Updated: 2025-04-03 09:32
VLAI
Details

UNIX symbolic link (Symlink) following issue exists in FutureNet NXR series, VXR series and WXR series routers. Attaching to the affected product an external storage containing malicious symbolic link files, a logged-in administrative user may obtain and/or destroy internal files.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-30485"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-61"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-04-03T07:15:41Z",
    "severity": "MODERATE"
  },
  "details": "UNIX symbolic link (Symlink) following issue exists in FutureNet NXR series, VXR series and WXR series routers. Attaching to the affected product an external storage containing malicious symbolic link files, a logged-in administrative user may obtain and/or destroy internal files.",
  "id": "GHSA-g6qj-9f49-6c8c",
  "modified": "2025-04-03T09:32:14Z",
  "published": "2025-04-03T09:32:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-30485"
    },
    {
      "type": "WEB",
      "url": "https://jvn.jp/en/vu/JVNVU92821536"
    },
    {
      "type": "WEB",
      "url": "https://www.centurysys.co.jp/backnumber/common/jvnvu92821536.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:P/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-G7VG-VFVV-MR49

Vulnerability from github – Published: 2026-03-10 18:31 – Updated: 2026-03-10 18:31
VLAI
Details

A UNIX symbolic link (Symlink) following vulnerability in Fortinet FortiClientLinux 7.4.0 through 7.4.4, FortiClientLinux 7.2.2 through 7.2.12 may allow a local and unprivileged user to escalate their privileges to root.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-24018"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-61"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-03-10T18:18:17Z",
    "severity": "HIGH"
  },
  "details": "A UNIX symbolic link (Symlink) following vulnerability in Fortinet FortiClientLinux 7.4.0 through 7.4.4, FortiClientLinux 7.2.2 through 7.2.12 may allow a local and unprivileged user to escalate their privileges to root.",
  "id": "GHSA-g7vg-vfvv-mr49",
  "modified": "2026-03-10T18:31:20Z",
  "published": "2026-03-10T18:31:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-24018"
    },
    {
      "type": "WEB",
      "url": "https://fortiguard.fortinet.com/psirt/FG-IR-26-083"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-GCMX-RFRG-443V

Vulnerability from github – Published: 2026-08-25 12:31 – Updated: 2026-08-25 12:31
VLAI
Details

UNIX symbolic link (symlink) following vulnerability in ilya-zlobintsev/LACT allows for local denial-of-service. This issue affects LACT: through 0.10.0.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-75038"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-61"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-25T10:18:13Z",
    "severity": "MODERATE"
  },
  "details": "UNIX symbolic link (symlink) following vulnerability in ilya-zlobintsev/LACT allows for local denial-of-service.\u00a0This issue affects LACT: through 0.10.0.",
  "id": "GHSA-gcmx-rfrg-443v",
  "modified": "2026-08-25T12:31:22Z",
  "published": "2026-08-25T12:31:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-75038"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.suse.com/show_bug.cgi?id=1276481"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ilya-zlobintsev/LACT"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-GF79-FRWR-2V77

Vulnerability from github – Published: 2025-02-13 18:32 – Updated: 2025-02-13 18:32
VLAI
Details

Dell SupportAssist OS Recovery versions prior to 5.5.13.1 contain a symbolic link attack vulnerability. A low-privileged attacker with local access could potentially exploit this vulnerability, leading to arbitrary file deletion and Elevation of Privileges.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-22480"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-02-13T16:16:48Z",
    "severity": "HIGH"
  },
  "details": "Dell SupportAssist OS Recovery versions prior to 5.5.13.1 contain a symbolic link attack vulnerability. A low-privileged attacker with local access could potentially exploit this vulnerability, leading to arbitrary file deletion and Elevation of Privileges.",
  "id": "GHSA-gf79-frwr-2v77",
  "modified": "2025-02-13T18:32:34Z",
  "published": "2025-02-13T18:32:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-22480"
    },
    {
      "type": "WEB",
      "url": "https://www.dell.com/support/kbdoc/en-us/000275712/dsa-2025-051"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-GGJM-F3G4-RWMM

Vulnerability from github – Published: 2025-08-20 19:09 – Updated: 2025-08-21 04:07
VLAI
Summary
n8n symlink traversal vulnerability in "Read/Write File" node allows access to restricted files
Details

Impact

A symlink traversal vulnerability was discovered in the Read/Write File node in n8n. While the node attempts to restrict access to sensitive directories and files, it does not properly account for symbolic links (symlinks). An attacker with the ability to create symlinks—such as by using the Execute Command node—could exploit this to bypass the intended directory restrictions and read from or write to otherwise inaccessible paths. Users of n8n.cloud are not impacted.

Patches

Affected users should update to version 1.106.0 or later.

Workarounds

Until the patch is applied:

  • Disable or restrict access to the Execute Command node and any other nodes that allow arbitrary file system access.
  • Avoid using the Read/Write File node on untrusted paths or inputs that could be manipulated via symlinks.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "n8n"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.106.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-57749"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-08-20T19:09:55Z",
    "nvd_published_at": "2025-08-20T22:15:29Z",
    "severity": "MODERATE"
  },
  "details": "### Impact\nA symlink traversal vulnerability was discovered in the `Read/Write File` node in n8n. While the node attempts to restrict access to sensitive directories and files, it does not properly account for symbolic links (symlinks). An attacker with the ability to create symlinks\u2014such as by using the `Execute Command` node\u2014could exploit this to bypass the intended directory restrictions and read from or write to otherwise inaccessible paths. Users of _n8n.cloud_ are not impacted.\n\n### Patches\nAffected users should update to version 1.106.0 or later.\n\n### Workarounds\nUntil the patch is applied:\n\n- Disable or restrict access to the `Execute Command` node and any other nodes that allow arbitrary file system access.\n- Avoid using the `Read/Write File` node on untrusted paths or inputs that could be manipulated via symlinks.",
  "id": "GHSA-ggjm-f3g4-rwmm",
  "modified": "2025-08-21T04:07:03Z",
  "published": "2025-08-20T19:09:55Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/n8n-io/n8n/security/advisories/GHSA-ggjm-f3g4-rwmm"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-57749"
    },
    {
      "type": "WEB",
      "url": "https://github.com/n8n-io/n8n/pull/17735"
    },
    {
      "type": "WEB",
      "url": "https://github.com/n8n-io/n8n/commit/c2c3e08cdf33570d9051e659812cbfbdd3c077fd"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/n8n-io/n8n"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "n8n symlink traversal vulnerability in \"Read/Write File\" node allows access to restricted files"
}

GHSA-GHQ2-5C67-FPRM

Vulnerability from github – Published: 2026-06-10 20:32 – Updated: 2026-06-10 20:32
VLAI
Summary
PDM: Project-Local State and Config Writes Follow Symlinks
Details

Summary

PDM writes several project-local state or configuration files without symlink protection. If a malicious repository places those files as symlinks, local PDM operations can overwrite the symlink targets.

This creates an arbitrary file clobber primitive relative to the privileges of the invoking user.

Affected Behavior

  • Project-local config writes can affect files outside the repository
  • The most stable demonstrated sink is pdm.toml
  • Related sinks include .pdm-python and .python-version

Affected Code

  • src/pdm/project/config.py:303-350
  • src/pdm/project/core.py:209-217
  • src/pdm/cli/commands/use.py:187-189

Technical Details

Config.__init__() resolves the project-local pdm.toml path and _save_config() writes to the resolved target. If PROJECT_ROOT/pdm.toml is a symlink to another file, pdm config -l ... updates the target file instead of refusing the write.

The same general problem exists for other project-local persistence paths that are written directly with no lstat / O_NOFOLLOW protection.

For the pdm.toml PoC specifically, the target file must already contain parseable TOML. Otherwise the load step fails before the write path is reached. That parser constraint does not apply to the .pdm-python or .python-version sinks.

Impact

  • Arbitrary file clobber as the invoking user
  • Destructive modification of local files outside the repository root
  • Useful primitive for privilege abuse when pdm is run in elevated contexts

Reproduction

PoC:

# Replace this with a Python interpreter that can run `python -m pdm`.
PDM_PY=/path/to/python-with-pdm
tmpdir=$(mktemp -d)
target="$tmpdir/clobbered-target.toml"

cat > "$target" <<'EOF'
[seed]
value = 1
EOF

ln -s "$target" "$tmpdir/pdm.toml"

cat > "$tmpdir/pyproject.toml" <<'EOF'
[project]
name = "symlink-clobber-demo"
version = "0.0.1"
EOF

(
  cd "$tmpdir" &&
  "$PDM_PY" -m pdm config -l venv.in_project false
)

cat "$target"

Expected result:

  • A temporary project is created
  • pdm.toml is a symlink to another TOML file
  • Running pdm config -l venv.in_project false modifies the symlink target

Observed output from local validation:

--- target ---
[seed]
value = 1

[venv]
in_project = false

Severity

Medium

CVSS v4.0

  • Base score: 6.8 (Medium)
  • Vector: CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N

Rationale:

  • AV:L: exploitation requires local execution of pdm against an attacker-prepared checkout
  • AC:L: there is no complex constraint once the symlink sink exists
  • AT:N: no extra prerequisite beyond the victim running the relevant command is required
  • PR:N: the attacker does not need prior privileges on the victim system
  • UI:A: the victim must actively run a command that writes project-local state or config
  • VC:N: the demonstrated issue is a write primitive, not a direct read primitive
  • VI:H: the attacker can cause unauthorized modification of files outside the repository root
  • VA:L: file clobber can disrupt local operation, but direct same-step availability impact is lower than a full RCE
  • SC:N/SI:N/SA:N: the base score is limited to the directly affected system

Root Cause

Project-local file sinks are treated as trusted regular files and are written without symlink checks or guarded atomic replacement.

Recommended Remediation

  • Refuse to write project-local config/state files when the destination is a symlink
  • Use lstat and O_NOFOLLOW where available
  • Avoid resolving attacker-controlled project-local paths before writing
  • Use atomic temp-file replacement only after confirming the destination is a regular file

Disclosure Notes

This issue is independent from the code-execution issues above. It is best tracked as a separate CVE candidate because the root cause and remediation are different.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "pdm"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.27.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47763"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-61"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-10T20:32:56Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nPDM writes several project-local state or configuration files without symlink protection. If a malicious repository places those files as symlinks, local PDM operations can overwrite the symlink targets.\n\nThis creates an arbitrary file clobber primitive relative to the privileges of the invoking user.\n\n## Affected Behavior\n\n- Project-local config writes can affect files outside the repository\n- The most stable demonstrated sink is `pdm.toml`\n- Related sinks include `.pdm-python` and `.python-version`\n\n## Affected Code\n\n- `src/pdm/project/config.py:303-350`\n- `src/pdm/project/core.py:209-217`\n- `src/pdm/cli/commands/use.py:187-189`\n\n## Technical Details\n\n`Config.__init__()` resolves the project-local `pdm.toml` path and `_save_config()` writes to the resolved target. If `PROJECT_ROOT/pdm.toml` is a symlink to another file, `pdm config -l ...` updates the target file instead of refusing the write.\n\nThe same general problem exists for other project-local persistence paths that are written directly with no `lstat` / `O_NOFOLLOW` protection.\n\nFor the `pdm.toml` PoC specifically, the target file must already contain parseable TOML. Otherwise the load step fails before the write path is reached. That parser constraint does not apply to the `.pdm-python` or `.python-version` sinks.\n\n## Impact\n\n- Arbitrary file clobber as the invoking user\n- Destructive modification of local files outside the repository root\n- Useful primitive for privilege abuse when `pdm` is run in elevated contexts\n\n## Reproduction\n\nPoC:\n\n```bash\n# Replace this with a Python interpreter that can run `python -m pdm`.\nPDM_PY=/path/to/python-with-pdm\ntmpdir=$(mktemp -d)\ntarget=\"$tmpdir/clobbered-target.toml\"\n\ncat \u003e \"$target\" \u003c\u003c\u0027EOF\u0027\n[seed]\nvalue = 1\nEOF\n\nln -s \"$target\" \"$tmpdir/pdm.toml\"\n\ncat \u003e \"$tmpdir/pyproject.toml\" \u003c\u003c\u0027EOF\u0027\n[project]\nname = \"symlink-clobber-demo\"\nversion = \"0.0.1\"\nEOF\n\n(\n  cd \"$tmpdir\" \u0026\u0026\n  \"$PDM_PY\" -m pdm config -l venv.in_project false\n)\n\ncat \"$target\"\n```\n\nExpected result:\n\n- A temporary project is created\n- `pdm.toml` is a symlink to another TOML file\n- Running `pdm config -l venv.in_project false` modifies the symlink target\n\nObserved output from local validation:\n\n```text\n--- target ---\n[seed]\nvalue = 1\n\n[venv]\nin_project = false\n```\n\n## Severity\n\nMedium\n\n## CVSS v4.0\n\n- Base score: `6.8` (`Medium`)\n- Vector: `CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N`\n\nRationale:\n\n- `AV:L`: exploitation requires local execution of `pdm` against an attacker-prepared checkout\n- `AC:L`: there is no complex constraint once the symlink sink exists\n- `AT:N`: no extra prerequisite beyond the victim running the relevant command is required\n- `PR:N`: the attacker does not need prior privileges on the victim system\n- `UI:A`: the victim must actively run a command that writes project-local state or config\n- `VC:N`: the demonstrated issue is a write primitive, not a direct read primitive\n- `VI:H`: the attacker can cause unauthorized modification of files outside the repository root\n- `VA:L`: file clobber can disrupt local operation, but direct same-step availability impact is lower than a full RCE\n- `SC:N/SI:N/SA:N`: the base score is limited to the directly affected system\n\n## Root Cause\n\nProject-local file sinks are treated as trusted regular files and are written without symlink checks or guarded atomic replacement.\n\n## Recommended Remediation\n\n- Refuse to write project-local config/state files when the destination is a symlink\n- Use `lstat` and `O_NOFOLLOW` where available\n- Avoid resolving attacker-controlled project-local paths before writing\n- Use atomic temp-file replacement only after confirming the destination is a regular file\n\n## Disclosure Notes\n\nThis issue is independent from the code-execution issues above. It is best tracked as a separate CVE candidate because the root cause and remediation are different.",
  "id": "GHSA-ghq2-5c67-fprm",
  "modified": "2026-06-10T20:32:56Z",
  "published": "2026-06-10T20:32:56Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/pdm-project/pdm/security/advisories/GHSA-ghq2-5c67-fprm"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pdm-project/pdm"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pdm-project/pdm/releases/tag/2.27.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "PDM: Project-Local State and Config Writes Follow Symlinks"
}

GHSA-GMW6-94GG-2RC2

Vulnerability from github – Published: 2021-08-31 16:03 – Updated: 2022-06-17 20:51
VLAI
Summary
UNIX Symbolic Link (Symlink) Following in @npmcli/arborist
Details

Impact

Arbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution

@npmcli/arborist, the library that calculates dependency trees and manages the node_modules folder hierarchy for the npm command line interface, aims to guarantee that package dependency contracts will be met, and the extraction of package contents will always be performed into the expected folder.

This is accomplished by extracting package contents into a project's node_modules folder.

If the node_modules folder of the root project or any of its dependencies is somehow replaced with a symbolic link, it could allow Arborist to write package dependencies to any arbitrary location on the file system.

Note that symbolic links contained within package artifact contents are filtered out, so another means of creating a node_modules symbolic link would have to be employed.

  1. A preinstall script could replace node_modules with a symlink. (This is prevented by using --ignore-scripts.)
  2. An attacker could supply the target with a git repository, instructing them to run npm install --ignore-scripts in the root. This may be successful, because npm install --ignore-scripts is typically not capable of making changes outside of the project directory, so it may be deemed safe.

Patches

2.8.2 (included in npm v7.20.7 and above)

Workarounds

Do not run npm install on untrusted codebases, without first ensuring that the node_modules directory in the project is not a symbolic link.

Fix

Prior to extracting any package contents, the node_modules folder into which it is extracted is verified to be a real directory. If it is not, then it is removed.

Caveat: if you are currently relying on creating a symbolic link to the node_modules folder in order to share dependencies between projects, then that will no longer be possible. Please use the npm link command, explicit file:... dependencies, and/or workspaces to share dependencies in a development environment.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@npmcli/arborist"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.8.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2021-39135"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59",
      "CWE-61"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-08-31T16:03:00Z",
    "nvd_published_at": "2021-08-31T17:15:00Z",
    "severity": "HIGH"
  },
  "details": "### Impact\n\nArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution\n\n`@npmcli/arborist`, the library that calculates dependency trees and manages the node_modules folder hierarchy for the npm command line interface, aims to guarantee that package dependency contracts will be met, and the extraction of package contents will always be performed into the expected folder.\n\nThis is accomplished by extracting package contents into a project\u0027s `node_modules` folder.\n\nIf the `node_modules` folder of the root project or any of its dependencies is somehow replaced with a symbolic link, it could allow Arborist to write package dependencies to any arbitrary location on the file system.\n\nNote that symbolic links contained within package artifact contents are filtered out, so another means of creating a `node_modules` symbolic link would have to be employed.\n\n1. A `preinstall` script could replace `node_modules` with a symlink.  (This is prevented by using `--ignore-scripts`.)\n2. An attacker could supply the target with a git repository, instructing them to run `npm install --ignore-scripts` in the root.  This may be successful, because `npm install --ignore-scripts` is typically not capable of making changes outside of the project directory, so it may be deemed safe.\n\n### Patches\n\n2.8.2 (included in npm v7.20.7 and above)\n\n### Workarounds\n\nDo not run `npm install` on untrusted codebases, without first ensuring that the `node_modules` directory in the project is not a symbolic link.\n\n### Fix\n\nPrior to extracting any package contents, the `node_modules` folder into which it is extracted is verified to be a real directory.  If it is not, then it is removed.\n\nCaveat: if you are currently relying on creating a symbolic link to the `node_modules` folder in order to share dependencies between projects, then that will no longer be possible.  Please use the `npm link` command, explicit `file:...` dependencies, and/or `workspaces` to share dependencies in a development environment.",
  "id": "GHSA-gmw6-94gg-2rc2",
  "modified": "2022-06-17T20:51:19Z",
  "published": "2021-08-31T16:03:34Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/npm/arborist/security/advisories/GHSA-gmw6-94gg-2rc2"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-39135"
    },
    {
      "type": "WEB",
      "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-389290.pdf"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/npm/arborist"
    },
    {
      "type": "WEB",
      "url": "https://www.npmjs.com/package/@npmcli/arborist"
    },
    {
      "type": "WEB",
      "url": "https://www.oracle.com/security-alerts/cpuoct2021.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "UNIX Symbolic Link (Symlink) Following in @npmcli/arborist"
}

Mitigation
Implementation

Symbolic link attacks often occur when a program creates a tmp directory that stores files/links. Access to the directory should be restricted to the program as to prevent attackers from manipulating the files.

Mitigation MIT-48.1
Architecture and Design

Strategy: Separation of Privilege

  • Follow the principle of least privilege when assigning access rights to entities in a software system.
  • Denying access to a file can prevent an attacker from replacing that file with a link to a sensitive file. Ensure good compartmentalization in the system to provide protected areas that can be trusted.
CAPEC-27: Leveraging Race Conditions via Symbolic Links

This attack leverages the use of symbolic links (Symlinks) in order to write to sensitive files. An attacker can create a Symlink link to a target file not otherwise accessible to them. When the privileged program tries to create a temporary file with the same name as the Symlink link, it will actually write to the target file pointed to by the attackers' Symlink link. If the attacker can insert malicious content in the temporary file they will be writing to the sensitive file by using the Symlink. The race occurs because the system checks if the temporary file exists, then creates the file. The attacker would typically create the Symlink during the interval between the check and the creation of the temporary file.