UNPKG

npm-api-analyzer

Version:

CLI tool to analyze npm packages for network API usage, prototype pollution, and security vulnerabilities

96 lines (95 loc) 3.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NPMSecurityAnalyzer = void 0; const packageDownloader_1 = require("./packageDownloader"); const fileAnalyzer_1 = require("./fileAnalyzer"); class NPMSecurityAnalyzer { constructor(tempDir) { this.packageDownloader = new packageDownloader_1.PackageDownloader(tempDir); this.fileAnalyzer = new fileAnalyzer_1.FileAnalyzer(); } async analyzePackage(packageName, version) { console.log(`Analyzing package: ${packageName}@${version}`); try { // Get package info const packageInfo = await this.packageDownloader.getPackageInfo(packageName, version); console.log(`Downloaded package info for ${packageName}@${version}`); // Download package const packageDir = await this.packageDownloader.downloadPackage(packageInfo); console.log(`Extracted package to: ${packageDir}`); // Analyze files const apiUsages = await this.fileAnalyzer.analyzeDirectory(packageDir); console.log(`Found ${apiUsages.length} API usages`); // Generate analysis result const result = { packageName, version, apiUsages, summary: this.generateSummary(apiUsages) }; return result; } catch (error) { throw new Error(`Failed to analyze package ${packageName}@${version}: ${error}`); } } generateSummary(apiUsages) { const apiTypes = {}; const categories = { network: 0, dom: 0, dynamicJs: 0, prototypePollution: 0 }; const riskFactors = []; apiUsages.forEach(api => { apiTypes[api.type] = (apiTypes[api.type] || 0) + 1; // Map category names to object keys const categoryKey = api.category === 'dynamic-js' ? 'dynamicJs' : api.category === 'prototype-pollution' ? 'prototypePollution' : api.category; if (categoryKey in categories) { categories[categoryKey]++; } // Collect risk factors if (api.riskLevel === 'high') { riskFactors.push(`High-risk ${api.category} API: ${api.api}`); } }); const totalAPIs = apiUsages.length; let riskLevel = 'low'; // Determine risk level based on total APIs and high-risk APIs const highRiskAPIs = apiUsages.filter(api => api.riskLevel === 'high').length; const mediumRiskAPIs = apiUsages.filter(api => api.riskLevel === 'medium').length; if (highRiskAPIs > 0 || totalAPIs > 20) { riskLevel = 'high'; } else if (mediumRiskAPIs > 0 || totalAPIs > 5) { riskLevel = 'medium'; } // Additional risk factors if (categories.dynamicJs > 0) { riskFactors.push(`Dynamic JavaScript execution detected (${categories.dynamicJs} instances)`); } if (categories.network > 10) { riskFactors.push(`High network activity (${categories.network} network APIs)`); } if (categories.dom > 0) { riskFactors.push(`DOM manipulation capabilities (${categories.dom} instances)`); } if (categories.prototypePollution > 0) { riskFactors.push(`Prototype pollution risks detected (${categories.prototypePollution} instances)`); } return { totalAPIs, categories, apiTypes, riskLevel, riskFactors }; } cleanup() { this.packageDownloader.cleanup(); } } exports.NPMSecurityAnalyzer = NPMSecurityAnalyzer;