@aikidosec/safe-chain 1.1.10 → 1.2.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 +71 -38
- package/bin/aikido-bun.js +4 -2
- package/bin/aikido-bunx.js +4 -2
- package/bin/aikido-npm.js +4 -2
- package/bin/aikido-npx.js +4 -2
- package/bin/aikido-pip.js +5 -3
- package/bin/aikido-pip3.js +5 -3
- package/bin/aikido-pnpm.js +4 -2
- package/bin/aikido-pnpx.js +4 -2
- package/bin/aikido-python.js +15 -13
- package/bin/aikido-python3.js +15 -13
- package/bin/aikido-uv.js +5 -3
- package/bin/aikido-yarn.js +4 -2
- package/bin/safe-chain.js +106 -10
- package/docs/banner.svg +151 -0
- package/docs/npm-to-binary-migration.md +89 -0
- package/package.json +5 -4
- package/src/packagemanager/pip/runPipCommand.js +25 -0
- package/src/registryProxy/mitmRequestHandler.js +8 -4
- package/src/shell-integration/helpers.js +73 -12
- package/src/shell-integration/path-wrappers/templates/unix-wrapper.template.sh +2 -2
- package/src/shell-integration/path-wrappers/templates/windows-wrapper.template.cmd +2 -2
- package/src/shell-integration/setup-ci.js +26 -9
- package/src/shell-integration/setup.js +17 -5
- package/src/shell-integration/startup-scripts/include-python/init-fish.fish +45 -43
- package/src/shell-integration/startup-scripts/include-python/init-posix.sh +36 -39
- package/src/shell-integration/startup-scripts/include-python/init-pwsh.ps1 +65 -61
- package/src/shell-integration/startup-scripts/init-fish.fish +39 -38
- package/src/shell-integration/startup-scripts/init-posix.sh +30 -34
- package/src/shell-integration/startup-scripts/init-pwsh.ps1 +42 -38
package/README.md
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# Aikido Safe Chain
|
|
2
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/@aikidosec/safe-chain)
|
|
6
|
+
[](https://www.npmjs.com/package/@aikidosec/safe-chain)
|
|
7
|
+
|
|
3
8
|
- ✅ **Block malware on developer laptops and CI/CD**
|
|
4
9
|
- ✅ **Supports npm and PyPI** more package managers coming
|
|
5
10
|
- ✅ **Blocks packages newer than 24 hours** without breaking your build
|
|
6
11
|
- ✅ **Tokenless, free, no build data shared**
|
|
7
12
|
|
|
8
|
-
Aikido Safe Chain
|
|
13
|
+
Aikido Safe Chain supports the following package managers:
|
|
9
14
|
|
|
10
15
|
- 📦 **npm**
|
|
11
16
|
- 📦 **npx**
|
|
@@ -22,29 +27,45 @@ Aikido Safe Chain works on Node.js version 16 and above and supports the followi
|
|
|
22
27
|
|
|
23
28
|
## Installation
|
|
24
29
|
|
|
25
|
-
Installing the Aikido Safe Chain is easy
|
|
30
|
+
Installing the Aikido Safe Chain is easy with our one-line installer.
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
```shell
|
|
29
|
-
npm install -g @aikidosec/safe-chain
|
|
30
|
-
```
|
|
31
|
-
2. **Setup the shell integration** by running:
|
|
32
|
+
> ⚠️ **Already installed via npm?** See the [migration guide](https://github.com/AikidoSec/safe-chain/blob/main/docs/npm-to-binary-migration.md) to switch to the binary version.
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
safe-chain setup
|
|
35
|
-
```
|
|
34
|
+
### Unix/Linux/macOS
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
**Default installation (JavaScript packages only):**
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
```shell
|
|
39
|
+
curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Include Python support (pip/pip3/uv):**
|
|
43
|
+
|
|
44
|
+
```shell
|
|
45
|
+
curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh -s -- --include-python
|
|
46
|
+
```
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
### Windows (PowerShell)
|
|
49
|
+
|
|
50
|
+
**Default installation (JavaScript packages only):**
|
|
51
|
+
|
|
52
|
+
```powershell
|
|
53
|
+
iex (iwr "https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.ps1" -UseBasicParsing)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Include Python support (pip/pip3/uv):**
|
|
57
|
+
|
|
58
|
+
```powershell
|
|
59
|
+
iex "& { $(iwr 'https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.ps1' -UseBasicParsing) } -includepython"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Verify the installation
|
|
63
|
+
|
|
64
|
+
1. **❗Restart your terminal** to start using the Aikido Safe Chain.
|
|
44
65
|
|
|
45
66
|
- This step is crucial as it ensures that the shell aliases for npm, npx, yarn, pnpm, pnpx, bun, bunx, and pip/pip3 are loaded correctly. If you do not restart your terminal, the aliases will not be available.
|
|
46
67
|
|
|
47
|
-
|
|
68
|
+
2. **Verify the installation** by running one of the following commands:
|
|
48
69
|
|
|
49
70
|
For JavaScript/Node.js:
|
|
50
71
|
|
|
@@ -52,7 +73,7 @@ Installing the Aikido Safe Chain is easy. You just need 3 simple steps:
|
|
|
52
73
|
npm install safe-chain-test
|
|
53
74
|
```
|
|
54
75
|
|
|
55
|
-
For Python (
|
|
76
|
+
For Python (if you enabled Python support):
|
|
56
77
|
|
|
57
78
|
```shell
|
|
58
79
|
pip3 install safe-chain-pi-test
|
|
@@ -90,7 +111,7 @@ The Aikido Safe Chain integrates with your shell to provide a seamless experienc
|
|
|
90
111
|
- ✅ **PowerShell**
|
|
91
112
|
- ✅ **PowerShell Core**
|
|
92
113
|
|
|
93
|
-
More information about the shell integration can be found in the [shell integration documentation](docs/shell-integration.md).
|
|
114
|
+
More information about the shell integration can be found in the [shell integration documentation](https://github.com/AikidoSec/safe-chain/blob/main/docs/shell-integration.md).
|
|
94
115
|
|
|
95
116
|
## Uninstallation
|
|
96
117
|
|
|
@@ -161,23 +182,37 @@ You can set the minimum package age through multiple sources (in order of priori
|
|
|
161
182
|
|
|
162
183
|
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.
|
|
163
184
|
|
|
164
|
-
|
|
185
|
+
## Installation for CI/CD
|
|
165
186
|
|
|
166
|
-
|
|
187
|
+
Use the `--ci` flag to automatically configure Aikido Safe Chain for CI/CD environments. This sets up executable shims in the PATH instead of shell aliases.
|
|
167
188
|
|
|
168
|
-
|
|
189
|
+
### Unix/Linux/macOS (GitHub Actions, Azure Pipelines, etc.)
|
|
190
|
+
|
|
191
|
+
**JavaScript only:**
|
|
169
192
|
|
|
170
193
|
```shell
|
|
171
|
-
safe-chain
|
|
194
|
+
curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh -s -- --ci
|
|
172
195
|
```
|
|
173
196
|
|
|
174
|
-
|
|
197
|
+
**With Python support:**
|
|
175
198
|
|
|
176
199
|
```shell
|
|
177
|
-
safe-chain
|
|
200
|
+
curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh -s -- --ci --include-python
|
|
178
201
|
```
|
|
179
202
|
|
|
180
|
-
|
|
203
|
+
### Windows (Azure Pipelines, etc.)
|
|
204
|
+
|
|
205
|
+
**JavaScript only:**
|
|
206
|
+
|
|
207
|
+
```powershell
|
|
208
|
+
iex "& { $(iwr 'https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.ps1' -UseBasicParsing) } -ci"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**With Python support:**
|
|
212
|
+
|
|
213
|
+
```powershell
|
|
214
|
+
iex "& { $(iwr 'https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.ps1' -UseBasicParsing) } -ci -includepython"
|
|
215
|
+
```
|
|
181
216
|
|
|
182
217
|
## Supported Platforms
|
|
183
218
|
|
|
@@ -193,16 +228,15 @@ This automatically configures your CI environment to use Aikido Safe Chain for a
|
|
|
193
228
|
node-version: "22"
|
|
194
229
|
cache: "npm"
|
|
195
230
|
|
|
196
|
-
- name:
|
|
197
|
-
run: |
|
|
198
|
-
npm i -g @aikidosec/safe-chain
|
|
199
|
-
safe-chain setup-ci
|
|
231
|
+
- name: Install safe-chain
|
|
232
|
+
run: curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh -s -- --ci --include-python
|
|
200
233
|
|
|
201
234
|
- name: Install dependencies
|
|
202
|
-
run:
|
|
203
|
-
npm ci
|
|
235
|
+
run: npm ci
|
|
204
236
|
```
|
|
205
237
|
|
|
238
|
+
> **Note:** Remove `--include-python` if you don't need Python (pip/pip3/uv) support.
|
|
239
|
+
|
|
206
240
|
## Azure DevOps Example
|
|
207
241
|
|
|
208
242
|
```yaml
|
|
@@ -211,14 +245,13 @@ This automatically configures your CI environment to use Aikido Safe Chain for a
|
|
|
211
245
|
versionSpec: "22.x"
|
|
212
246
|
displayName: "Install Node.js"
|
|
213
247
|
|
|
214
|
-
- script: |
|
|
215
|
-
|
|
216
|
-
safe-chain setup-ci
|
|
217
|
-
displayName: "Install safe chain"
|
|
248
|
+
- script: curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/install-safe-chain.sh | sh -s -- --ci --include-python
|
|
249
|
+
displayName: "Install safe-chain"
|
|
218
250
|
|
|
219
|
-
- script:
|
|
220
|
-
|
|
221
|
-
displayName: "npm install and build"
|
|
251
|
+
- script: npm ci
|
|
252
|
+
displayName: "Install dependencies"
|
|
222
253
|
```
|
|
223
254
|
|
|
255
|
+
> **Note:** Remove `--include-python` if you don't need Python (pip/pip3/uv) support.
|
|
256
|
+
|
|
224
257
|
After setup, all subsequent package manager commands in your CI pipeline will automatically be protected by Aikido Safe Chain's malware detection.
|
package/bin/aikido-bun.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "bun";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-bunx.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "bunx";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-npm.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "npm";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-npx.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "npx";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-pip.js
CHANGED
|
@@ -13,6 +13,8 @@ setCurrentPipInvocation(PIP_INVOCATIONS.PIP);
|
|
|
13
13
|
|
|
14
14
|
initializePackageManager(PIP_PACKAGE_MANAGER);
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
process.
|
|
16
|
+
(async () => {
|
|
17
|
+
// Pass through only user-supplied pip args
|
|
18
|
+
var exitCode = await main(process.argv.slice(2));
|
|
19
|
+
process.exit(exitCode);
|
|
20
|
+
})();
|
package/bin/aikido-pip3.js
CHANGED
|
@@ -14,6 +14,8 @@ setCurrentPipInvocation(PIP_INVOCATIONS.PIP3);
|
|
|
14
14
|
// Create package manager
|
|
15
15
|
initializePackageManager(PIP_PACKAGE_MANAGER);
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
process.
|
|
17
|
+
(async () => {
|
|
18
|
+
// Pass through only user-supplied pip args
|
|
19
|
+
var exitCode = await main(process.argv.slice(2));
|
|
20
|
+
process.exit(exitCode);
|
|
21
|
+
})();
|
package/bin/aikido-pnpm.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "pnpm";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-pnpx.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "pnpx";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/aikido-python.js
CHANGED
|
@@ -11,18 +11,20 @@ setEcoSystem(ECOSYSTEM_PY);
|
|
|
11
11
|
// Strip nodejs and wrapper script from args
|
|
12
12
|
let argv = process.argv.slice(2);
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
(async () => {
|
|
15
|
+
if (argv[0] === '-m' && (argv[1] === 'pip' || argv[1] === 'pip3')) {
|
|
16
|
+
setEcoSystem(ECOSYSTEM_PY);
|
|
17
|
+
setCurrentPipInvocation(argv[1] === 'pip3' ? PIP_INVOCATIONS.PY_PIP3 : PIP_INVOCATIONS.PY_PIP);
|
|
18
|
+
initializePackageManager(PIP_PACKAGE_MANAGER);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
// Strip off the '-m pip' or '-m pip3' from the args
|
|
21
|
+
argv = argv.slice(2);
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} else {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
23
|
+
var exitCode = await main(argv);
|
|
24
|
+
process.exit(exitCode);
|
|
25
|
+
} else {
|
|
26
|
+
// Forward to real python binary for non-pip flows
|
|
27
|
+
const { spawn } = await import('child_process');
|
|
28
|
+
spawn('python', argv, { stdio: 'inherit' });
|
|
29
|
+
}
|
|
30
|
+
})();
|
package/bin/aikido-python3.js
CHANGED
|
@@ -11,18 +11,20 @@ setEcoSystem(ECOSYSTEM_PY);
|
|
|
11
11
|
// Strip nodejs and wrapper script from args
|
|
12
12
|
let argv = process.argv.slice(2);
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
(async () => {
|
|
15
|
+
if (argv[0] === '-m' && (argv[1] === 'pip' || argv[1] === 'pip3')) {
|
|
16
|
+
setEcoSystem(ECOSYSTEM_PY);
|
|
17
|
+
setCurrentPipInvocation(argv[1] === 'pip3' ? PIP_INVOCATIONS.PY3_PIP3 : PIP_INVOCATIONS.PY3_PIP);
|
|
18
|
+
initializePackageManager(PIP_PACKAGE_MANAGER);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
// Strip off the '-m pip' or '-m pip3' from the args
|
|
21
|
+
argv = argv.slice(2);
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} else {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
23
|
+
var exitCode = await main(argv);
|
|
24
|
+
process.exit(exitCode);
|
|
25
|
+
} else {
|
|
26
|
+
// Forward to real python3 binary for non-pip flows
|
|
27
|
+
const { spawn } = await import('child_process');
|
|
28
|
+
spawn('python3', argv, { stdio: 'inherit' });
|
|
29
|
+
}
|
|
30
|
+
})();
|
package/bin/aikido-uv.js
CHANGED
|
@@ -9,6 +9,8 @@ setEcoSystem(ECOSYSTEM_PY);
|
|
|
9
9
|
|
|
10
10
|
initializePackageManager("uv");
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
process.
|
|
12
|
+
(async () => {
|
|
13
|
+
// Pass through only user-supplied uv args
|
|
14
|
+
var exitCode = await main(process.argv.slice(2));
|
|
15
|
+
process.exit(exitCode);
|
|
16
|
+
})();
|
package/bin/aikido-yarn.js
CHANGED
|
@@ -7,6 +7,8 @@ import { setEcoSystem, ECOSYSTEM_JS } from "../src/config/settings.js";
|
|
|
7
7
|
setEcoSystem(ECOSYSTEM_JS);
|
|
8
8
|
const packageManagerName = "yarn";
|
|
9
9
|
initializePackageManager(packageManagerName);
|
|
10
|
-
var exitCode = await main(process.argv.slice(2));
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
(async () => {
|
|
12
|
+
var exitCode = await main(process.argv.slice(2));
|
|
13
|
+
process.exit(exitCode);
|
|
14
|
+
})();
|
package/bin/safe-chain.js
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import { createRequire } from "module";
|
|
5
4
|
import { ui } from "../src/environment/userInteraction.js";
|
|
6
5
|
import { setup } from "../src/shell-integration/setup.js";
|
|
7
6
|
import { teardown } from "../src/shell-integration/teardown.js";
|
|
8
7
|
import { setupCi } from "../src/shell-integration/setup-ci.js";
|
|
9
8
|
import { initializeCliArguments } from "../src/config/cliArguments.js";
|
|
9
|
+
import { setEcoSystem } from "../src/config/settings.js";
|
|
10
|
+
import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js";
|
|
11
|
+
import { main } from "../src/main.js";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
import fs from "fs";
|
|
15
|
+
import { knownAikidoTools } from "../src/shell-integration/helpers.js";
|
|
16
|
+
import {
|
|
17
|
+
PIP_INVOCATIONS,
|
|
18
|
+
PIP_PACKAGE_MANAGER,
|
|
19
|
+
setCurrentPipInvocation,
|
|
20
|
+
} from "../src/packagemanager/pip/pipSettings.js";
|
|
21
|
+
|
|
22
|
+
/** @type {string} */
|
|
23
|
+
// This checks the current file's dirname in a way that's compatible with:
|
|
24
|
+
// - Modulejs (import.meta.url)
|
|
25
|
+
// - ES modules (__dirname)
|
|
26
|
+
// This is needed because safe-chain's npm package is built using ES modules,
|
|
27
|
+
// but building the binaries requires commonjs.
|
|
28
|
+
let dirname;
|
|
29
|
+
if (import.meta.url) {
|
|
30
|
+
const filename = fileURLToPath(import.meta.url);
|
|
31
|
+
dirname = path.dirname(filename);
|
|
32
|
+
} else {
|
|
33
|
+
dirname = __dirname;
|
|
34
|
+
}
|
|
10
35
|
|
|
11
36
|
if (process.argv.length < 3) {
|
|
12
37
|
ui.writeError("No command provided. Please provide a command to execute.");
|
|
@@ -19,19 +44,35 @@ initializeCliArguments(process.argv);
|
|
|
19
44
|
|
|
20
45
|
const command = process.argv[2];
|
|
21
46
|
|
|
22
|
-
|
|
47
|
+
const tool = knownAikidoTools.find((tool) => tool.tool === command);
|
|
48
|
+
|
|
49
|
+
if (tool && tool.internalPackageManagerName === PIP_PACKAGE_MANAGER) {
|
|
50
|
+
(async function () {
|
|
51
|
+
await executePip(tool);
|
|
52
|
+
})();
|
|
53
|
+
} else if (tool) {
|
|
54
|
+
const args = process.argv.slice(3);
|
|
55
|
+
|
|
56
|
+
setEcoSystem(tool.ecoSystem);
|
|
57
|
+
initializePackageManager(tool.internalPackageManagerName);
|
|
58
|
+
|
|
59
|
+
(async () => {
|
|
60
|
+
var exitCode = await main(args);
|
|
61
|
+
process.exit(exitCode);
|
|
62
|
+
})();
|
|
63
|
+
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
23
64
|
writeHelp();
|
|
24
65
|
process.exit(0);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (command === "setup") {
|
|
66
|
+
} else if (command === "setup") {
|
|
28
67
|
setup();
|
|
29
68
|
} else if (command === "teardown") {
|
|
30
69
|
teardown();
|
|
31
70
|
} else if (command === "setup-ci") {
|
|
32
71
|
setupCi();
|
|
33
72
|
} else if (command === "--version" || command === "-v" || command === "-v") {
|
|
34
|
-
|
|
73
|
+
(async () => {
|
|
74
|
+
ui.writeInformation(`Current safe-chain version: ${await getVersion()}`);
|
|
75
|
+
})();
|
|
35
76
|
} else {
|
|
36
77
|
ui.writeError(`Unknown command: ${command}.`);
|
|
37
78
|
ui.emptyLine();
|
|
@@ -87,8 +128,63 @@ function writeHelp() {
|
|
|
87
128
|
ui.emptyLine();
|
|
88
129
|
}
|
|
89
130
|
|
|
90
|
-
function getVersion() {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
131
|
+
async function getVersion() {
|
|
132
|
+
const packageJsonPath = path.join(dirname, "..", "package.json");
|
|
133
|
+
|
|
134
|
+
const data = await fs.promises.readFile(packageJsonPath);
|
|
135
|
+
const json = JSON.parse(data.toString("utf8"));
|
|
136
|
+
|
|
137
|
+
if (json && json.version) {
|
|
138
|
+
return json.version;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return "0.0.0";
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {import("../src/shell-integration/helpers.js").AikidoTool} tool
|
|
146
|
+
*/
|
|
147
|
+
async function executePip(tool) {
|
|
148
|
+
// Scanners for pip / pip3 / python / python3 use a slightly different approach:
|
|
149
|
+
// - They all use the same PIP_PACKAGE_MANAGER internally, but need some setup to be able to do so
|
|
150
|
+
// - It needs to set which tool to run (pip / pip3 / python / python3)
|
|
151
|
+
// - For python and python3, the -m pip/pip3 args are removed and later added again by the package manager
|
|
152
|
+
// - Python / python3 skips safe-chain if not being run with -m pip or -m pip3
|
|
153
|
+
|
|
154
|
+
let args = process.argv.slice(3);
|
|
155
|
+
setEcoSystem(tool.ecoSystem);
|
|
156
|
+
initializePackageManager(PIP_PACKAGE_MANAGER);
|
|
157
|
+
|
|
158
|
+
let shouldSkip = false;
|
|
159
|
+
if (tool.tool === "pip") {
|
|
160
|
+
setCurrentPipInvocation(PIP_INVOCATIONS.PIP);
|
|
161
|
+
} else if (tool.tool === "pip3") {
|
|
162
|
+
setCurrentPipInvocation(PIP_INVOCATIONS.PIP3);
|
|
163
|
+
} else if (tool.tool === "python") {
|
|
164
|
+
if (args[0] === "-m" && (args[1] === "pip" || args[1] === "pip3")) {
|
|
165
|
+
setCurrentPipInvocation(
|
|
166
|
+
args[1] === "pip3" ? PIP_INVOCATIONS.PY_PIP3 : PIP_INVOCATIONS.PY_PIP
|
|
167
|
+
);
|
|
168
|
+
args = args.slice(2);
|
|
169
|
+
} else {
|
|
170
|
+
shouldSkip = true;
|
|
171
|
+
}
|
|
172
|
+
} else if (tool.tool === "python3") {
|
|
173
|
+
if (args[0] === "-m" && (args[1] === "pip" || args[1] === "pip3")) {
|
|
174
|
+
setCurrentPipInvocation(
|
|
175
|
+
args[1] === "pip3" ? PIP_INVOCATIONS.PY3_PIP3 : PIP_INVOCATIONS.PY3_PIP
|
|
176
|
+
);
|
|
177
|
+
args = args.slice(2);
|
|
178
|
+
} else {
|
|
179
|
+
shouldSkip = true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (shouldSkip) {
|
|
184
|
+
const { spawn } = await import("child_process");
|
|
185
|
+
spawn(tool.tool, args, { stdio: "inherit" });
|
|
186
|
+
} else {
|
|
187
|
+
var exitCode = await main(args);
|
|
188
|
+
process.exit(exitCode);
|
|
189
|
+
}
|
|
94
190
|
}
|