Merge pull request #164 from AikidoSec/remove-safe-chain-bun

Remove the safe-chain-bun package
This commit is contained in:
Sander Declerck 2025-11-25 16:07:23 +01:00 committed by GitHub
commit 5b6fe659c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 2 additions and 414 deletions

206
package-lock.json generated
View file

@ -19,10 +19,6 @@
"resolved": "packages/safe-chain",
"link": true
},
"node_modules/@aikidosec/safe-chain-bun": {
"resolved": "packages/safe-chain-bun",
"link": true
},
"node_modules/@aikidosec/safe-chain-e2e-tests": {
"resolved": "test/e2e",
"link": true
@ -143,160 +139,6 @@
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/@oven/bun-darwin-aarch64": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.2.21.tgz",
"integrity": "sha512-SihfZ3czKeWz6Z3m5rUDrMlarwOXjnkUg+7tIiSB9VZCFSvWEItMfdAF170eCXxZmEh7A1dw20a3lW37lkmlrA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"peer": true
},
"node_modules/@oven/bun-darwin-x64": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.2.21.tgz",
"integrity": "sha512-iXr4y2ap6EmME7/EDoLMxSRKAh9yswKfrHDb9sF+ExHbk1C+XsNGxMY73ckQe2w0SIH6NXz2cRMTORbZ8LNjig==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"peer": true
},
"node_modules/@oven/bun-darwin-x64-baseline": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.2.21.tgz",
"integrity": "sha512-3KeslC5z3vpXxluYBqh6EDwojxTSyWJQeYPJFf7y/Z5QJuAN7g33l8jrx072X8P/G8CBzU1lJky14vhhnqWd7A==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"peer": true
},
"node_modules/@oven/bun-linux-aarch64": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.2.21.tgz",
"integrity": "sha512-jpUFKGUpim4h4KOqI1VYYgvifZVrWNQZFrmVPfSqGb0ZzF/p5L2qc9Hy2aUL3Lo+zHMPylwbe0iLKElPYk0xoQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-linux-aarch64-musl": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.2.21.tgz",
"integrity": "sha512-7UoUHKACYDin3iR6kdqUrF1AOCCjTHPTv1xmzlX4rzwNQvFYSAR83AMrY7hkatKGzLYkI8EjXDAvFJpwF+ZxoA==",
"cpu": [
"aarch64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-linux-x64": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.2.21.tgz",
"integrity": "sha512-6RuXFaVU2ve0TVw1vfFo7ix/jh9IX7mMAEhwE2odX8EdX/ea55upiivYQ/EKeXt+Ij3STc2bCeV4vvRoEJAHdg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-linux-x64-baseline": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.2.21.tgz",
"integrity": "sha512-oZ5FUMfeghwbQcL9oxajsKjwVI+1GnVvxcJ3z+pifuXaLMZr25NCr5h0q2j+ZxEFL3RtL/Pyj8/HLfzGEIVAVg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-linux-x64-musl": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.2.21.tgz",
"integrity": "sha512-ioZjU+2yyLJXaDA8FKoy+tj/fuZKovG9EMp+n9+EG7g3MULbe5nU8gdsS/dET28WzuPlDlSkqF8EUocvg4HajQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-linux-x64-musl-baseline": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl-baseline/-/bun-linux-x64-musl-baseline-1.2.21.tgz",
"integrity": "sha512-0NzMg4XdXgujDM2jZogiV6MgACXW0a0NfB+o6fxwmUzdmMBUk1ZMRzypUi4XKjGUe89mYcPJcVFQRRnNwzTK/Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"peer": true
},
"node_modules/@oven/bun-windows-x64": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.2.21.tgz",
"integrity": "sha512-DZVCXrZGN/B4JnVnieZin1Kxse1wOkf+Fm2hDGpZHzs27ECbw5xPMFIc0r/oCpxTc/InxuvYO9UGoOmvhFaHsQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"peer": true
},
"node_modules/@oven/bun-windows-x64-baseline": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.2.21.tgz",
"integrity": "sha512-sTnkLdThgsa6X8ib6eb3+zgy+CGJOibK6Th4wV2wmZFi5af6TM+digEi9i+q/X3nabGwPXm0V4vBiVpvcFilsA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"peer": true
},
"node_modules/@oxlint/darwin-arm64": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-1.22.0.tgz",
@ -559,41 +401,6 @@
"balanced-match": "^1.0.0"
}
},
"node_modules/bun": {
"version": "1.2.21",
"resolved": "https://registry.npmjs.org/bun/-/bun-1.2.21.tgz",
"integrity": "sha512-y0lJ02dS90U3PJm+7KAKY8Se95AQvP5Xm77LouUwrpNOHpv59kBG4SK1+9iE1cAhpUaFipq+0EJ56S6MmE3row==",
"cpu": [
"arm64",
"x64",
"aarch64"
],
"hasInstallScript": true,
"license": "MIT",
"os": [
"darwin",
"linux",
"win32"
],
"peer": true,
"bin": {
"bun": "bin/bun.exe",
"bunx": "bin/bunx.exe"
},
"optionalDependencies": {
"@oven/bun-darwin-aarch64": "1.2.21",
"@oven/bun-darwin-x64": "1.2.21",
"@oven/bun-darwin-x64-baseline": "1.2.21",
"@oven/bun-linux-aarch64": "1.2.21",
"@oven/bun-linux-aarch64-musl": "1.2.21",
"@oven/bun-linux-x64": "1.2.21",
"@oven/bun-linux-x64-baseline": "1.2.21",
"@oven/bun-linux-x64-musl": "1.2.21",
"@oven/bun-linux-x64-musl-baseline": "1.2.21",
"@oven/bun-windows-x64": "1.2.21",
"@oven/bun-windows-x64-baseline": "1.2.21"
}
},
"node_modules/cacache": {
"version": "19.0.1",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz",
@ -1880,7 +1687,7 @@
"certifi": "14.5.15",
"chalk": "5.4.1",
"https-proxy-agent": "7.0.6",
"ini": "^6.0.0",
"ini": "6.0.0",
"make-fetch-happen": "14.0.3",
"node-forge": "1.3.1",
"npm-registry-fetch": "18.0.2",
@ -1910,17 +1717,6 @@
"typescript": "^5.9.3"
}
},
"packages/safe-chain-bun": {
"name": "@aikidosec/safe-chain-bun",
"version": "1.0.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@aikidosec/safe-chain": "file:../safe-chain"
},
"peerDependencies": {
"bun": ">=1.2.21"
}
},
"packages/safe-chain/node_modules/@types/node": {
"version": "18.19.130",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",

View file

@ -7,7 +7,7 @@
"test/e2e"
],
"scripts": {
"test": "npm run test --workspace=packages/safe-chain --workspace=packages/safe-chain-bun",
"test": "npm run test --workspace=packages/safe-chain",
"test:e2e": "npm run test --workspace=test/e2e",
"lint": "npm run lint --workspace=packages/safe-chain",
"typecheck": "npm run typecheck --workspace=packages/safe-chain"

View file

@ -1,30 +0,0 @@
{
"name": "@aikidosec/safe-chain-bun",
"version": "1.0.0",
"type": "module",
"main": "src/index.js",
"scripts": {
"test": "node --test --experimental-test-module-mocks 'src/**/*.spec.js'"
},
"exports": {
".": {
"bun": "./src/index.js",
"default": "./src/index.js"
}
},
"keywords": ["bun", "security", "scanner", "malware", "aikido"],
"author": "Aikido Security",
"license": "AGPL-3.0-or-later",
"description": "Aikido Security Scanner for Bun package manager - detects malware and security threats during package installation",
"repository": {
"type": "git",
"url": "git+https://github.com/AikidoSec/safe-chain.git",
"directory": "packages/safe-chain-bun"
},
"dependencies": {
"@aikidosec/safe-chain": "file:../safe-chain"
},
"peerDependencies": {
"bun": ">=1.2.21"
}
}

View file

@ -1,38 +0,0 @@
// oxlint-disable no-console
import { auditChanges } from "@aikidosec/safe-chain/scanning";
// Bun Security Scanner for Safe-Chain
// This is the entry point for Bun's native security scanner integration
export const scanner = {
version: "1", // Our scanner is using version 1 of the bun security scanner API.
async scan({ packages }) {
const advisories = [];
try {
const changes = packages.map((pkg) => ({
name: pkg.name,
version: pkg.version,
type: "add",
}));
const audit = await auditChanges(changes);
if (!audit.isAllowed) {
for (const change of audit.disallowedChanges) {
advisories.push({
level: "fatal", // Fatal will block the installation process, this is what we want for packages that contain malware.
package: change.name,
url: null,
description: `Package ${change.name}@${change.version} contains known security threats (${change.reason}). Installation blocked by Safe-Chain.`,
});
}
}
} catch (/** @type any */ error) {
console.warn(`Safe-Chain security scan failed: ${error.message}`);
}
return advisories;
},
};

View file

@ -1,140 +0,0 @@
import assert from "node:assert/strict";
import { describe, it, mock } from "node:test";
describe("Bun Scanner", async () => {
const mockAuditChanges = mock.fn();
// Mock the scanning module
mock.module("@aikidosec/safe-chain/scanning", {
namedExports: {
auditChanges: mockAuditChanges,
},
});
const { scanner } = await import("./index.js");
it("should export scanner object with version", () => {
assert.strictEqual(scanner.version, "1");
assert.strictEqual(typeof scanner.scan, "function");
});
it("should return empty advisories for clean packages", async () => {
mockAuditChanges.mock.mockImplementation(() => ({
allowedChanges: [{ name: "express", version: "4.18.2", type: "add" }],
disallowedChanges: [],
isAllowed: true,
}));
const packages = [{ name: "express", version: "4.18.2" }];
const result = await scanner.scan({ packages });
assert.deepEqual(result, []);
assert.strictEqual(mockAuditChanges.mock.callCount(), 1);
assert.deepEqual(mockAuditChanges.mock.calls[0].arguments[0], [
{ name: "express", version: "4.18.2", type: "add" },
]);
});
it("should return fatal advisory for malware packages", async () => {
mockAuditChanges.mock.mockImplementation(() => ({
allowedChanges: [],
disallowedChanges: [
{
name: "malicious-pkg",
version: "1.0.0",
type: "add",
reason: "MALWARE",
},
],
isAllowed: false,
}));
const packages = [{ name: "malicious-pkg", version: "1.0.0" }];
const result = await scanner.scan({ packages });
assert.strictEqual(result.length, 1);
assert.deepEqual(result[0], {
level: "fatal",
package: "malicious-pkg",
url: null,
description: "Package malicious-pkg@1.0.0 contains known security threats (MALWARE). Installation blocked by Safe-Chain.",
});
});
it("should handle multiple packages with mixed results", async () => {
mockAuditChanges.mock.mockImplementation(() => ({
allowedChanges: [{ name: "express", version: "4.18.2", type: "add" }],
disallowedChanges: [
{
name: "malicious-pkg",
version: "1.0.0",
type: "add",
reason: "MALWARE",
},
{
name: "another-bad-pkg",
version: "2.1.0",
type: "add",
reason: "MALWARE",
},
],
isAllowed: false,
}));
const packages = [
{ name: "express", version: "4.18.2" },
{ name: "malicious-pkg", version: "1.0.0" },
{ name: "another-bad-pkg", version: "2.1.0" },
];
const result = await scanner.scan({ packages });
assert.strictEqual(result.length, 2);
assert.strictEqual(result[0].package, "malicious-pkg");
assert.strictEqual(result[0].level, "fatal");
assert.strictEqual(result[1].package, "another-bad-pkg");
assert.strictEqual(result[1].level, "fatal");
});
it("should handle empty package list", async () => {
mockAuditChanges.mock.mockImplementation(() => ({
allowedChanges: [],
disallowedChanges: [],
isAllowed: true,
}));
const result = await scanner.scan({ packages: [] });
assert.deepEqual(result, []);
assert.deepEqual(
mockAuditChanges.mock.calls[mockAuditChanges.mock.callCount() - 1]
.arguments[0],
[]
);
});
it("should convert Bun package format to safe-chain format correctly", async () => {
mockAuditChanges.mock.mockImplementation(() => ({
allowedChanges: [],
disallowedChanges: [],
isAllowed: true,
}));
const bunPackages = [
{ name: "lodash", version: "4.17.21" },
{ name: "@types/node", version: "20.0.0" },
];
await scanner.scan({ packages: bunPackages });
const expectedChanges = [
{ name: "lodash", version: "4.17.21", type: "add" },
{ name: "@types/node", version: "20.0.0", type: "add" },
];
assert.deepEqual(
mockAuditChanges.mock.calls[mockAuditChanges.mock.callCount() - 1]
.arguments[0],
expectedChanges
);
});
});