mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Some adaptations"
This commit is contained in:
parent
ca5c1e8869
commit
e455828339
4 changed files with 10 additions and 69 deletions
|
|
@ -56,6 +56,8 @@ You can check the installed version by running:
|
|||
safe-chain --version
|
||||
```
|
||||
|
||||
> **Note:** When using pip or pip3, Safe Chain may need to install a CA certificate in your OS trust store to enable secure MITM protection. This operation requires root (administrator) permissions. You may be prompted for your password when running pip commands for the first time.
|
||||
|
||||
## How it works
|
||||
|
||||
The Aikido Safe Chain works by running a lightweight proxy server that intercepts package downloads from the npm registry and PyPI. When you run npm, npx, yarn, pnpm, pnpx, bun, bunx, `pip`, or `pip3` commands, all package downloads are routed through this local proxy, which verifies packages in real-time against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. If malware is detected in any package (including deep dependencies), the proxy blocks the download before the malicious code reaches your machine.
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import { safeSpawn } from "../../utils/safeSpawn.js";
|
|||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
import { installSafeChainCA } from "../../registryProxy/certUtils.js";
|
||||
|
||||
function shouldMockCAInstall() {
|
||||
return process.env.SAFE_CHAIN_TEST_SKIP_CA_INSTALL === "1";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} command
|
||||
* @param {string[]} args
|
||||
|
|
@ -15,10 +11,9 @@ function shouldMockCAInstall() {
|
|||
*/
|
||||
export async function runPip(command, args) {
|
||||
try {
|
||||
// Install Safe Chain CA in OS trust store before running pip, unless in test mode
|
||||
if (!shouldMockCAInstall()) {
|
||||
// Install Safe Chain CA in OS trust store before running pip
|
||||
// Py 3.14 requires that certs are properly installed in the OS trust store
|
||||
await installSafeChainCA();
|
||||
}
|
||||
const env = mergeSafeChainProxyEnvironmentVariables(process.env);
|
||||
const result = await safeSpawn(command, args, {
|
||||
stdio: "inherit",
|
||||
|
|
|
|||
|
|
@ -36,63 +36,6 @@ describe("runPipCommand environment variable handling", () => {
|
|||
mock.reset();
|
||||
});
|
||||
|
||||
it("should set REQUESTS_CA_BUNDLE and SSL_CERT_FILE for default PyPI (no explicit index)", async () => {
|
||||
const res = await runPip("pip3", ["install", "requests"]);
|
||||
assert.strictEqual(res.status, 0);
|
||||
|
||||
assert.ok(capturedArgs, "safeSpawn should have been called");
|
||||
|
||||
// Check environment variables are set
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.REQUESTS_CA_BUNDLE,
|
||||
"/tmp/test-combined-ca.pem",
|
||||
"REQUESTS_CA_BUNDLE should be set to combined bundle path"
|
||||
);
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.SSL_CERT_FILE,
|
||||
"/tmp/test-combined-ca.pem",
|
||||
"SSL_CERT_FILE should be set to combined bundle path"
|
||||
);
|
||||
|
||||
// Args should be unchanged (no arg injection)
|
||||
assert.deepStrictEqual(capturedArgs.args, ["install", "requests"]);
|
||||
});
|
||||
|
||||
it("should set CA environment variables even for external/test PyPI mirror (covers non-CLI traffic)", async () => {
|
||||
const res = await runPip("pip3", [
|
||||
"install",
|
||||
"certifi",
|
||||
"--index-url",
|
||||
"https://test.pypi.org/simple",
|
||||
]);
|
||||
assert.strictEqual(res.status, 0);
|
||||
// Env vars should be set unconditionally
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.REQUESTS_CA_BUNDLE,
|
||||
"/tmp/test-combined-ca.pem"
|
||||
);
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.SSL_CERT_FILE,
|
||||
"/tmp/test-combined-ca.pem"
|
||||
);
|
||||
});
|
||||
|
||||
it("should still set CA env vars for PyPI even with user --cert flag", async () => {
|
||||
// For default PyPI, we still set env vars; pip CLI --cert takes precedence
|
||||
const res = await runPip("pip3", ["install", "requests"]);
|
||||
assert.strictEqual(res.status, 0);
|
||||
|
||||
// Environment variables still set (pip CLI --cert takes precedence)
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.REQUESTS_CA_BUNDLE,
|
||||
"/tmp/test-combined-ca.pem"
|
||||
);
|
||||
assert.strictEqual(
|
||||
capturedArgs.options.env.SSL_CERT_FILE,
|
||||
"/tmp/test-combined-ca.pem"
|
||||
);
|
||||
});
|
||||
|
||||
it("should preserve HTTPS_PROXY from proxy merge", async () => {
|
||||
const res = await runPip("pip3", ["install", "requests"]);
|
||||
assert.strictEqual(res.status, 0);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import fs from "fs";
|
|||
import os from "os";
|
||||
import { safeSpawn } from "../utils/safeSpawn.js";
|
||||
import { DARWIN_CA_PATH, LINUX_CA_PATH } from "../config/settings.js";
|
||||
import { ui } from "../environment/userInteraction.js";
|
||||
|
||||
const certFolder = path.join(os.homedir(), ".safe-chain", "certs");
|
||||
const ca = loadCa();
|
||||
|
|
@ -155,7 +156,7 @@ export async function installSafeChainCA() {
|
|||
try {
|
||||
const alreadyInstalled = await isSafeChainCAInstalled();
|
||||
if (alreadyInstalled) {
|
||||
console.log("Safe Chain CA already installed in OS trust store.");
|
||||
ui.writeVerbose("Safe-chain: CA already installed in OS trust store.");
|
||||
return;
|
||||
}
|
||||
if (platform === "darwin") {
|
||||
|
|
@ -171,9 +172,9 @@ export async function installSafeChainCA() {
|
|||
} else {
|
||||
throw new Error("Unsupported OS for automatic CA installation. Please install manually.");
|
||||
}
|
||||
console.log("Safe Chain CA installed in OS trust store.");
|
||||
ui.writeVerbose("Safe-chain: CA installed in OS trust store.");
|
||||
} catch (/** @type any */ error) {
|
||||
console.error("Failed to install Safe Chain CA:", error.message);
|
||||
ui.writeError("Failed to install safe-chain: CA:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue