diff --git a/package-lock.json b/package-lock.json index 73ed31e..60bd1bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 6a5dec3..aa40862 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/packages/safe-chain-bun/package.json b/packages/safe-chain-bun/package.json deleted file mode 100644 index ca154b8..0000000 --- a/packages/safe-chain-bun/package.json +++ /dev/null @@ -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" - } -} diff --git a/packages/safe-chain-bun/src/index.js b/packages/safe-chain-bun/src/index.js deleted file mode 100644 index 6e933c3..0000000 --- a/packages/safe-chain-bun/src/index.js +++ /dev/null @@ -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; - }, -}; diff --git a/packages/safe-chain-bun/src/index.spec.js b/packages/safe-chain-bun/src/index.spec.js deleted file mode 100644 index 3293b56..0000000 --- a/packages/safe-chain-bun/src/index.spec.js +++ /dev/null @@ -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 - ); - }); -});