grepleaks 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/grepleaks.js +71 -36
- package/package.json +1 -1
package/bin/grepleaks.js
CHANGED
|
@@ -9,7 +9,7 @@ const readline = require('readline');
|
|
|
9
9
|
const { exec } = require('child_process');
|
|
10
10
|
const archiver = require('archiver');
|
|
11
11
|
|
|
12
|
-
const VERSION = '1.0.
|
|
12
|
+
const VERSION = '1.0.3';
|
|
13
13
|
const API_URL = 'https://grepleaks.com/api/v1';
|
|
14
14
|
const WEB_URL = 'https://grepleaks.com';
|
|
15
15
|
const CONFIG_DIR = path.join(os.homedir(), '.grepleaks');
|
|
@@ -491,18 +491,46 @@ function generateMarkdownReport(result) {
|
|
|
491
491
|
const score = result.security_score || 0;
|
|
492
492
|
const grade = result.grade_level || 'N/A';
|
|
493
493
|
const projectName = result.project_name || 'Unknown Project';
|
|
494
|
+
const lang = getLang();
|
|
495
|
+
|
|
496
|
+
const dateStr = new Date().toLocaleDateString(lang === 'fr' ? 'fr-FR' : 'en-US', {
|
|
497
|
+
year: 'numeric',
|
|
498
|
+
month: 'long',
|
|
499
|
+
day: 'numeric'
|
|
500
|
+
});
|
|
494
501
|
|
|
495
|
-
|
|
502
|
+
// Count by severity
|
|
503
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
504
|
+
for (const v of vulns) {
|
|
505
|
+
const sev = (v.severity || 'low').toLowerCase();
|
|
506
|
+
if (counts[sev] !== undefined) counts[sev]++;
|
|
507
|
+
}
|
|
496
508
|
|
|
497
|
-
|
|
498
|
-
md
|
|
499
|
-
md +=
|
|
500
|
-
|
|
509
|
+
// Header
|
|
510
|
+
let md = `# ${t('reportTitle')}\n\n`;
|
|
511
|
+
md += `> **${projectName}** | ${dateStr}\n\n`;
|
|
512
|
+
|
|
513
|
+
// Score card
|
|
514
|
+
const scoreEmoji = score >= 90 ? '🛡️' : score >= 75 ? '✅' : score >= 50 ? '⚠️' : '🚨';
|
|
515
|
+
md += `## ${scoreEmoji} ${lang === 'fr' ? 'Score de Sécurité' : 'Security Score'}: ${score}/100 (${grade})\n\n`;
|
|
516
|
+
|
|
517
|
+
// Summary table
|
|
518
|
+
if (vulns.length > 0) {
|
|
519
|
+
md += `| ${lang === 'fr' ? 'Sévérité' : 'Severity'} | ${lang === 'fr' ? 'Nombre' : 'Count'} |\n`;
|
|
520
|
+
md += `|----------|-------|\n`;
|
|
521
|
+
if (counts.critical > 0) md += `| 🔴 Critical | ${counts.critical} |\n`;
|
|
522
|
+
if (counts.high > 0) md += `| 🟠 High | ${counts.high} |\n`;
|
|
523
|
+
if (counts.medium > 0) md += `| 🟡 Medium | ${counts.medium} |\n`;
|
|
524
|
+
if (counts.low > 0) md += `| 🟢 Low | ${counts.low} |\n`;
|
|
525
|
+
md += `\n`;
|
|
526
|
+
}
|
|
501
527
|
|
|
528
|
+
// Vulnerabilities
|
|
502
529
|
if (vulns.length === 0) {
|
|
503
|
-
md += `## ${t('reportNoVulns')}\n\n`;
|
|
530
|
+
md += `## ✅ ${t('reportNoVulns')}\n\n`;
|
|
504
531
|
md += `${t('reportCongrats')}\n`;
|
|
505
532
|
} else {
|
|
533
|
+
md += `---\n\n`;
|
|
506
534
|
md += `## ${t('reportVulnsDetected')}\n\n`;
|
|
507
535
|
|
|
508
536
|
const bySeverity = { CRITICAL: [], HIGH: [], MEDIUM: [], LOW: [] };
|
|
@@ -518,64 +546,71 @@ function generateMarkdownReport(result) {
|
|
|
518
546
|
severity === 'HIGH' ? '🟠' :
|
|
519
547
|
severity === 'MEDIUM' ? '🟡' : '🟢';
|
|
520
548
|
|
|
521
|
-
|
|
549
|
+
const severityLabel = lang === 'fr'
|
|
550
|
+
? { CRITICAL: 'Critique', HIGH: 'Élevée', MEDIUM: 'Moyenne', LOW: 'Faible' }[severity]
|
|
551
|
+
: severity.charAt(0) + severity.slice(1).toLowerCase();
|
|
522
552
|
|
|
523
|
-
|
|
524
|
-
// Title: use rule_id or description snippet
|
|
525
|
-
const title = v.rule_id || (v.description ? v.description.substring(0, 50) + '...' : 'Vulnerability');
|
|
526
|
-
md += `#### ${title}\n\n`;
|
|
553
|
+
md += `### ${emoji} ${severityLabel}\n\n`;
|
|
527
554
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
555
|
+
for (let i = 0; i < items.length; i++) {
|
|
556
|
+
const v = items[i];
|
|
557
|
+
|
|
558
|
+
// Title from description (first sentence or truncated)
|
|
559
|
+
let title = v.description || 'Security Issue';
|
|
560
|
+
const firstSentence = title.match(/^[^.!?]+[.!?]/);
|
|
561
|
+
if (firstSentence) {
|
|
562
|
+
title = firstSentence[0];
|
|
563
|
+
} else if (title.length > 80) {
|
|
564
|
+
title = title.substring(0, 77) + '...';
|
|
531
565
|
}
|
|
532
566
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
567
|
+
md += `<details>\n<summary><strong>${title}</strong></summary>\n\n`;
|
|
568
|
+
|
|
569
|
+
// Location
|
|
570
|
+
if (v.location) {
|
|
571
|
+
md += `📍 **${lang === 'fr' ? 'Emplacement' : 'Location'}:** \`${v.location}\`\n\n`;
|
|
536
572
|
}
|
|
537
573
|
|
|
538
|
-
// CVE
|
|
574
|
+
// CVE
|
|
539
575
|
if (v.cve) {
|
|
540
|
-
md +=
|
|
576
|
+
md += `🔖 **CVE:** [${v.cve}](https://nvd.nist.gov/vuln/detail/${v.cve})\n\n`;
|
|
541
577
|
}
|
|
542
578
|
|
|
543
|
-
// Package info
|
|
579
|
+
// Package info
|
|
544
580
|
if (v.package_name) {
|
|
545
|
-
md +=
|
|
546
|
-
if (v.current_version) md += `
|
|
581
|
+
md += `📦 **Package:** \`${v.package_name}\``;
|
|
582
|
+
if (v.current_version) md += ` v${v.current_version}`;
|
|
547
583
|
md += `\n`;
|
|
548
584
|
if (v.fixed_version) {
|
|
549
|
-
md +=
|
|
585
|
+
md += `✅ **${lang === 'fr' ? 'Correction' : 'Fix'}:** ${lang === 'fr' ? 'Mettre à jour vers' : 'Upgrade to'} v${v.fixed_version}\n`;
|
|
550
586
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
// Description
|
|
554
|
-
if (v.description) {
|
|
555
|
-
md += `\n${v.description}\n`;
|
|
587
|
+
md += `\n`;
|
|
556
588
|
}
|
|
557
589
|
|
|
558
590
|
// Code snippet
|
|
559
591
|
if (v.code_snippet) {
|
|
560
|
-
md +=
|
|
592
|
+
md += `**${lang === 'fr' ? 'Code concerné' : 'Affected code'}:**\n\`\`\`\n${v.code_snippet}\n\`\`\`\n\n`;
|
|
561
593
|
}
|
|
562
594
|
|
|
563
595
|
// Recommendation
|
|
564
|
-
|
|
565
|
-
|
|
596
|
+
const rec = v.llm_recommendation || v.recommendation;
|
|
597
|
+
if (rec) {
|
|
598
|
+
md += `💡 **${t('reportRecommendation')}**\n\n${rec}\n\n`;
|
|
566
599
|
}
|
|
567
600
|
|
|
568
|
-
// Reference
|
|
601
|
+
// Reference
|
|
569
602
|
if (v.reference_url) {
|
|
570
|
-
md +=
|
|
603
|
+
md += `🔗 [${lang === 'fr' ? 'Plus d\'informations' : 'Learn more'}](${v.reference_url})\n\n`;
|
|
571
604
|
}
|
|
572
605
|
|
|
573
|
-
md +=
|
|
606
|
+
md += `</details>\n\n`;
|
|
574
607
|
}
|
|
575
608
|
}
|
|
576
609
|
}
|
|
577
610
|
|
|
578
|
-
|
|
611
|
+
// Footer
|
|
612
|
+
md += `---\n\n`;
|
|
613
|
+
md += `<sub>${t('reportGeneratedBy')} [grepleaks](https://grepleaks.com) ${scoreEmoji}</sub>\n`;
|
|
579
614
|
|
|
580
615
|
return md;
|
|
581
616
|
}
|