From d737abd24adbb4922186ec3b10a7c03977fc50d8 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Wed, 8 Oct 2025 16:25:56 +0200 Subject: [PATCH 1/4] Update readme for version 1.1.0 --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d36f1a0..d173650 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Aikido Safe Chain +> πŸš€ **Version 1.1.0: Full Package Manager Support** +> +> Starting from version 1.1.0, Aikido Safe Chain now provides complete protection for all package managers. We've changed how we block malicious packages: instead of checking which packages are being installed, we run a lightweight proxy server that intercepts and blocks downloads of packages containing malware. This means full dependency tree protection for all package managers, not just npm. + The Aikido Safe Chain **prevents developers from installing malware** on their workstations through npm, npx, yarn, pnpm and pnpx. It's **free** to use and does not require any token. The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), and [pnpx](https://pnpm.io/cli/dlx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm or pnpx from downloading or running the malware. @@ -8,16 +12,12 @@ The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [n Aikido Safe Chain works on Node.js version 18 and above and supports the following package managers: -- βœ… full coverage: **npm >= 10.4.0**: -- ⚠️ limited to scanning the install command arguments (broader scanning coming soon): - - **npm < 10.4.0** - - **npx** - - **yarn** - - **pnpm** - - **pnpx** -- 🚧 **bun**: coming soon - -Note on the limited support for npm < 10.4.0, npx, yarn, pnpm and pnpx: adding **full support for these package managers is a high priority**. In the meantime, we offer limited support already, which means that the Aikido Safe Chain will scan the package names passed as arguments to the install commands. However, it will not scan the full dependency tree of these packages. +- βœ… **npm**: +- βœ… **npx** +- βœ… **yarn** +- βœ… **pnpm** +- βœ… **pnpx** +- βœ… **bun** # Usage From b08b4e2d4ec332f2ef4a11aec205613906051240 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Wed, 8 Oct 2025 15:12:06 +0200 Subject: [PATCH 2/4] Wrap bun with safe-chain to block downloads of packages with malware --- packages/safe-chain/bin/aikido-bun.js | 10 +++ packages/safe-chain/bin/aikido-bunx.js | 10 +++ packages/safe-chain/package.json | 2 + .../bun/createBunPackageManager.js | 42 ++++++++++ .../packagemanager/currentPackageManager.js | 8 ++ .../src/shell-integration/helpers.js | 5 +- .../startup-scripts/init-fish.fish | 8 ++ .../startup-scripts/init-posix.sh | 8 ++ .../startup-scripts/init-pwsh.ps1 | 8 ++ test/e2e/Dockerfile | 3 + test/e2e/bun.e2e.spec.js | 79 +++++++++++++++++++ 11 files changed, 181 insertions(+), 2 deletions(-) create mode 100755 packages/safe-chain/bin/aikido-bun.js create mode 100755 packages/safe-chain/bin/aikido-bunx.js create mode 100644 packages/safe-chain/src/packagemanager/bun/createBunPackageManager.js create mode 100644 test/e2e/bun.e2e.spec.js diff --git a/packages/safe-chain/bin/aikido-bun.js b/packages/safe-chain/bin/aikido-bun.js new file mode 100755 index 0000000..01e3972 --- /dev/null +++ b/packages/safe-chain/bin/aikido-bun.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node + +import { main } from "../src/main.js"; +import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js"; + +const packageManagerName = "bun"; +initializePackageManager(packageManagerName); +var exitCode = await main(process.argv.slice(2)); + +process.exit(exitCode); diff --git a/packages/safe-chain/bin/aikido-bunx.js b/packages/safe-chain/bin/aikido-bunx.js new file mode 100755 index 0000000..fb378e5 --- /dev/null +++ b/packages/safe-chain/bin/aikido-bunx.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node + +import { main } from "../src/main.js"; +import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js"; + +const packageManagerName = "bunx"; +initializePackageManager(packageManagerName); +var exitCode = await main(process.argv.slice(2)); + +process.exit(exitCode); diff --git a/packages/safe-chain/package.json b/packages/safe-chain/package.json index d28fe73..c0d2115 100644 --- a/packages/safe-chain/package.json +++ b/packages/safe-chain/package.json @@ -12,6 +12,8 @@ "aikido-yarn": "bin/aikido-yarn.js", "aikido-pnpm": "bin/aikido-pnpm.js", "aikido-pnpx": "bin/aikido-pnpx.js", + "aikido-bun": "bin/aikido-bun.js", + "aikido-bunx": "bin/aikido-bunx.js", "safe-chain": "bin/safe-chain.js" }, "type": "module", diff --git a/packages/safe-chain/src/packagemanager/bun/createBunPackageManager.js b/packages/safe-chain/src/packagemanager/bun/createBunPackageManager.js new file mode 100644 index 0000000..14faa5f --- /dev/null +++ b/packages/safe-chain/src/packagemanager/bun/createBunPackageManager.js @@ -0,0 +1,42 @@ +import { ui } from "../../environment/userInteraction.js"; +import { safeSpawn } from "../../utils/safeSpawn.js"; +import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js"; + +export function createBunPackageManager() { + return { + runCommand: (args) => runBunCommand("bun", args), + + // For bun, we use the proxy-only approach to block package downloads, + // so we don't need to analyze commands. + isSupportedCommand: () => false, + getDependencyUpdatesForCommand: () => [], + }; +} + +export function createBunxPackageManager() { + return { + runCommand: (args) => runBunCommand("bunx", args), + + // For bunx, we use the proxy-only approach to block package downloads, + // so we don't need to analyze commands. + isSupportedCommand: () => false, + getDependencyUpdatesForCommand: () => [], + }; +} + +async function runBunCommand(command, args) { + try { + const result = await safeSpawn(command, args, { + stdio: "inherit", + env: mergeSafeChainProxyEnvironmentVariables(process.env), + }); + return { status: result.status }; + } catch (error) { + if (error.status) { + return { status: error.status }; + } else { + ui.writeError("Error executing command:", error.message); + return { status: 1 }; + } + } +} diff --git a/packages/safe-chain/src/packagemanager/currentPackageManager.js b/packages/safe-chain/src/packagemanager/currentPackageManager.js index 9497a20..2a10d86 100644 --- a/packages/safe-chain/src/packagemanager/currentPackageManager.js +++ b/packages/safe-chain/src/packagemanager/currentPackageManager.js @@ -1,3 +1,7 @@ +import { + createBunPackageManager, + createBunxPackageManager, +} from "./bun/createBunPackageManager.js"; import { createNpmPackageManager } from "./npm/createPackageManager.js"; import { createNpxPackageManager } from "./npx/createPackageManager.js"; import { @@ -21,6 +25,10 @@ export function initializePackageManager(packageManagerName, version) { state.packageManagerName = createPnpmPackageManager(); } else if (packageManagerName === "pnpx") { state.packageManagerName = createPnpxPackageManager(); + } else if (packageManagerName === "bun") { + state.packageManagerName = createBunPackageManager(); + } else if (packageManagerName === "bunx") { + state.packageManagerName = createBunxPackageManager(); } else { throw new Error("Unsupported package manager: " + packageManagerName); } diff --git a/packages/safe-chain/src/shell-integration/helpers.js b/packages/safe-chain/src/shell-integration/helpers.js index 23132f0..2345022 100644 --- a/packages/safe-chain/src/shell-integration/helpers.js +++ b/packages/safe-chain/src/shell-integration/helpers.js @@ -9,8 +9,9 @@ export const knownAikidoTools = [ { tool: "yarn", aikidoCommand: "aikido-yarn" }, { tool: "pnpm", aikidoCommand: "aikido-pnpm" }, { tool: "pnpx", aikidoCommand: "aikido-pnpx" }, - // When adding a new tool here, also update the expected alias in the tests (setup.spec.js, teardown.spec.js) - // and add the documentation for the new tool in the README.md + { tool: "bun", aikidoCommand: "aikido-bun" }, + { tool: "bunx", aikidoCommand: "aikido-bunx" }, + // When adding a new tool here, also update the documentation for the new tool in the README.md ]; /** diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-fish.fish b/packages/safe-chain/src/shell-integration/startup-scripts/init-fish.fish index 87f6a79..29d6bf3 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-fish.fish +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-fish.fish @@ -46,6 +46,14 @@ function pnpx wrapSafeChainCommand "pnpx" "aikido-pnpx" $argv end +function bun + wrapSafeChainCommand "bun" "aikido-bun" $argv +end + +function bunx + wrapSafeChainCommand "bunx" "aikido-bunx" $argv +end + function npm # If args is just -v or --version and nothing else, just run the `npm -v` command # This is because nvm uses this to check the version of npm diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh b/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh index 01b23c4..353c6c0 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh @@ -42,6 +42,14 @@ function pnpx() { wrapSafeChainCommand "pnpx" "aikido-pnpx" "$@" } +function bun() { + wrapSafeChainCommand "bun" "aikido-bun" "$@" +} + +function bunx() { + wrapSafeChainCommand "bunx" "aikido-bunx" "$@" +} + function npm() { if [[ "$1" == "-v" || "$1" == "--version" ]] && [[ $# -eq 1 ]]; then # If args is just -v or --version and nothing else, just run the npm version command diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 index 7fb44d6..a449405 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-pwsh.ps1 @@ -68,6 +68,14 @@ function pnpx { Invoke-WrappedCommand "pnpx" "aikido-pnpx" $args } +function bun { + Invoke-WrappedCommand "bun" "aikido-bun" $args +} + +function bunx { + Invoke-WrappedCommand "bunx" "aikido-bunx" $args +} + function npm { # If args is just -v or --version and nothing else, just run the npm version command # This is because nvm uses this to check the version of npm diff --git a/test/e2e/Dockerfile b/test/e2e/Dockerfile index 3c8ce73..484f5fe 100644 --- a/test/e2e/Dockerfile +++ b/test/e2e/Dockerfile @@ -46,6 +46,9 @@ RUN volta install npm@${NPM_VERSION} RUN volta install yarn@${YARN_VERSION} RUN volta install pnpm@${PNPM_VERSION} +# Install Bun +RUN curl -fsSL https://bun.sh/install | bash + # Copy and install Safe chain COPY --from=builder /app/*.tgz /pkgs/ RUN npm install -g /pkgs/*.tgz diff --git a/test/e2e/bun.e2e.spec.js b/test/e2e/bun.e2e.spec.js new file mode 100644 index 0000000..8dea93b --- /dev/null +++ b/test/e2e/bun.e2e.spec.js @@ -0,0 +1,79 @@ +import { describe, it, before, beforeEach, afterEach } from "node:test"; +import { DockerTestContainer } from "./DockerTestContainer.js"; +import assert from "node:assert"; + +describe("E2E: bun coverage", () => { + let container; + + before(async () => { + DockerTestContainer.buildImage(); + }); + + beforeEach(async () => { + // Run a new Docker container for each test + container = new DockerTestContainer(); + await container.start(); + + const installationShell = await container.openShell("zsh"); + await installationShell.runCommand("safe-chain setup"); + }); + + afterEach(async () => { + // Stop and clean up the container after each test + if (container) { + await container.stop(); + container = null; + } + }); + + it(`safe-chain succesfully installs safe packages`, async () => { + const shell = await container.openShell("bash"); + const result = await shell.runCommand("bun i axios"); + + assert.ok( + result.output.includes("no malicious packages found."), + `Output did not include expected text. Output was:\n${result.output}` + ); + }); + + it(`safe-chain blocks download of malicious packages already in package.json`, async () => { + const shell = await container.openShell("bash"); + await shell.runCommand( + 'echo \'{"name":"test-project","version":"1.0.0","dependencies":{"safe-chain-test":"0.0.1-security"}}\' > package.json' + ); + + var result = await shell.runCommand("bun install"); + + assert.ok( + result.output.includes("blocked 1 malicious package downloads"), + `Output did not include expected text. Output was:\n${result.output}` + ); + assert.ok( + result.output.includes("- safe-chain-test"), + `Output did not include expected text. Output was:\n${result.output}` + ); + assert.ok( + result.output.includes("Exiting without installing malicious packages."), + `Output did not include expected text. Output was:\n${result.output}` + ); + }); + + it("safe-chain blocks bunx from downloading malicious packages", async () => { + const shell = await container.openShell("bash"); + + const result = await shell.runCommand("bunx safe-chain-test"); + + assert.ok( + result.output.includes("blocked 1 malicious package downloads"), + `Output did not include expected text. Output was:\n${result.output}` + ); + assert.ok( + result.output.includes("- safe-chain-test"), + `Output did not include expected text. Output was:\n${result.output}` + ); + assert.ok( + result.output.includes("Exiting without installing malicious packages."), + `Output did not include expected text. Output was:\n${result.output}` + ); + }); +}); From 41e88d422ea8a4df81caca059b8b3a99dfd95d64 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Wed, 8 Oct 2025 16:34:26 +0200 Subject: [PATCH 3/4] Add mention of bun everywhere --- README.md | 15 ++++++++------- docs/shell-integration.md | 8 ++++---- packages/safe-chain/package.json | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d173650..b2d1fa4 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,21 @@ > > Starting from version 1.1.0, Aikido Safe Chain now provides complete protection for all package managers. We've changed how we block malicious packages: instead of checking which packages are being installed, we run a lightweight proxy server that intercepts and blocks downloads of packages containing malware. This means full dependency tree protection for all package managers, not just npm. -The Aikido Safe Chain **prevents developers from installing malware** on their workstations through npm, npx, yarn, pnpm and pnpx. It's **free** to use and does not require any token. +The Aikido Safe Chain **prevents developers from installing malware** on their workstations through npm, npx, yarn, pnpm, pnpx, bun, and bunx. It's **free** to use and does not require any token. -The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), and [pnpx](https://pnpm.io/cli/dlx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm or pnpx from downloading or running the malware. +The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), [pnpx](https://pnpm.io/cli/dlx), [bun](https://bun.sh/), and [bunx](https://bun.sh/docs/cli/bunx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, pnpx, bun, or bunx from downloading or running the malware. ![demo](./docs/safe-package-manager-demo.png) Aikido Safe Chain works on Node.js version 18 and above and supports the following package managers: -- βœ… **npm**: +- βœ… **npm** - βœ… **npx** - βœ… **yarn** - βœ… **pnpm** - βœ… **pnpx** - βœ… **bun** +- βœ… **bunx** # Usage @@ -34,20 +35,20 @@ Installing the Aikido Safe Chain is easy. You just need 3 simple steps: safe-chain setup ``` 3. **❗Restart your terminal** to start using the Aikido Safe Chain. - - This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm and pnpx are loaded correctly. If you do not restart your terminal, the aliases will not be available. + - This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, bun, and bunx are loaded correctly. If you do not restart your terminal, the aliases will not be available. 4. **Verify the installation** by running: ```shell npm install safe-chain-test ``` - 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` or `pnpx` 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`, or `bunx` 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. ## How it works -The Aikido Safe Chain works by intercepting the npm, npx, yarn, pnpm and pnpx commands and verifying the packages against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. +The Aikido Safe Chain works by intercepting the npm, npx, yarn, pnpm, pnpx, bun, and bunx commands and verifying the packages against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. -The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm and pnpx commands. It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which perform malware checks before executing the original commands. We currently support: +The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, bun, and bunx commands. It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which perform malware checks before executing the original commands. We currently support: - βœ… **Bash** - βœ… **Zsh** diff --git a/docs/shell-integration.md b/docs/shell-integration.md index 6b2c79e..4a6ac99 100644 --- a/docs/shell-integration.md +++ b/docs/shell-integration.md @@ -2,7 +2,7 @@ ## Overview -The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`) with Aikido's security scanning functionality. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents. +The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`) with Aikido's security scanning functionality. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents. ## Supported Shells @@ -28,7 +28,7 @@ This command: - Copies necessary startup scripts to Safe Chain's installation directory (`~/.safe-chain/scripts`) - Detects all supported shells on your system -- Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, and `pnpx` +- Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, and `bunx` ❗ After running this command, **you must restart your terminal** for the changes to take effect. This ensures that the startup scripts are sourced correctly. @@ -77,7 +77,7 @@ The system modifies the following files to source Safe Chain startup scripts: This means the shell functions are working but the Aikido commands aren't installed or available in your PATH: - Make sure Aikido Safe Chain is properly installed on your system -- Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm` and `aikido-pnpx` commands exist +- Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm`, `aikido-pnpx`, `aikido-bun`, and `aikido-bunx` commands exist - Check that these commands are in your system's PATH ### Manual Verification @@ -120,4 +120,4 @@ npm() { } ``` -Repeat this pattern for `npx`, `yarn`, `pnpm`, and `pnpx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes. +Repeat this pattern for `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, and `bunx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes. diff --git a/packages/safe-chain/package.json b/packages/safe-chain/package.json index c0d2115..6a927d4 100644 --- a/packages/safe-chain/package.json +++ b/packages/safe-chain/package.json @@ -28,7 +28,7 @@ "keywords": [], "author": "Aikido Security", "license": "AGPL-3.0-or-later", - "description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), and [pnpx](https://pnpm.io/cli/dlx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, or pnpx from downloading or running the malware.", + "description": "The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), [pnpx](https://pnpm.io/cli/dlx), [bun](https://bun.sh/), and [bunx](https://bun.sh/docs/cli/bunx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, pnpx, bun, or bunx from downloading or running the malware.", "dependencies": { "abbrev": "3.0.1", "chalk": "5.4.1", From 79a2186c1f144fdd9ade2f84b1fde2cffcd0e6f5 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Wed, 8 Oct 2025 16:42:56 +0200 Subject: [PATCH 4/4] Mention proxy in "how it works" --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b2d1fa4..fd2cdff 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ # Aikido Safe Chain -> πŸš€ **Version 1.1.0: Full Package Manager Support** -> -> Starting from version 1.1.0, Aikido Safe Chain now provides complete protection for all package managers. We've changed how we block malicious packages: instead of checking which packages are being installed, we run a lightweight proxy server that intercepts and blocks downloads of packages containing malware. This means full dependency tree protection for all package managers, not just npm. - The Aikido Safe Chain **prevents developers from installing malware** on their workstations through npm, npx, yarn, pnpm, pnpx, bun, and bunx. It's **free** to use and does not require any token. The Aikido Safe Chain wraps around the [npm cli](https://github.com/npm/cli), [npx](https://github.com/npm/cli/blob/latest/docs/content/commands/npx.md), [yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/), [pnpx](https://pnpm.io/cli/dlx), [bun](https://bun.sh/), and [bunx](https://bun.sh/docs/cli/bunx) to provide extra checks before installing new packages. This tool will detect when a package contains malware and prompt you to exit, preventing npm, npx, yarn, pnpm, pnpx, bun, or bunx from downloading or running the malware. @@ -46,9 +42,9 @@ When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, or `bunx` commands, th ## How it works -The Aikido Safe Chain works by intercepting the npm, npx, yarn, pnpm, pnpx, bun, and bunx commands and verifying the packages against **[Aikido Intel - Open Sources Threat Intelligence](https://intel.aikido.dev/?tab=malware)**. +The Aikido Safe Chain works by running a lightweight proxy server that intercepts package downloads from the npm registry. When you run npm, npx, yarn, pnpm, pnpx, bun, or bunx 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. -The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, bun, and bunx commands. It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which perform malware checks before executing the original commands. We currently support: +The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, bun, and bunx commands. It sets up aliases for these commands so that they are wrapped by the Aikido Safe Chain commands, which manage the proxy server before executing the original commands. We currently support: - βœ… **Bash** - βœ… **Zsh**