Skip to content

Support for PDM package manager (Python)#399

Merged
reiniercriel merged 10 commits into
AikidoSec:mainfrom
greenpixie:feat/pdm-support
May 15, 2026
Merged

Support for PDM package manager (Python)#399
reiniercriel merged 10 commits into
AikidoSec:mainfrom
greenpixie:feat/pdm-support

Conversation

@chris-greenpixie
Copy link
Copy Markdown
Contributor

@chris-greenpixie chris-greenpixie commented Apr 7, 2026

Summary

  • Adds PDM as a supported Python package manager, using the same MITM proxy approach as poetry/uv/pipx
  • PDM uses the same underlying system as pip, so all malware detection and minimum package age enforcement happens at the existing pip interceptor proxy layer — no PDM-specific scanning logic needed
  • Includes shell integration (bash/zsh, fish, PowerShell), E2E test suite, and Docker test image setup

Summary by Aikido

Security Issues: 0 🔍 Quality Issues: 1 Resolved Issues: 0

🚀 New Features

  • Added PDM package manager support with proxy and shell integration

More info

PDM is a modern Python package manager using pyproject.toml (PEP 621).
Uses the same MITM-only proxy approach as poetry/uv/pipx — all malware
detection and minimum package age enforcement happens at the proxy layer
by intercepting PyPI requests.
* @param {NodeJS.ProcessEnv} env - Environment object to modify
* @param {string} combinedCaPath - Path to the combined CA bundle
*/
function setPdmCaBundleEnvironmentVariables(env, combinedCaPath) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setPdmCaBundleEnvironmentVariables mutates its 'env' parameter by assigning SSL_CERT_FILE / REQUESTS_CA_BUNDLE / PIP_CERT, causing side effects on the caller-provided object; avoid modifying the input argument directly.

Details

✨ AI Reasoning
​A function added in this change modifies the passed-in 'env' object by assigning properties on it. Mutating a parameter makes it harder to reason about the original value and can produce surprising side effects for callers. The change alters program state via the argument rather than returning a new modified value, which increases coupling between caller and callee and can hide where environment changes occur.

🔧 How do I fix it?
Create new local variables instead of reassigning parameters. Use different variable names to clearly distinguish between input and modified values.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

The install message in `safe-chain setup` help was hardcoding a stale
list of package managers (missing uv, uvx, poetry, pipx, pdm). Use the
existing getPackageManagerList() helper so the list stays in sync with
knownAikidoTools.
Comment thread test/e2e/pdm.e2e.spec.js Outdated
await shell.runCommand("cd /tmp/test-pdm-malware && pdm init --non-interactive");

const result = await shell.runCommand(
"cd /tmp/test-pdm-malware && pdm add safe-chain-pi-test"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe-chain-pi-test is no longer published (PYPI pulled it SIGH) , so these tests will start failing. The other pypi package mgr specs (poetry, uv, pip) use numpy==2.4.4 as the malware proxy. That one is already added to malwarelistmirror so just changing the name here should be fine

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn that's inconvenient from pypi. Have updated the pdm tests to use numpy==2.4.4, and also fixed the failing bun test. E2E tests are passing locally for me now

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that! Have a PR open for fixing those bun tests but not merged yet.

The safe-chain-pi-test package no longer exists on PyPI. Aikido now
patches numpy==2.4.4 into the malware list for tests, matching the
pattern already used in the poetry e2e suite.
The user-facing message is "Safe-chain: blocked N malicious package
downloads", not "blocked by safe-chain" (which only appears in the
proxy's HTTP response, not the rendered CLI output).
Bun retries blocked downloads, so the count in "blocked N malicious
package downloads" can be >1. Match on the surrounding text rather than
a fixed count to keep the assertion robust.

Also drops the brittle "pdm update updates dependencies" case.
@reiniercriel reiniercriel merged commit a5c29d9 into AikidoSec:main May 15, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants