@aikidosec/safe-chain 1.4.9 → 1.5.1
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.
- package/README.md +34 -6
- package/bin/aikido-uvx.js +16 -0
- package/bin/safe-chain.js +18 -1
- package/docs/Release.md +25 -0
- package/docs/shell-integration.md +4 -4
- package/npm-shrinkwrap.json +53 -942
- package/package.json +3 -4
- package/src/config/configFile.js +2 -2
- package/src/config/safeChainDir.js +71 -0
- package/src/installLocation.js +42 -0
- package/src/packagemanager/currentPackageManager.js +3 -0
- package/src/packagemanager/uvx/createUvxPackageManager.js +18 -0
- package/src/registryProxy/certUtils.js +3 -3
- package/src/registryProxy/interceptors/pip/modifyPipInfo.js +17 -0
- package/src/registryProxy/interceptors/pip/pipInterceptor.js +2 -0
- package/src/scanning/malwareDatabase.js +41 -38
- package/src/scanning/newPackagesListCache.js +16 -19
- package/src/shell-integration/helpers.js +6 -14
- package/src/shell-integration/path-wrappers/templates/unix-wrapper.template.sh +16 -1
- package/src/shell-integration/path-wrappers/templates/windows-wrapper.template.cmd +3 -2
- package/src/shell-integration/setup-ci.js +9 -29
- package/src/shell-integration/setup.js +3 -22
- package/src/shell-integration/startup-scripts/init-fish.fish +8 -1
- package/src/shell-integration/startup-scripts/init-posix.sh +17 -1
- package/src/shell-integration/startup-scripts/init-pwsh.ps1 +6 -1
- package/src/shell-integration/supported-shells/bash.js +75 -5
- package/src/shell-integration/supported-shells/fish.js +7 -5
- package/src/shell-integration/supported-shells/powershell.js +7 -5
- package/src/shell-integration/supported-shells/windowsPowershell.js +7 -5
- package/src/shell-integration/supported-shells/zsh.js +7 -5
- package/src/shell-integration/teardown.js +3 -1
- package/src/ultimate/ultimateTroubleshooting.js +0 -111
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
- ✅ **Blocks packages newer than 48 hours** without breaking your build
|
|
11
11
|
- ✅ **Tokenless, free, no build data shared**
|
|
12
12
|
|
|
13
|
+
## Need protection beyond npm & PyPI?
|
|
14
|
+
|
|
15
|
+
[Aikido Endpoint](https://www.aikido.dev/protect/endpoint-protection?utm_source=github.com&utm_medium=referral&utm_campaign=safechain) builds on Safe Chain, extending package and extension security across more ecosystems: **npm**, **PyPI**, **Maven**, **NuGet**, **VS Code**, **Open VSX** - (Cursor, Windsurf, Kiro, Vs Codium, ...), **Chrome extensions**, **Skills.sh AI skills** and more.
|
|
16
|
+
|
|
17
|
+
Get centralized policy management, request-and-approval workflows, and visibility across every developer workstation in your org. Powered by the same Aikido Intel feed. Deploy it manually or manage it through your MDM tool (Jamf, Fleet, or Iru).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
13
21
|
Aikido Safe Chain supports the following package managers:
|
|
14
22
|
|
|
15
23
|
- 📦 **npm**
|
|
@@ -23,6 +31,7 @@ Aikido Safe Chain supports the following package managers:
|
|
|
23
31
|
- 📦 **pip3**
|
|
24
32
|
- 📦 **uv**
|
|
25
33
|
- 📦 **poetry**
|
|
34
|
+
- 📦 **uvx**
|
|
26
35
|
- 📦 **pipx**
|
|
27
36
|
|
|
28
37
|
# Usage
|
|
@@ -66,7 +75,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
|
|
|
66
75
|
### Verify the installation
|
|
67
76
|
|
|
68
77
|
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.
|
|
78
|
+
- 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
79
|
|
|
71
80
|
2. **Verify the installation** by running the verification command:
|
|
72
81
|
|
|
@@ -97,7 +106,7 @@ You can find all available versions on the [releases page](https://github.com/Ai
|
|
|
97
106
|
|
|
98
107
|
- The output should show that Aikido Safe Chain is blocking the installation of these test packages as they are flagged as malware.
|
|
99
108
|
|
|
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.
|
|
109
|
+
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
110
|
|
|
102
111
|
You can check the installed version by running:
|
|
103
112
|
|
|
@@ -109,7 +118,7 @@ safe-chain --version
|
|
|
109
118
|
|
|
110
119
|
### Malware Blocking
|
|
111
120
|
|
|
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.
|
|
121
|
+
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
122
|
|
|
114
123
|
### Minimum package age
|
|
115
124
|
|
|
@@ -128,7 +137,7 @@ By default, the minimum package age is 48 hours. This provides an additional sec
|
|
|
128
137
|
|
|
129
138
|
### Shell Integration
|
|
130
139
|
|
|
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:
|
|
140
|
+
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
141
|
|
|
133
142
|
- ✅ **Bash**
|
|
134
143
|
- ✅ **Zsh**
|
|
@@ -316,6 +325,24 @@ The base URL should point to a server that mirrors the structure of `https://mal
|
|
|
316
325
|
- `/releases/npm.json` (JavaScript new packages list)
|
|
317
326
|
- `/releases/pypi.json` (Python new packages list)
|
|
318
327
|
|
|
328
|
+
## Custom Install Directory
|
|
329
|
+
|
|
330
|
+
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.
|
|
331
|
+
|
|
332
|
+
When set, all Safe Chain data (binary, shims, scripts, config) is placed under the custom directory instead of `~/.safe-chain`.
|
|
333
|
+
|
|
334
|
+
### Unix/Linux/macOS
|
|
335
|
+
|
|
336
|
+
```shell
|
|
337
|
+
curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh | sh -s -- --install-dir /usr/local/.safe-chain
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Windows
|
|
341
|
+
|
|
342
|
+
```powershell
|
|
343
|
+
iex "& { $(iwr 'https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.ps1' -UseBasicParsing) } -InstallDir 'C:\ProgramData\safe-chain'"
|
|
344
|
+
```
|
|
345
|
+
|
|
319
346
|
# Usage in CI/CD
|
|
320
347
|
|
|
321
348
|
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 +433,7 @@ pipeline {
|
|
|
406
433
|
environment {
|
|
407
434
|
// Jenkins does not automatically persist PATH updates from setup-ci,
|
|
408
435
|
// so add the shims + binary directory explicitly for all stages.
|
|
436
|
+
// If you installed into a custom directory, replace ~/.safe-chain with that path here.
|
|
409
437
|
PATH = "${env.HOME}/.safe-chain/shims:${env.HOME}/.safe-chain/bin:${env.PATH}"
|
|
410
438
|
}
|
|
411
439
|
|
|
@@ -443,7 +471,7 @@ steps:
|
|
|
443
471
|
name: Install
|
|
444
472
|
script:
|
|
445
473
|
- curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh | sh -s -- --ci
|
|
446
|
-
- export PATH=~/.safe-chain/shims:$PATH
|
|
474
|
+
- export PATH=~/.safe-chain/shims:~/.safe-chain/bin:$PATH
|
|
447
475
|
- npm ci
|
|
448
476
|
```
|
|
449
477
|
|
|
@@ -461,7 +489,7 @@ To add safe-chain in GitLab pipelines, you need to install it in the image runni
|
|
|
461
489
|
# Install safe-chain
|
|
462
490
|
RUN curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh | sh -s -- --ci
|
|
463
491
|
|
|
464
|
-
# Add safe-chain to PATH
|
|
492
|
+
# Add safe-chain to PATH (update paths if you used a custom install dir)
|
|
465
493
|
ENV PATH="/root/.safe-chain/shims:/root/.safe-chain/bin:${PATH}"
|
|
466
494
|
```
|
|
467
495
|
|
|
@@ -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",
|
package/docs/Release.md
ADDED
|
@@ -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
|
|