Created
September 8, 2025 21:02
-
-
Save Santiago-j-s/4201a2dbd4b91bc04f5e8e1e36385d4a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| import { execSync } from "child_process"; | |
| import { readFileSync } from "fs"; | |
| import { join, dirname } from "path"; | |
| import { fileURLToPath } from "url"; | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = dirname(__filename); | |
| // Vulnerable package versions from supply chain attack | |
| const vulnerablePackages = [ | |
| "ansi-styles@6.2.2", | |
| "debug@4.4.2", | |
| "chalk@5.6.1", | |
| "supports-color@10.2.1", | |
| "strip-ansi@7.1.1", | |
| "ansi-regex@6.2.1", | |
| "wrap-ansi@9.0.1", | |
| "color-convert@3.1.1", | |
| "color-name@2.0.1", | |
| "is-arrayish@0.3.3", | |
| "slice-ansi@7.1.1", | |
| "color@5.0.1", | |
| "color-string@2.1.1", | |
| "simple-swizzle@0.2.3", | |
| "supports-hyperlinks@4.1.1", | |
| "has-ansi@6.0.1", | |
| "chalk-template@1.1.1", | |
| "backslash@0.2.1", | |
| ]; | |
| // Colors for console output | |
| const colors = { | |
| reset: "\x1b[0m", | |
| bright: "\x1b[1m", | |
| red: "\x1b[31m", | |
| green: "\x1b[32m", | |
| yellow: "\x1b[33m", | |
| blue: "\x1b[34m", | |
| magenta: "\x1b[35m", | |
| cyan: "\x1b[36m", | |
| }; | |
| function colorize(text, color) { | |
| return `${colors[color]}${text}${colors.reset}`; | |
| } | |
| function getAllInstalledPackages() { | |
| try { | |
| const packageLockPath = join(__dirname, "..", "package-lock.json"); | |
| const packageLock = JSON.parse(readFileSync(packageLockPath, "utf8")); | |
| const installedPackages = {}; | |
| // Check all packages in package-lock.json | |
| if (packageLock.packages) { | |
| for (const [packagePath, packageData] of Object.entries( | |
| packageLock.packages, | |
| )) { | |
| if (packagePath.startsWith("node_modules/")) { | |
| const packageName = packagePath.replace("node_modules/", ""); | |
| installedPackages[packageName] = packageData.version; | |
| } | |
| } | |
| } | |
| return installedPackages; | |
| } catch (error) { | |
| console.error( | |
| colorize("Error reading package-lock.json:", "red"), | |
| error.message, | |
| ); | |
| return {}; | |
| } | |
| } | |
| function checkNpmRegistry(packageName) { | |
| try { | |
| const result = execSync(`npm view ${packageName} version`, { | |
| encoding: "utf8", | |
| stdio: "pipe", | |
| }); | |
| return result.trim(); | |
| } catch (error) { | |
| return null; | |
| } | |
| } | |
| function main() { | |
| console.log(colorize("π¨ Supply Chain Attack Vulnerability Check\n", "red")); | |
| console.log( | |
| colorize( | |
| "Checking for vulnerable package versions from supply chain attack...\n", | |
| "yellow", | |
| ), | |
| ); | |
| const installedPackages = getAllInstalledPackages(); | |
| const vulnerableFound = []; | |
| const safeVersions = []; | |
| console.log(colorize("Vulnerability Scan Results:", "bright")); | |
| console.log(colorize("=".repeat(60), "red")); | |
| for (const vulnerableSpec of vulnerablePackages) { | |
| const [packageName, vulnerableVersion] = vulnerableSpec.split("@"); | |
| const installedVersion = installedPackages[packageName]; | |
| if (installedVersion) { | |
| if (installedVersion === vulnerableVersion) { | |
| // VULNERABLE VERSION FOUND! | |
| vulnerableFound.push({ packageName, version: installedVersion }); | |
| console.log( | |
| `\n${colorize("π¨ VULNERABLE", "red")} ${colorize(packageName, "bright")}:`, | |
| ); | |
| console.log( | |
| ` β οΈ Installed: ${colorize(installedVersion, "red")} ${colorize("(VULNERABLE!)", "red")}`, | |
| ); | |
| console.log(` π Vulnerable: ${colorize(vulnerableVersion, "red")}`); | |
| const latestVersion = checkNpmRegistry(packageName); | |
| if (latestVersion) { | |
| console.log(` β Latest Safe: ${colorize(latestVersion, "green")}`); | |
| console.log(` π‘ Action: Update to latest version immediately!`); | |
| } | |
| } else { | |
| // Safe version installed | |
| safeVersions.push({ packageName, version: installedVersion }); | |
| console.log( | |
| `\n${colorize("β SAFE", "green")} ${colorize(packageName, "bright")}:`, | |
| ); | |
| console.log(` β Installed: ${colorize(installedVersion, "green")}`); | |
| console.log(` π Vulnerable: ${colorize(vulnerableVersion, "red")}`); | |
| } | |
| } else { | |
| // Package not installed | |
| console.log( | |
| `\n${colorize("β NOT INSTALLED", "blue")} ${colorize(packageName, "bright")}:`, | |
| ); | |
| console.log(` π Vulnerable: ${colorize(vulnerableVersion, "red")}`); | |
| } | |
| } | |
| // Summary | |
| console.log(`\n${colorize("=".repeat(60), "red")}`); | |
| console.log(colorize("SUMMARY:", "bright")); | |
| if (vulnerableFound.length > 0) { | |
| console.log(`\n${colorize("π¨ VULNERABILITIES FOUND:", "red")}`); | |
| vulnerableFound.forEach(({ packageName, version }) => { | |
| console.log( | |
| ` β’ ${colorize(packageName, "red")}@${colorize(version, "red")}`, | |
| ); | |
| }); | |
| console.log(`\n${colorize("β οΈ IMMEDIATE ACTION REQUIRED:", "red")}`); | |
| console.log( | |
| ` Run: npm update ${vulnerableFound.map((p) => p.packageName).join(" ")}`, | |
| ); | |
| console.log(` Or: npm audit fix`); | |
| } else { | |
| console.log(`\n${colorize("β NO VULNERABILITIES FOUND", "green")}`); | |
| console.log( | |
| ` Your project is safe from these supply chain attack versions.`, | |
| ); | |
| } | |
| if (safeVersions.length > 0) { | |
| console.log(`\n${colorize("β Safe versions installed:", "green")}`); | |
| safeVersions.forEach(({ packageName, version }) => { | |
| console.log( | |
| ` β’ ${colorize(packageName, "green")}@${colorize(version, "green")}`, | |
| ); | |
| }); | |
| } | |
| console.log(`\n${colorize("Check complete!", "cyan")}`); | |
| // Exit with error code if vulnerabilities found | |
| if (vulnerableFound.length > 0) { | |
| process.exit(1); | |
| } | |
| } | |
| main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment