From 9914c0ccb31ed892bc31a8cc4890571bc5f32317 Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Fri, 24 Oct 2025 13:47:22 -0700 Subject: [PATCH] Some fixes --- README.md | 6 +++--- .../src/packagemanager/pip/createPackageManager.js | 4 ---- .../pip/parsing/parsePackagesFromInstallArgs.js | 5 ++--- .../pip/parsing/parsePackagesFromInstallArgs.spec.js | 12 +++--------- .../registryProxy.connect-tunnel.spec.js | 3 +++ 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 3129b71..57d8c89 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Aikido Safe Chain works on Node.js version 18 and above and supports the followi - ✅ **pnpx** - ✅ **bun** - ✅ **bunx** -- ✅ **pip** (pip and pip3) +- ✅ **pip** # Usage @@ -39,7 +39,7 @@ Installing the Aikido Safe Chain is easy. You just need 3 simple steps: ``` - The output should show that Aikido Safe Chain is blocking the installation of this package as it is flagged as malware. -When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, or `pip` (including `pip3`) commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. If any malware is detected, it will prompt you to exit the command. +When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, or `pip` commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. If any malware is detected, it will prompt you to exit the command. You can check the installed version by running: ```shell @@ -60,7 +60,7 @@ The Aikido Safe Chain integrates with your shell to provide a seamless experienc More information about the shell integration can be found in the [shell integration documentation](docs/shell-integration.md). -### Python / pip support +### Python support - Supports `pip` and `pip3` commands. - Scans Python packages fetched by `pip install`, `pip download`, and `pip wheel`. diff --git a/packages/safe-chain/src/packagemanager/pip/createPackageManager.js b/packages/safe-chain/src/packagemanager/pip/createPackageManager.js index 2eaab01..3c0e974 100644 --- a/packages/safe-chain/src/packagemanager/pip/createPackageManager.js +++ b/packages/safe-chain/src/packagemanager/pip/createPackageManager.js @@ -7,10 +7,6 @@ import { pipWheelCommand, } from "./utils/pipCommands.js"; -/** - * Creates a package manager - * @param {string} [command="pip"] - The pip command to use (e.g., "pip", "pip3") defaults to "pip" - */ export function createPipPackageManager(command = "pip") { function isSupportedCommand(args) { const scanner = findDependencyScannerForCommand( diff --git a/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.js b/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.js index 71c99c0..b0b2f6c 100644 --- a/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.js +++ b/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.js @@ -101,8 +101,7 @@ function isPipOptionWithParameter(arg) { } function parsePipSpec(spec) { - // Ignore obvious URLs and paths - // These cannot be scanned from the malware database + // Ignore obvious URLs and paths, rely on mitm scanner const lower = spec.toLowerCase(); if ( lower.startsWith("git+") || @@ -116,7 +115,7 @@ function parsePipSpec(spec) { spec.startsWith("../") || spec.startsWith("/") ) { - return { name: spec, version: "latest" }; + return null; } // Strip extras: package[extra1,extra2] diff --git a/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.spec.js b/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.spec.js index 6a0098b..8a653c9 100644 --- a/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.spec.js +++ b/packages/safe-chain/src/packagemanager/pip/parsing/parsePackagesFromInstallArgs.spec.js @@ -40,9 +40,8 @@ describe("parsePackagesFromInstallArgs", () => { ]); }); - it("should parse multiple constraints", () => { + it("should skip ranges", () => { const result = parsePackagesFromInstallArgs(["install", "requests>=2,<3"]); - // Range specifiers should be skipped since they don't provide exact versions assert.deepEqual(result, []); }); @@ -69,7 +68,7 @@ describe("parsePackagesFromInstallArgs", () => { ]); }); - it("should treat VCS/URL/path specs as names (no version)", () => { + it("should skip VCS/URL/path)", () => { const result = parsePackagesFromInstallArgs([ "install", "git+https://github.com/pallets/flask.git", @@ -77,12 +76,7 @@ describe("parsePackagesFromInstallArgs", () => { "file:/tmp/pkg.whl", "./localpkg", ]); - assert.deepEqual(result, [ - { name: "git+https://github.com/pallets/flask.git", version: "latest", type: "add" }, - { name: "https://files.pythonhosted.org/packages/foo/bar.whl", version: "latest", type: "add" }, - { name: "file:/tmp/pkg.whl", version: "latest", type: "add" }, - { name: "./localpkg", version: "latest", type: "add" }, - ]); + assert.deepEqual(result, []); }); it("should return empty array for no packages", () => { diff --git a/packages/safe-chain/src/registryProxy/registryProxy.connect-tunnel.spec.js b/packages/safe-chain/src/registryProxy/registryProxy.connect-tunnel.spec.js index e5f5902..a1fea55 100644 --- a/packages/safe-chain/src/registryProxy/registryProxy.connect-tunnel.spec.js +++ b/packages/safe-chain/src/registryProxy/registryProxy.connect-tunnel.spec.js @@ -147,6 +147,9 @@ function sendHttpsRequestThroughTunnel(socket, verb, url) { { socket: socket, servername: url.hostname, + // Tests should focus on tunnel behavior, not system CA state; + // disable CA verification to avoid flakiness on machines without full roots. + rejectUnauthorized: false, }, () => { tlsSocket.write(