mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
100 lines
3.5 KiB
JavaScript
100 lines
3.5 KiB
JavaScript
const fs = require('fs');
|
|
|
|
const audit = JSON.parse(fs.readFileSync('artifacts/npm-audit.json', 'utf8'));
|
|
const outdated = JSON.parse(fs.readFileSync('artifacts/npm-outdated.json', 'utf8'));
|
|
|
|
let report = `# Dependency Report - ${new Date().toISOString().split('T')[0]}\n\n`;
|
|
|
|
report += `## Vulnerabilities\n`;
|
|
const severities = { critical: [], high: [], moderate: [], low: [], info: [] };
|
|
|
|
if (audit.vulnerabilities) {
|
|
for (const [pkg, details] of Object.entries(audit.vulnerabilities)) {
|
|
if (severities[details.severity]) {
|
|
severities[details.severity].push({ pkg, ...details });
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const sev of ['critical', 'high', 'moderate', 'low', 'info']) {
|
|
if (severities[sev].length > 0) {
|
|
report += `### ${sev.toUpperCase()} (${severities[sev].length})\n`;
|
|
severities[sev].forEach(v => {
|
|
// Process 'via' array
|
|
let viaStr = '';
|
|
if (Array.isArray(v.via)) {
|
|
viaStr = v.via.map(item => {
|
|
if (typeof item === 'string') return item;
|
|
return item.title || item.name || 'Unknown advisory';
|
|
}).join(', ');
|
|
} else {
|
|
viaStr = String(v.via);
|
|
}
|
|
|
|
report += `- **${v.pkg}**: ${viaStr}\n`;
|
|
if (sev === 'critical' || sev === 'high') {
|
|
report += ` - Path: Direct dependency? ${v.isDirect ? 'Yes' : 'No'}\n`;
|
|
if (v.fixAvailable) {
|
|
report += ` - Fix Available: ${JSON.stringify(v.fixAvailable)}\n`;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (Object.keys(audit.vulnerabilities || {}).length === 0) {
|
|
report += `No vulnerabilities found.\n`;
|
|
}
|
|
|
|
|
|
report += `\n## Outdated Packages\n`;
|
|
const outdatedList = { major: [], minor: [], patch: [] };
|
|
|
|
for (const [pkg, details] of Object.entries(outdated)) {
|
|
const current = details.current;
|
|
const wanted = details.wanted;
|
|
const latest = details.latest;
|
|
|
|
if (!current) continue;
|
|
|
|
const type = details.type;
|
|
|
|
if (wanted !== current) {
|
|
const cParts = current.split('.');
|
|
const wParts = wanted.split('.');
|
|
if (cParts[0] !== wParts[0]) outdatedList.major.push({ pkg, current, wanted, latest, type });
|
|
else if (cParts[1] !== wParts[1]) outdatedList.minor.push({ pkg, current, wanted, latest, type });
|
|
else outdatedList.patch.push({ pkg, current, wanted, latest, type });
|
|
} else if (latest !== current) {
|
|
outdatedList.major.push({ pkg, current, wanted, latest, type });
|
|
}
|
|
}
|
|
|
|
report += `### Major Updates (Risky)\n`;
|
|
outdatedList.major.forEach(p => report += `- **${p.pkg}** (${p.type}): ${p.current} -> ${p.latest}\n`);
|
|
|
|
report += `\n### Minor Updates (Safe-ish)\n`;
|
|
outdatedList.minor.forEach(p => report += `- **${p.pkg}** (${p.type}): ${p.current} -> ${p.wanted} (Latest: ${p.latest})\n`);
|
|
|
|
report += `\n### Patch Updates (Safe)\n`;
|
|
outdatedList.patch.forEach(p => report += `- **${p.pkg}** (${p.type}): ${p.current} -> ${p.wanted}\n`);
|
|
|
|
|
|
report += `\n## Triage & Actions\n`;
|
|
if (severities.critical.length > 0) {
|
|
report += `- [ ] **CRITICAL**: Investigate ${severities.critical.map(v => v.pkg).join(', ')} immediately.\n`;
|
|
}
|
|
if (severities.high.length > 0) {
|
|
report += `- [ ] **HIGH**: Check for safe upgrades for ${severities.high.map(v => v.pkg).join(', ')}.\n`;
|
|
}
|
|
|
|
const safeUpgrades = [...outdatedList.patch, ...outdatedList.minor].filter(p => p.type !== 'devDependencies');
|
|
if (safeUpgrades.length > 0) {
|
|
report += `- [ ] **Safe Candidates**: ${safeUpgrades.map(p => p.pkg).join(', ')}\n`;
|
|
} else {
|
|
report += `- No safe direct dependency upgrades identified.\n`;
|
|
}
|
|
|
|
fs.writeFileSync('artifacts/deps-report.md', report);
|
|
console.log('Report generated.');
|