@aikidosec/safe-chain 0.0.1-immutable-releases-beta

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 (112) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +517 -0
  3. package/bin/aikido-bun.js +14 -0
  4. package/bin/aikido-bunx.js +14 -0
  5. package/bin/aikido-npm.js +14 -0
  6. package/bin/aikido-npx.js +14 -0
  7. package/bin/aikido-pip.js +17 -0
  8. package/bin/aikido-pip3.js +17 -0
  9. package/bin/aikido-pipx.js +16 -0
  10. package/bin/aikido-pnpm.js +14 -0
  11. package/bin/aikido-pnpx.js +14 -0
  12. package/bin/aikido-poetry.js +13 -0
  13. package/bin/aikido-python.js +19 -0
  14. package/bin/aikido-python3.js +19 -0
  15. package/bin/aikido-uv.js +16 -0
  16. package/bin/aikido-yarn.js +14 -0
  17. package/bin/safe-chain.js +130 -0
  18. package/docs/banner.svg +151 -0
  19. package/docs/safe-package-manager-demo.gif +0 -0
  20. package/docs/safe-package-manager-demo.png +0 -0
  21. package/docs/shell-integration.md +149 -0
  22. package/docs/troubleshooting.md +321 -0
  23. package/npm-shrinkwrap.json +4069 -0
  24. package/package.json +72 -0
  25. package/src/api/aikido.js +187 -0
  26. package/src/api/npmApi.js +71 -0
  27. package/src/config/cliArguments.js +161 -0
  28. package/src/config/configFile.js +327 -0
  29. package/src/config/environmentVariables.js +57 -0
  30. package/src/config/settings.js +247 -0
  31. package/src/environment/environment.js +14 -0
  32. package/src/environment/userInteraction.js +122 -0
  33. package/src/main.js +123 -0
  34. package/src/packagemanager/_shared/commandErrors.js +17 -0
  35. package/src/packagemanager/_shared/matchesCommand.js +18 -0
  36. package/src/packagemanager/bun/createBunPackageManager.js +48 -0
  37. package/src/packagemanager/currentPackageManager.js +79 -0
  38. package/src/packagemanager/npm/createPackageManager.js +72 -0
  39. package/src/packagemanager/npm/dependencyScanner/commandArgumentScanner.js +74 -0
  40. package/src/packagemanager/npm/dependencyScanner/nullScanner.js +9 -0
  41. package/src/packagemanager/npm/parsing/parsePackagesFromInstallArgs.js +144 -0
  42. package/src/packagemanager/npm/runNpmCommand.js +20 -0
  43. package/src/packagemanager/npm/utils/abbrevs-generated.js +359 -0
  44. package/src/packagemanager/npm/utils/cmd-list.js +174 -0
  45. package/src/packagemanager/npm/utils/npmCommands.js +34 -0
  46. package/src/packagemanager/npx/createPackageManager.js +15 -0
  47. package/src/packagemanager/npx/dependencyScanner/commandArgumentScanner.js +43 -0
  48. package/src/packagemanager/npx/parsing/parsePackagesFromArguments.js +130 -0
  49. package/src/packagemanager/npx/runNpxCommand.js +20 -0
  50. package/src/packagemanager/pip/createPackageManager.js +25 -0
  51. package/src/packagemanager/pip/pipSettings.js +6 -0
  52. package/src/packagemanager/pip/runPipCommand.js +209 -0
  53. package/src/packagemanager/pipx/createPipXPackageManager.js +18 -0
  54. package/src/packagemanager/pipx/runPipXCommand.js +60 -0
  55. package/src/packagemanager/pnpm/createPackageManager.js +57 -0
  56. package/src/packagemanager/pnpm/dependencyScanner/commandArgumentScanner.js +35 -0
  57. package/src/packagemanager/pnpm/parsing/parsePackagesFromArguments.js +109 -0
  58. package/src/packagemanager/pnpm/runPnpmCommand.js +32 -0
  59. package/src/packagemanager/poetry/createPoetryPackageManager.js +72 -0
  60. package/src/packagemanager/uv/createUvPackageManager.js +18 -0
  61. package/src/packagemanager/uv/runUvCommand.js +66 -0
  62. package/src/packagemanager/yarn/createPackageManager.js +41 -0
  63. package/src/packagemanager/yarn/dependencyScanner/commandArgumentScanner.js +35 -0
  64. package/src/packagemanager/yarn/parsing/parsePackagesFromArguments.js +128 -0
  65. package/src/packagemanager/yarn/runYarnCommand.js +36 -0
  66. package/src/registryProxy/certBundle.js +203 -0
  67. package/src/registryProxy/certUtils.js +178 -0
  68. package/src/registryProxy/getConnectTimeout.js +13 -0
  69. package/src/registryProxy/http-utils.js +80 -0
  70. package/src/registryProxy/interceptors/createInterceptorForEcoSystem.js +25 -0
  71. package/src/registryProxy/interceptors/interceptorBuilder.js +179 -0
  72. package/src/registryProxy/interceptors/minimumPackageAgeExclusions.js +33 -0
  73. package/src/registryProxy/interceptors/npm/modifyNpmInfo.js +180 -0
  74. package/src/registryProxy/interceptors/npm/npmInterceptor.js +101 -0
  75. package/src/registryProxy/interceptors/npm/parseNpmPackageUrl.js +60 -0
  76. package/src/registryProxy/interceptors/pip/modifyPipInfo.js +167 -0
  77. package/src/registryProxy/interceptors/pip/modifyPipJsonResponse.js +176 -0
  78. package/src/registryProxy/interceptors/pip/parsePipPackageUrl.js +162 -0
  79. package/src/registryProxy/interceptors/pip/pipInterceptor.js +122 -0
  80. package/src/registryProxy/interceptors/pip/pipMetadataResponseUtils.js +27 -0
  81. package/src/registryProxy/interceptors/pip/pipMetadataVersionUtils.js +131 -0
  82. package/src/registryProxy/interceptors/suppressedVersionsState.js +21 -0
  83. package/src/registryProxy/isImdsEndpoint.js +13 -0
  84. package/src/registryProxy/mitmRequestHandler.js +240 -0
  85. package/src/registryProxy/plainHttpProxy.js +95 -0
  86. package/src/registryProxy/registryProxy.js +255 -0
  87. package/src/registryProxy/tunnelRequestHandler.js +213 -0
  88. package/src/scanning/audit/index.js +129 -0
  89. package/src/scanning/index.js +82 -0
  90. package/src/scanning/malwareDatabase.js +131 -0
  91. package/src/scanning/newPackagesDatabaseBuilder.js +71 -0
  92. package/src/scanning/newPackagesDatabaseWarnings.js +17 -0
  93. package/src/scanning/newPackagesListCache.js +126 -0
  94. package/src/scanning/packageNameVariants.js +29 -0
  95. package/src/shell-integration/helpers.js +304 -0
  96. package/src/shell-integration/path-wrappers/templates/unix-wrapper.template.sh +22 -0
  97. package/src/shell-integration/path-wrappers/templates/windows-wrapper.template.cmd +24 -0
  98. package/src/shell-integration/setup-ci.js +172 -0
  99. package/src/shell-integration/setup.js +129 -0
  100. package/src/shell-integration/shellDetection.js +39 -0
  101. package/src/shell-integration/startup-scripts/init-fish.fish +115 -0
  102. package/src/shell-integration/startup-scripts/init-posix.sh +96 -0
  103. package/src/shell-integration/startup-scripts/init-pwsh.ps1 +171 -0
  104. package/src/shell-integration/supported-shells/bash.js +152 -0
  105. package/src/shell-integration/supported-shells/fish.js +95 -0
  106. package/src/shell-integration/supported-shells/powershell.js +100 -0
  107. package/src/shell-integration/supported-shells/windowsPowershell.js +100 -0
  108. package/src/shell-integration/supported-shells/zsh.js +92 -0
  109. package/src/shell-integration/teardown.js +112 -0
  110. package/src/ultimate/ultimateTroubleshooting.js +111 -0
  111. package/src/utils/safeSpawn.js +153 -0
  112. package/tsconfig.json +21 -0
@@ -0,0 +1,153 @@
1
+ import { spawn, execSync } from "child_process";
2
+ import os from "os";
3
+ import { ui } from "../environment/userInteraction.js";
4
+
5
+ /**
6
+ * @param {string} arg
7
+ *
8
+ * @returns {string}
9
+ */
10
+ function sanitizeShellArgument(arg) {
11
+ // If argument contains shell metacharacters, wrap in double quotes
12
+ // and escape characters that are special even inside double quotes
13
+ if (hasShellMetaChars(arg)) {
14
+ // Inside double quotes, we need to escape: " $ ` \
15
+ return '"' + escapeDoubleQuoteContent(arg) + '"';
16
+ }
17
+ return arg;
18
+ }
19
+
20
+ /**
21
+ * @param {string} arg
22
+ *
23
+ * @returns {boolean}
24
+ */
25
+ function hasShellMetaChars(arg) {
26
+ // Shell metacharacters that need escaping
27
+ // These characters have special meaning in shells and need to be quoted
28
+ // Whenever one of these characters is present, we should quote the argument
29
+ // Characters: space, ", &, ', |, ;, <, >, (, ), $, `, \, !, *, ?, [, ], {, }, ~, #
30
+ const shellMetaChars = /[ "&'|;<>()$`\\!*?[\]{}~#]/;
31
+ return shellMetaChars.test(arg);
32
+ }
33
+
34
+ /**
35
+ * @param {string} arg
36
+ *
37
+ * @returns {string}
38
+ */
39
+ function escapeDoubleQuoteContent(arg) {
40
+ // Escape special characters for shell safety
41
+ // This escapes ", $, `, and \ by prefixing them with a backslash
42
+ return arg.replace(/(["`$\\])/g, "\\$1");
43
+ }
44
+
45
+ /**
46
+ * @param {string} command
47
+ * @param {string[]} args
48
+ *
49
+ * @returns {string}
50
+ */
51
+ function buildCommand(command, args) {
52
+ if (args.length === 0) {
53
+ return command;
54
+ }
55
+
56
+ const escapedArgs = args.map(sanitizeShellArgument);
57
+
58
+ return `${command} ${escapedArgs.join(" ")}`;
59
+ }
60
+
61
+ /**
62
+ * @param {string} command
63
+ *
64
+ * @returns {string}
65
+ */
66
+ function resolveCommandPath(command) {
67
+ // command will be "npm", "yarn", etc.
68
+ // Use 'command -v' to find the full path
69
+ const fullPath = execSync(`command -v ${command}`, {
70
+ encoding: "utf8",
71
+ }).trim();
72
+
73
+ if (!fullPath) {
74
+ throw new Error(`Command not found: ${command}`);
75
+ }
76
+
77
+ return fullPath;
78
+ }
79
+
80
+ /**
81
+ * @param {string} command
82
+ * @param {string[]} args
83
+ * @param {import("child_process").SpawnOptions} options
84
+ *
85
+ * @returns {Promise<{status: number, stdout: string, stderr: string}>}
86
+ */
87
+ export async function safeSpawn(command, args, options = {}) {
88
+ // The command is always one of our supported package managers.
89
+ // It should always be alphanumeric or _ or -
90
+ // Reject any command names with suspicious characters
91
+ if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
92
+ throw new Error(`Invalid command name: ${command}`);
93
+ }
94
+
95
+ return new Promise((resolve, reject) => {
96
+ // Windows requires shell: true because .bat and .cmd files are not executable
97
+ // without a terminal. On Unix/macOS, we resolve the full path first, then use
98
+ // array args (safer, no escaping needed).
99
+ // See: https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
100
+ let child;
101
+ if (os.platform() === "win32") {
102
+ const fullCommand = buildCommand(command, args);
103
+ child = spawn(fullCommand, { ...options, shell: true });
104
+ } else {
105
+ const fullPath = resolveCommandPath(command);
106
+ child = spawn(fullPath, args, options);
107
+ }
108
+
109
+ // When stdio is piped, we need to collect the output
110
+ let stdout = "";
111
+ let stderr = "";
112
+
113
+ child.stdout?.on("data", (data) => {
114
+ stdout += data.toString();
115
+ });
116
+
117
+ child.stderr?.on("data", (data) => {
118
+ stderr += data.toString();
119
+ });
120
+
121
+ child.on("close", (code) => {
122
+ // Code is null if it terminated by a signal. This should never
123
+ // happen in our code. If this happens, return 1 error code.
124
+
125
+ code = code ?? 1;
126
+
127
+ resolve({
128
+ status: code,
129
+ stdout: stdout,
130
+ stderr: stderr,
131
+ });
132
+ });
133
+
134
+ child.on("error", (error) => {
135
+ reject(error);
136
+ });
137
+ });
138
+ }
139
+
140
+ /**
141
+ * @param {string} command
142
+ * @param {string[]} args
143
+ * @param {import("child_process").SpawnOptions} options
144
+ *
145
+ * @returns {Promise<{status: number, stdout: string, stderr: string}>}
146
+ */
147
+ export async function printVerboseAndSafeSpawn(command, args, options = {}) {
148
+ ui.writeVerbose(`Running: ${command} ${args.join(" ")}`);
149
+
150
+ const result = await safeSpawn(command, args, options);
151
+
152
+ return result;
153
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["es2023"],
4
+ "module": "node16",
5
+ "strict": true,
6
+ "skipLibCheck": true,
7
+ "moduleResolution": "node16",
8
+ "allowJs": true,
9
+ "checkJs": true,
10
+ "noEmit": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": [
14
+ "src/**/*.js",
15
+ "bin/**/*.js"
16
+ ],
17
+ "exclude": [
18
+ "node_modules",
19
+ "src/**/*.spec.js"
20
+ ]
21
+ }