From 15785fad73fb91f6bdb1873dd5ddc4ef730ad814 Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Fri, 24 Oct 2025 09:59:53 -0700 Subject: [PATCH] Make sure we use a different version.txt to prevent having to redownload DB --- packages/safe-chain/src/api/aikido.js | 18 ++------------ packages/safe-chain/src/config/configFile.js | 7 ++++-- .../src/registryProxy/registryProxy.js | 1 - .../src/scanning/malwareDatabase.js | 24 ++++++++++++++++--- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/packages/safe-chain/src/api/aikido.js b/packages/safe-chain/src/api/aikido.js index 9e5f6bd..b38a4cc 100644 --- a/packages/safe-chain/src/api/aikido.js +++ b/packages/safe-chain/src/api/aikido.js @@ -3,22 +3,13 @@ import { getEcoSystem } from "../config/settings.js"; const malwareDatabaseUrls = { js: "https://malware-list.aikido.dev/malware_predictions.json", - py: "https://malware-list.aikido.dev/malware_predictions_python.json", + py: "https://malware-list.aikido.dev/malware_pypi.json", }; export async function fetchMalwareDatabase() { const ecosystem = getEcoSystem() || "js"; const malwareDatabaseUrl = malwareDatabaseUrls[ecosystem]; const response = await fetch(malwareDatabaseUrl); - - // Python malware database doesn't exist yet, return empty database - if (!response.ok && ecosystem === "py" && response.status === 403) { - return { - malwareDatabase: [], - version: undefined, - }; - } - if (!response.ok) { throw new Error(`Error fetching ${ecosystem} malware database: ${response.statusText}`); } @@ -41,12 +32,7 @@ export async function fetchMalwareDatabaseVersion() { const response = await fetch(malwareDatabaseUrl, { method: "HEAD", }); - - // Python malware database doesn't exist yet, return undefined - if (!response.ok && ecosystem === "py" && response.status === 403) { - return undefined; - } - + if (!response.ok) { throw new Error( `Error fetching ${ecosystem} malware database version: ${response.statusText}` diff --git a/packages/safe-chain/src/config/configFile.js b/packages/safe-chain/src/config/configFile.js index 2feb307..1091eb0 100644 --- a/packages/safe-chain/src/config/configFile.js +++ b/packages/safe-chain/src/config/configFile.js @@ -2,6 +2,7 @@ import fs from "fs"; import path from "path"; import os from "os"; import { ui } from "../environment/userInteraction.js"; +import { getEcoSystem } from "./settings.js"; export function getScanTimeout() { const config = readConfigFile(); @@ -68,12 +69,14 @@ function readConfigFile() { function getDatabasePath() { const aikidoDir = getAikidoDirectory(); - return path.join(aikidoDir, "malwareDatabase.json"); + const ecosystem = getEcoSystem() || "js"; + return path.join(aikidoDir, `malwareDatabase_${ecosystem}.json`); } function getDatabaseVersionPath() { const aikidoDir = getAikidoDirectory(); - return path.join(aikidoDir, "version.txt"); + const ecosystem = getEcoSystem() || "js"; + return path.join(aikidoDir, `version_${ecosystem}.txt`); } function getConfigFilePath() { diff --git a/packages/safe-chain/src/registryProxy/registryProxy.js b/packages/safe-chain/src/registryProxy/registryProxy.js index ebb315b..013c470 100644 --- a/packages/safe-chain/src/registryProxy/registryProxy.js +++ b/packages/safe-chain/src/registryProxy/registryProxy.js @@ -111,7 +111,6 @@ function handleConnect(req, clientSocket, head) { // CONNECT method is used for HTTPS requests // It establishes a tunnel to the server identified by the request URL - console.log("**registryProxy.js** Handling CONNECT request for:", req.url); if ((knownJsRegistries.some((reg) => req.url.includes(reg))) || (knownPipRegistries.some((reg) => req.url.includes(reg)))) { mitmConnect(req, clientSocket, isAllowedUrl); diff --git a/packages/safe-chain/src/scanning/malwareDatabase.js b/packages/safe-chain/src/scanning/malwareDatabase.js index 1cb781b..b21733a 100644 --- a/packages/safe-chain/src/scanning/malwareDatabase.js +++ b/packages/safe-chain/src/scanning/malwareDatabase.js @@ -7,9 +7,24 @@ import { writeDatabaseToLocalCache, } from "../config/configFile.js"; import { ui } from "../environment/userInteraction.js"; +import { getEcoSystem } from "../config/settings.js"; let cachedMalwareDatabase = null; +/** + * Normalize package name for comparison. + * For Python packages (PEP-503): lowercase and replace _, -, . with - + * For js packages: keep as-is (case-sensitive) + */ +function normalizePackageName(name) { + const ecosystem = getEcoSystem(); + if (ecosystem === "py") { + return name.toLowerCase().replace(/[-_.]+/g, "-"); + } + + return name; +} + export async function openMalwareDatabase() { if (cachedMalwareDatabase) { return cachedMalwareDatabase; @@ -18,10 +33,13 @@ export async function openMalwareDatabase() { const malwareDatabase = await getMalwareDatabase(); function getPackageStatus(name, version) { + const normalizedName = normalizePackageName(name); const packageData = malwareDatabase.find( - (pkg) => - pkg.package_name === name && - (pkg.version === version || pkg.version === "*") + (pkg) => { + const normalizedPkgName = normalizePackageName(pkg.package_name); + return normalizedPkgName === normalizedName && + (pkg.version === version || pkg.version === "*"); + } ); if (!packageData) {