@aikidosec/safe-chain 1.4.9 β†’ 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +25 -5
  2. package/bin/aikido-uvx.js +16 -0
  3. package/bin/safe-chain.js +18 -1
  4. package/docs/Release.md +25 -0
  5. package/docs/shell-integration.md +4 -4
  6. package/npm-shrinkwrap.json +54 -943
  7. package/package.json +3 -4
  8. package/src/config/configFile.js +2 -2
  9. package/src/config/safeChainDir.js +71 -0
  10. package/src/installLocation.js +42 -0
  11. package/src/packagemanager/currentPackageManager.js +3 -0
  12. package/src/packagemanager/uvx/createUvxPackageManager.js +18 -0
  13. package/src/registryProxy/certUtils.js +3 -3
  14. package/src/registryProxy/interceptors/pip/modifyPipInfo.js +17 -0
  15. package/src/registryProxy/interceptors/pip/pipInterceptor.js +2 -0
  16. package/src/shell-integration/helpers.js +6 -14
  17. package/src/shell-integration/path-wrappers/templates/unix-wrapper.template.sh +16 -1
  18. package/src/shell-integration/path-wrappers/templates/windows-wrapper.template.cmd +3 -2
  19. package/src/shell-integration/setup-ci.js +9 -29
  20. package/src/shell-integration/setup.js +3 -22
  21. package/src/shell-integration/startup-scripts/init-fish.fish +8 -1
  22. package/src/shell-integration/startup-scripts/init-posix.sh +17 -1
  23. package/src/shell-integration/startup-scripts/init-pwsh.ps1 +6 -1
  24. package/src/shell-integration/supported-shells/bash.js +75 -5
  25. package/src/shell-integration/supported-shells/fish.js +7 -5
  26. package/src/shell-integration/supported-shells/powershell.js +7 -5
  27. package/src/shell-integration/supported-shells/windowsPowershell.js +7 -5
  28. package/src/shell-integration/supported-shells/zsh.js +7 -5
  29. package/src/shell-integration/teardown.js +3 -1
  30. package/src/ultimate/ultimateTroubleshooting.js +0 -111
package/README.md CHANGED
@@ -23,6 +23,7 @@ Aikido Safe Chain supports the following package managers:
23
23
  - πŸ“¦ **pip3**
24
24
  - πŸ“¦ **uv**
25
25
  - πŸ“¦ **poetry**
26
+ - πŸ“¦ **uvx**
26
27
  - πŸ“¦ **pipx**
27
28
 
28
29
  # Usage
@@ -66,7 +67,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
66
67
  ### Verify the installation
67
68
 
68
69
  1. **❗Restart your terminal** to start using the Aikido Safe Chain.
69
- - This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, bun, bunx, pip, pip3, poetry, uv and pipx are loaded correctly. If you do not restart your terminal, the aliases will not be available.
70
+ - This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, bun, bunx, pip, pip3, poetry, uv, uvx and pipx are loaded correctly. If you do not restart your terminal, the aliases will not be available.
70
71
 
71
72
  2. **Verify the installation** by running the verification command:
72
73
 
@@ -97,7 +98,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
97
98
 
98
99
  - The output should show that Aikido Safe Chain is blocking the installation of these test packages as they are flagged as malware.
99
100
 
100
- When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `poetry` and `pipx` commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. It also intercepts Python module invocations for pip when available (e.g., `python -m pip install ...`, `python3 -m pip download ...`). If any malware is detected, it will prompt you to exit the command.
101
+ When running `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` commands, the Aikido Safe Chain will automatically check for malware in the packages you are trying to install. It also intercepts Python module invocations for pip when available (e.g., `python -m pip install ...`, `python3 -m pip download ...`). If any malware is detected, it will prompt you to exit the command.
101
102
 
102
103
  You can check the installed version by running:
103
104
 
@@ -109,7 +110,7 @@ safe-chain --version
109
110
 
110
111
  ### Malware Blocking
111
112
 
112
- 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, pip3, uv, poetry or pipx 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.
113
+ 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, pip3, uv, uvx, poetry or pipx 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.
113
114
 
114
115
  ### Minimum package age
115
116
 
@@ -128,7 +129,7 @@ By default, the minimum package age is 48 hours. This provides an additional sec
128
129
 
129
130
  ### Shell Integration
130
131
 
131
- The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, bun, bunx, and Python package managers (pip, uv, poetry, pipx). 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:
132
+ The Aikido Safe Chain integrates with your shell to provide a seamless experience when using npm, npx, yarn, pnpm, pnpx, bun, bunx, and Python package managers (pip, uv, uvx, poetry, pipx). 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:
132
133
 
133
134
  - βœ… **Bash**
134
135
  - βœ… **Zsh**
@@ -316,6 +317,24 @@ The base URL should point to a server that mirrors the structure of `https://mal
316
317
  - `/releases/npm.json` (JavaScript new packages list)
317
318
  - `/releases/pypi.json` (Python new packages list)
318
319
 
320
+ ## Custom Install Directory
321
+
322
+ By default, Safe Chain installs itself into `~/.safe-chain`. You can change this by passing an explicit install directory to the installer. This is useful for system-wide installations (e.g. inside a Docker image) or when you need to avoid conflicts with other tools.
323
+
324
+ When set, all Safe Chain data (binary, shims, scripts, config) is placed under the custom directory instead of `~/.safe-chain`.
325
+
326
+ ### Unix/Linux/macOS
327
+
328
+ ```shell
329
+ curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh | sh -s -- --install-dir /usr/local/.safe-chain
330
+ ```
331
+
332
+ ### Windows
333
+
334
+ ```powershell
335
+ iex "& { $(iwr 'https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.ps1' -UseBasicParsing) } -InstallDir 'C:\ProgramData\safe-chain'"
336
+ ```
337
+
319
338
  # Usage in CI/CD
320
339
 
321
340
  You can protect your CI/CD pipelines from malicious packages by integrating Aikido Safe Chain into your build process. This ensures that any packages installed during your automated builds are checked for malware before installation.
@@ -406,6 +425,7 @@ pipeline {
406
425
  environment {
407
426
  // Jenkins does not automatically persist PATH updates from setup-ci,
408
427
  // so add the shims + binary directory explicitly for all stages.
428
+ // If you installed into a custom directory, replace ~/.safe-chain with that path here.
409
429
  PATH = "${env.HOME}/.safe-chain/shims:${env.HOME}/.safe-chain/bin:${env.PATH}"
410
430
  }
411
431
 
@@ -461,7 +481,7 @@ To add safe-chain in GitLab pipelines, you need to install it in the image runni
461
481
  # Install safe-chain
462
482
  RUN curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh | sh -s -- --ci
463
483
 
464
- # Add safe-chain to PATH
484
+ # Add safe-chain to PATH (update paths if you used a custom install dir)
465
485
  ENV PATH="/root/.safe-chain/shims:/root/.safe-chain/bin:${PATH}"
466
486
  ```
467
487
 
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from "../src/main.js";
4
+ import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js";
5
+ import { setEcoSystem, ECOSYSTEM_PY } from "../src/config/settings.js";
6
+
7
+ // Set eco system
8
+ setEcoSystem(ECOSYSTEM_PY);
9
+
10
+ initializePackageManager("uvx");
11
+
12
+ (async () => {
13
+ // Pass through only user-supplied uvx args
14
+ var exitCode = await main(process.argv.slice(2));
15
+ process.exit(exitCode);
16
+ })();
package/bin/safe-chain.js CHANGED
@@ -16,6 +16,7 @@ import path from "path";
16
16
  import { fileURLToPath } from "url";
17
17
  import fs from "fs";
18
18
  import { knownAikidoTools } from "../src/shell-integration/helpers.js";
19
+ import { getInstalledSafeChainDir } from "../src/installLocation.js";
19
20
 
20
21
  /** @type {string} */
21
22
  // This checks the current file's dirname in a way that's compatible with:
@@ -67,6 +68,17 @@ if (tool) {
67
68
  teardownDirectories();
68
69
  } else if (command === "setup-ci") {
69
70
  setupCi();
71
+ } else if (command === "get-install-dir") {
72
+ const installDir = getInstalledSafeChainDir();
73
+ if (!installDir) {
74
+ ui.writeError(
75
+ "Install directory is only available for packaged safe-chain binaries.",
76
+ );
77
+ process.exit(1);
78
+ }
79
+
80
+ ui.writeInformation(installDir);
81
+ process.exit(0);
70
82
  } else if (command === "--version" || command === "-v" || command === "-v") {
71
83
  (async () => {
72
84
  ui.writeInformation(`Current safe-chain version: ${await getVersion()}`);
@@ -88,7 +100,7 @@ function writeHelp() {
88
100
  ui.writeInformation(
89
101
  `Available commands: ${chalk.cyan("setup")}, ${chalk.cyan(
90
102
  "teardown",
91
- )}, ${chalk.cyan("setup-ci")}, ${chalk.cyan("help")}, ${chalk.cyan(
103
+ )}, ${chalk.cyan("setup-ci")}, ${chalk.cyan("get-install-dir")}, ${chalk.cyan("help")}, ${chalk.cyan(
92
104
  "--version",
93
105
  )}`,
94
106
  );
@@ -108,6 +120,11 @@ function writeHelp() {
108
120
  "safe-chain setup-ci",
109
121
  )}: This will setup safe-chain for CI environments by creating shims and modifying the PATH.`,
110
122
  );
123
+ ui.writeInformation(
124
+ `- ${chalk.cyan(
125
+ "safe-chain get-install-dir",
126
+ )}: Print the install directory for packaged safe-chain binaries.`,
127
+ );
111
128
  ui.writeInformation(
112
129
  `- ${chalk.cyan("safe-chain --version")} (or ${chalk.cyan(
113
130
  "-v",
@@ -0,0 +1,25 @@
1
+ # Release Guide
2
+
3
+ ## Steps
4
+
5
+ ### 1. Create and push a version tag
6
+
7
+ ```bash
8
+ git tag 1.0.0
9
+ git push origin 1.0.0
10
+ ```
11
+
12
+ This triggers the build pipeline, which compiles binaries for all platforms and creates a draft GitHub release.
13
+
14
+ ### 2. Wait for artifacts to build
15
+
16
+ Monitor the [Actions tab](https://github.com/AikidoSec/safe-chain/actions) until the `Create Release` workflow completes.
17
+
18
+ ### 3. Publish the GitHub release
19
+
20
+ 1. Go to the [Releases page](https://github.com/AikidoSec/safe-chain/releases)
21
+ 2. Open the draft release created for your tag
22
+ 3. Add release notes
23
+ 4. Click **Publish release**
24
+
25
+ Publishing the release automatically triggers an npm publish. Pre-release versions (e.g. `1.0.0-beta`) are published to npm under a tag matching the pre-release identifier (e.g. `beta`). Stable versions are published to the `latest` tag.
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `poetry`, `pipx`) with Aikido's security scanning functionality. It also intercepts Python module invocations for pip when available: `python -m pip`, `python -m pip3`, `python3 -m pip`, `python3 -m pip3`. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents.
5
+ The shell integration automatically wraps common package manager commands (`npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry`, `pipx`) with Aikido's security scanning functionality. It also intercepts Python module invocations for pip when available: `python -m pip`, `python -m pip3`, `python3 -m pip`, `python3 -m pip3`. This is achieved by sourcing startup scripts that define shell functions to wrap these commands with their Aikido-protected equivalents.
6
6
 
7
7
  ## Supported Shells
8
8
 
@@ -28,7 +28,7 @@ This command:
28
28
 
29
29
  - Copies necessary startup scripts to Safe Chain's installation directory (`~/.safe-chain/scripts`)
30
30
  - Detects all supported shells on your system
31
- - Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `poetry` and `pipx`
31
+ - Sources each shell's startup file to add Safe Chain functions for `npm`, `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx`
32
32
  - Adds lightweight interceptors so `python -m pip[...]` and `python3 -m pip[...]` route through Safe Chain when invoked by name
33
33
 
34
34
  ❗ After running this command, **you must restart your terminal** for the changes to take effect. This ensures that the startup scripts are sourced correctly.
@@ -78,7 +78,7 @@ The system modifies the following files to source Safe Chain startup scripts:
78
78
  This means the shell functions are working but the Aikido commands aren't installed or available in your PATH:
79
79
 
80
80
  - Make sure Aikido Safe Chain is properly installed on your system
81
- - Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm`, `aikido-pnpx`, `aikido-bun`, `aikido-bunx`, `aikido-pip`, `aikido-pip3`, `aikido-uv`, `aikido-poetry` and `aikido-pipx` commands exist
81
+ - Verify the `aikido-npm`, `aikido-npx`, `aikido-yarn`, `aikido-pnpm`, `aikido-pnpx`, `aikido-bun`, `aikido-bunx`, `aikido-pip`, `aikido-pip3`, `aikido-uv`, `aikido-uvx`, `aikido-poetry` and `aikido-pipx` commands exist
82
82
  - Check that these commands are in your system's PATH
83
83
 
84
84
  ### Manual Verification
@@ -121,7 +121,7 @@ npm() {
121
121
  }
122
122
  ```
123
123
 
124
- Repeat this pattern for `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `poetry` and `pipx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes.
124
+ Repeat this pattern for `npx`, `yarn`, `pnpm`, `pnpx`, `bun`, `bunx`, `pip`, `pip3`, `uv`, `uvx`, `poetry` and `pipx` using their respective `aikido-*` commands. After adding these functions, restart your terminal to apply the changes.
125
125
 
126
126
  To intercept Python module invocations for pip without altering Python itself, you can add small forwarding functions:
127
127