commit c01eb784632ce2a6a26a71f9fa054857847a1c99 Author: Sebastian Kiepsch Date: Wed Sep 10 16:01:44 2025 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1a90a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/ \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..686fe32 --- /dev/null +++ b/Readme.md @@ -0,0 +1,18 @@ +# Vuln Version Checker + +Born out of the need to check existing versions of packages because of these vulnerabilities (https://socket.dev/blog/npm-author-qix-compromised-in-major-supply-chain-attack) + +## How to use + +* Install needed dependencies + +``` +npm install +``` + +* Run the tool + +``` +node index.js vuln.json package-lock.json +``` +* find the generated report in `report.html` \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..b1b5777 --- /dev/null +++ b/index.js @@ -0,0 +1,99 @@ +const fs = require('fs'); +const path = require('path'); +const tableify = require('tableify'); + +// Parse command line arguments +const args = process.argv.slice(2); +if (args.length === 2) { + vulnPath = path.resolve(args[0]); + pkgLockPath = path.resolve(args[1]); +} else { + +} + +function cleanVersion(version) { + if (version.startsWith('^')) { + return version.slice(1); + } else if (version.startsWith('~')) { + return version.slice(1); + } else { + return version; + } +} + +const rawDataVuln = fs.readFileSync(vulnPath, 'utf8'); +const rawDataPackageLock = fs.readFileSync(pkgLockPath, 'utf8'); + +const vulnJson = JSON.parse(rawDataVuln); +const packageLockJson = JSON.parse(rawDataPackageLock); + +let tableOutput = []; +let htmlOutput = ''; +// Check direct package dep +vulnJson.packages.forEach(vulnPackage => { + console.log("Package: " + vulnPackage.name + ' (' + vulnPackage.version + ")"); + + for (var packageName in packageLockJson.packages) { + + // Check if direct package is vuln + if (packageName.includes(vulnPackage.name)) { + var isVuln = packageLockJson.packages[packageName].version == vulnPackage.version ? "[VULNERABLE] " : "[OK] "; + var sameMajor = cleanVersion(packageLockJson.packages[packageName].version).split('.')[0] == vulnPackage.version.split('.')[0]; + if (sameMajor) isVuln = "[SAME MAJOR] " + + tableOutput.push({ + type: "Package", + flag: isVuln, + package_name: packageName, + installed_version: packageLockJson.packages[packageName].version, + vuln_version: vulnPackage.version + }) + + } + + // Check if dependencies are vuln + for (var dependencyName in packageLockJson.packages[packageName].dependencies) { + if (dependencyName.includes(vulnPackage.name)) { + var isVuln = packageLockJson.packages[packageName].dependencies[dependencyName] == vulnPackage.version ? "[VULNERABLE] " : "[OK] "; + var sameMajor = cleanVersion(packageLockJson.packages[packageName].dependencies[dependencyName]).split('.')[0] == vulnPackage.version.split('.')[0]; + if (sameMajor) isVuln = "[SAME MAJOR] " + tableOutput.push({ + type: "Package Dependency", + flag: isVuln, + package_name: dependencyName, + parent: packageName, + installed_version: packageLockJson.packages[packageName].dependencies[dependencyName], + vuln_version: vulnPackage.version, + }) + + } + } + + // Check if dev-Dependencies are vuln + for (var dependencyName in packageLockJson.packages[packageName].devDependencies) { + if (dependencyName.includes(vulnPackage.name)) { + var isVuln = packageLockJson.packages[packageName].devDependencies[dependencyName] == vulnPackage.version ? "[VULNERABLE] " : "[OK] "; + var sameMajor = cleanVersion(packageLockJson.packages[packageName].devDependencies[dependencyName]).split('.')[0] == vulnPackage.version.split('.')[0]; + if (sameMajor) isVuln = "[SAME MAJOR] " + tableOutput.push({ + type: "Package DevDependency", + flag: isVuln, + package_name: dependencyName, + parent: packageName, + installed_version: packageLockJson.packages[packageName].devDependencies[dependencyName], + vuln_version: vulnPackage.version, + }); + + } + } + } + + //console.table(tableOutput); + htmlOutput += "

" + vulnPackage.name + "

" + htmlOutput += tableify(tableOutput) + tableOutput = []; +}); + +fs.writeFileSync("report.html", htmlOutput + ""); + + diff --git a/package-lock-sample.json b/package-lock-sample.json new file mode 100644 index 0000000..b4d9724 --- /dev/null +++ b/package-lock-sample.json @@ -0,0 +1,51 @@ +{ + "name": "frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.1.0", + "dependencies": { + "backslash": "0.2.1", + "@azure/msal-react": "^2.0.22" + }, + "devDependencies": { + "@openapitools/openapi-generator-cli": "^2.13.4", + "@playwright/test": "^1.47.1", + "chalk":"5.6.1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + } + } +} + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b53de56 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,205 @@ +{ + "name": "vuln-checker", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vuln-checker", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "tableify": "^1.1.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tableify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tableify/-/tableify-1.1.1.tgz", + "integrity": "sha512-Wgad32Sgy7+4z4IyeQwiBrgVTEEMMC0CJDt6z3FA8tDruz8ifRUMZR9iE6YzoaGQMqzsC0qRR7Nv+b364dQHbw==", + "license": "MIT", + "dependencies": { + "yargs": "^17.2.1" + }, + "bin": { + "tableify": "bin/tableify" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..60fd2d9 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "vuln-checker", + "version": "1.0.0", + "description": "", + "license": "ISC", + "author": "", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "tableify": "^1.1.1" + } +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..a2a5169 --- /dev/null +++ b/style.css @@ -0,0 +1,49 @@ +body { + font-family: arial; + padding: 50px; + margin: 0px; +} + +table { + font-size: 10pt; + border-top: black 1px solid; + border-right: black 1px solid; + /* border-spacing : 10px */ + border-collapse: collapse; +} + +td, +th { + text-align: left; + vertical-align: top; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-left: black 1px solid; + border-bottom: black 1px solid; + padding-left: 4px; + padding-right: 4px; +} + +th { + background-color: #aaaaaa; +} + +td.number { + color: blue +} + +td.boolean { + color: green; + font-style: italic; +} + +td.date { + color: purple; +} + +td.null:after { + color: gray; + font-style: italic; + content: null; +} \ No newline at end of file diff --git a/vuln.json b/vuln.json new file mode 100644 index 0000000..d3bbe10 --- /dev/null +++ b/vuln.json @@ -0,0 +1,23 @@ +{ + "packages": [ + {"name": "backslash", "version": "0.2.1"}, + {"name": "chalk", "version": "5.6.1"}, + {"name": "chalk-template", "version": "1.1.1"}, + {"name": "color-convert", "version": "3.1.1"}, + {"name": "color-name", "version": "2.0.1"}, + {"name": "color-string", "version": "2.1.1"}, + {"name": "wrap-ansi", "version": "9.0.1"}, + {"name": "supports-hyperlinks", "version": "4.1.1"}, + {"name": "strip-ansi", "version": "7.1.1"}, + {"name": "slice-ansi", "version": "7.1.1"}, + {"name": "simple-swizzle", "version": "0.2.3"}, + {"name": "is-arrayish", "version": "0.3.3"}, + {"name": "error-ex", "version": "1.3.3"}, + {"name": "has-ansi", "version": "6.0.1"}, + {"name": "ansi-regex", "version": "6.2.1"}, + {"name": "ansi-styles", "version": "6.2.2"}, + {"name": "supports-color", "version": "10.2.1"}, + {"name": "proto-tinker-wc", "version": "1.8.7"}, + {"name": "debug", "version": "4.4.2"} + ] +} \ No newline at end of file