From f01d935bb1e1eb6f598a60a2e9a3038b559b0821 Mon Sep 17 00:00:00 2001 From: 123Haynes <209302+123Haynes@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:08:30 +0000 Subject: [PATCH] remove trailing slashes and fix test failures --- packages/safe-chain/src/api/aikido.js | 10 ++++--- packages/safe-chain/src/api/aikido.spec.js | 9 +++++++ packages/safe-chain/src/config/settings.js | 21 ++++++++++++--- .../safe-chain/src/config/settings.spec.js | 26 +++++++++++++++++++ .../src/scanning/newPackagesDatabase.spec.js | 1 + .../newPackagesDatabaseBuilder.spec.js | 1 + .../src/scanning/newPackagesListCache.spec.js | 1 + 7 files changed, 61 insertions(+), 8 deletions(-) diff --git a/packages/safe-chain/src/api/aikido.js b/packages/safe-chain/src/api/aikido.js index 91ed692..25babb9 100644 --- a/packages/safe-chain/src/api/aikido.js +++ b/packages/safe-chain/src/api/aikido.js @@ -97,12 +97,13 @@ export async function fetchNewPackagesList() { const ecosystem = getEcoSystem(); const baseUrl = getMalwareListBaseUrl(); const path = newPackagesListPaths[/** @type {keyof typeof newPackagesListPaths} */ (ecosystem)]; - const url = `${baseUrl}/${path}`; - if (!url) { + if (!path) { return { newPackagesList: [], version: undefined }; } + const url = `${baseUrl}/${path}`; + const response = await fetch(url); if (!response.ok) { throw new Error( @@ -130,12 +131,13 @@ export async function fetchNewPackagesListVersion() { const ecosystem = getEcoSystem(); const baseUrl = getMalwareListBaseUrl(); const path = newPackagesListPaths[/** @type {keyof typeof newPackagesListPaths} */ (ecosystem)]; - const url = `${baseUrl}/${path}`; - if (!url) { + if (!path) { return undefined; } + const url = `${baseUrl}/${path}`; + const response = await fetch(url, { method: "HEAD" }); if (!response.ok) { throw new Error( diff --git a/packages/safe-chain/src/api/aikido.spec.js b/packages/safe-chain/src/api/aikido.spec.js index 8b8d2dc..f41b9d2 100644 --- a/packages/safe-chain/src/api/aikido.spec.js +++ b/packages/safe-chain/src/api/aikido.spec.js @@ -185,6 +185,15 @@ describe("aikido API", async () => { assert.deepStrictEqual(result.newPackagesList, []); assert.strictEqual(result.version, undefined); }); + + it("should return undefined version without fetching for unsupported ecosystems", async () => { + ecosystem = "ruby"; + + const result = await fetchNewPackagesListVersion(); + + assert.strictEqual(mockFetch.mock.calls.length, 0); + assert.strictEqual(result, undefined); + }); }); describe("fetchNewPackagesListVersion", () => { diff --git a/packages/safe-chain/src/config/settings.js b/packages/safe-chain/src/config/settings.js index 9171849..7aab75f 100644 --- a/packages/safe-chain/src/config/settings.js +++ b/packages/safe-chain/src/config/settings.js @@ -207,21 +207,34 @@ export function getMalwareListBaseUrl() { // Priority 1: CLI argument const cliValue = cliArguments.getMalwareListBaseUrl(); if (cliValue) { - return cliValue; + return removeTrailingSlashes(cliValue); } // Priority 2: Environment variable const envValue = environmentVariables.getMalwareListBaseUrl(); if (envValue) { - return envValue; + return removeTrailingSlashes(envValue); } // Priority 3: Config file const configValue = configFile.getMalwareListBaseUrl(); if (configValue) { - return configValue; + return removeTrailingSlashes(configValue); } // Default - return "https://malware-list.aikido.dev"; + return removeTrailingSlashes("https://malware-list.aikido.dev"); +} + +/** + * Removes trailing slashes from a URL-like string. + * @param {string} value + * @returns {string} + */ +function removeTrailingSlashes(value) { + if (!value || typeof value !== "string") { + return value; + } + + return value.replace(/\/+$/, ""); } diff --git a/packages/safe-chain/src/config/settings.spec.js b/packages/safe-chain/src/config/settings.spec.js index 64e1272..48108c4 100644 --- a/packages/safe-chain/src/config/settings.spec.js +++ b/packages/safe-chain/src/config/settings.spec.js @@ -562,6 +562,32 @@ describe("getMalwareListBaseUrl", () => { assert.strictEqual(url, "https://malware-list.aikido.dev"); }); + it("should trim trailing slash from CLI argument", () => { + initializeCliArguments(["--safe-chain-malware-list-base-url=https://cli-mirror.com/"]); + + const url = getMalwareListBaseUrl(); + + assert.strictEqual(url, "https://cli-mirror.com"); + }); + + it("should trim trailing slash from environment variable", () => { + process.env[envVarName] = "https://env-mirror.com/"; + + const url = getMalwareListBaseUrl(); + + assert.strictEqual(url, "https://env-mirror.com"); + }); + + it("should trim trailing slash from config file value", () => { + configFileContent = JSON.stringify({ + malwareListBaseUrl: "https://config-mirror.com/", + }); + + const url = getMalwareListBaseUrl(); + + assert.strictEqual(url, "https://config-mirror.com"); + }); + it("should return CLI argument value with highest priority", () => { initializeCliArguments(["--safe-chain-malware-list-base-url=https://cli-mirror.com"]); diff --git a/packages/safe-chain/src/scanning/newPackagesDatabase.spec.js b/packages/safe-chain/src/scanning/newPackagesDatabase.spec.js index f363f27..32de737 100644 --- a/packages/safe-chain/src/scanning/newPackagesDatabase.spec.js +++ b/packages/safe-chain/src/scanning/newPackagesDatabase.spec.js @@ -51,6 +51,7 @@ mock.module("../config/settings.js", { namedExports: { getMinimumPackageAgeHours: () => minimumPackageAgeHours, getEcoSystem: () => ecosystem, + getMalwareListBaseUrl: () => "https://malware-list.aikido.dev", ECOSYSTEM_JS: "js", ECOSYSTEM_PY: "py", }, diff --git a/packages/safe-chain/src/scanning/newPackagesDatabaseBuilder.spec.js b/packages/safe-chain/src/scanning/newPackagesDatabaseBuilder.spec.js index 9670a9e..1424a20 100644 --- a/packages/safe-chain/src/scanning/newPackagesDatabaseBuilder.spec.js +++ b/packages/safe-chain/src/scanning/newPackagesDatabaseBuilder.spec.js @@ -8,6 +8,7 @@ mock.module("../config/settings.js", { namedExports: { getMinimumPackageAgeHours: () => minimumPackageAgeHours, getEcoSystem: () => ecosystem, + getMalwareListBaseUrl: () => "https://malware-list.aikido.dev", ECOSYSTEM_JS: "js", ECOSYSTEM_PY: "py", }, diff --git a/packages/safe-chain/src/scanning/newPackagesListCache.spec.js b/packages/safe-chain/src/scanning/newPackagesListCache.spec.js index 8616876..503a0cc 100644 --- a/packages/safe-chain/src/scanning/newPackagesListCache.spec.js +++ b/packages/safe-chain/src/scanning/newPackagesListCache.spec.js @@ -20,6 +20,7 @@ mock.module("../config/settings.js", { namedExports: { getEcoSystem: () => ecosystem, getMinimumPackageAgeHours: () => 24, + getMalwareListBaseUrl: () => "https://malware-list.aikido.dev", ECOSYSTEM_JS: "js", ECOSYSTEM_PY: "py", },