PDM: Project-Local State and Config Writes Follow Symlinks
Date: 2026-06
Affected: pip/pdm
Attack vector: rce
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-47763
CWE: CWE-61

## 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 eleva


Mitigations:

Architectural layers (MAESTRO):