npm-api-analyzer
Version:
CLI tool to analyze npm packages for network API usage, prototype pollution, and security vulnerabilities
100 lines (99 loc) • 4.24 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Reporter = void 0;
const markdownReporter_1 = require("./markdownReporter");
class Reporter {
static generateReport(result) {
const { packageName, version, apiUsages, summary } = result;
let report = `\n=== NPM Security Analysis Report ===\n`;
report += `Package: ${packageName}@${version}\n`;
report += `Analysis Date: ${new Date().toISOString()}\n\n`;
report += `SUMMARY:\n`;
report += ` Total APIs Found: ${summary.totalAPIs}\n`;
report += ` Network APIs: ${summary.categories.network}\n`;
report += ` DOM Operations: ${summary.categories.dom}\n`;
report += ` Dynamic JS: ${summary.categories.dynamicJs}\n`;
report += ` Risk Level: ${summary.riskLevel.toUpperCase()}\n\n`;
if (summary.totalAPIs > 0) {
report += `API Types Distribution:\n`;
Object.entries(summary.apiTypes).forEach(([type, count]) => {
report += ` ${type}: ${count}\n`;
});
report += `\n`;
report += `DETAILED FINDINGS:\n`;
const groupedAPIs = this.groupAPIsByType(apiUsages);
Object.entries(groupedAPIs).forEach(([type, apis]) => {
report += `\n${type.toUpperCase()} APIs (${apis.length}):\n`;
apis.forEach(api => {
report += ` ✓ ${api.api} [${api.riskLevel.toUpperCase()} RISK]\n`;
report += ` Location: ${api.location.file}:${api.location.line}:${api.location.column}\n`;
report += ` Context: ${api.context.currentLine}\n\n`;
});
});
}
else {
report += `✅ No suspicious API usage detected in this package.\n`;
}
report += `\nRisk Assessment:\n`;
report += this.generateRiskAssessment(result);
return report;
}
static generateMarkdownReport(result) {
return markdownReporter_1.MarkdownReporter.generateMarkdownReport(result);
}
static groupAPIsByType(apis) {
const grouped = {};
apis.forEach(api => {
if (!grouped[api.type]) {
grouped[api.type] = [];
}
grouped[api.type].push(api);
});
return grouped;
}
static generateRiskAssessment(result) {
const { summary } = result;
let assessment = '';
switch (summary.riskLevel) {
case 'low':
assessment = '🟢 LOW: Package has minimal security concerns.\n';
break;
case 'medium':
assessment = '🟡 MEDIUM: Package has some security risks. Review usage carefully.\n';
break;
case 'high':
assessment = '🔴 HIGH: Package has significant security risks. Requires thorough review.\n';
break;
}
if (summary.riskFactors.length > 0) {
assessment += '\nRisk Factors:\n';
summary.riskFactors.forEach(factor => {
assessment += `• ${factor}\n`;
});
}
assessment += '\nRecommendations:\n';
if (summary.categories.dynamicJs > 0) {
assessment += '• Audit all dynamic JavaScript execution carefully\n';
}
if (summary.apiTypes.xhr || summary.apiTypes.fetch) {
assessment += '• Review network requests for data exfiltration risks\n';
}
if (summary.apiTypes.websocket) {
assessment += '• Check WebSocket connections for unauthorized communication\n';
}
if (summary.apiTypes.node) {
assessment += '• Verify server-side HTTP requests are legitimate\n';
}
if (summary.apiTypes['dom-manipulation']) {
assessment += '• Examine DOM manipulation for potential XSS vectors\n';
}
if (summary.totalAPIs > 10) {
assessment += '• Consider using a more lightweight alternative\n';
}
return assessment;
}
static generateJSONReport(result) {
return JSON.stringify(result, null, 2);
}
}
exports.Reporter = Reporter;
;