grepleaks 1.0.2 → 1.0.4
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 +70 -35
- 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.4';
|
|
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();
|
|
494
495
|
|
|
495
|
-
const dateStr = new Date().toLocaleDateString(
|
|
496
|
+
const dateStr = new Date().toLocaleDateString(lang === 'fr' ? 'fr-FR' : 'en-US', {
|
|
497
|
+
year: 'numeric',
|
|
498
|
+
month: 'long',
|
|
499
|
+
day: 'numeric'
|
|
500
|
+
});
|
|
496
501
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
+
}
|
|
508
|
+
|
|
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 += `#### ${i + 1}. ${title}\n\n`;
|
|
568
|
+
|
|
569
|
+
// Location
|
|
570
|
+
if (v.location) {
|
|
571
|
+
md += `- **${lang === 'fr' ? 'Fichier' : 'File'}:** \`${v.location}\`\n`;
|
|
536
572
|
}
|
|
537
573
|
|
|
538
|
-
// CVE
|
|
574
|
+
// CVE
|
|
539
575
|
if (v.cve) {
|
|
540
|
-
md += `- **CVE:** ${v.cve}\n`;
|
|
576
|
+
md += `- **CVE:** [${v.cve}](https://nvd.nist.gov/vuln/detail/${v.cve})\n`;
|
|
541
577
|
}
|
|
542
578
|
|
|
543
|
-
// Package info
|
|
579
|
+
// Package info
|
|
544
580
|
if (v.package_name) {
|
|
545
|
-
md += `- **Package:**
|
|
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
587
|
}
|
|
552
588
|
|
|
553
|
-
|
|
554
|
-
if (v.description) {
|
|
555
|
-
md += `\n${v.description}\n`;
|
|
556
|
-
}
|
|
589
|
+
md += `\n`;
|
|
557
590
|
|
|
558
591
|
// Code snippet
|
|
559
592
|
if (v.code_snippet) {
|
|
560
|
-
md +=
|
|
593
|
+
md += `**${lang === 'fr' ? 'Code concerné' : 'Affected code'}:**\n\`\`\`\n${v.code_snippet}\n\`\`\`\n\n`;
|
|
561
594
|
}
|
|
562
595
|
|
|
563
596
|
// Recommendation
|
|
564
|
-
|
|
565
|
-
|
|
597
|
+
const rec = v.llm_recommendation || v.recommendation;
|
|
598
|
+
if (rec) {
|
|
599
|
+
md += `**${t('reportRecommendation')}:** ${rec}\n\n`;
|
|
566
600
|
}
|
|
567
601
|
|
|
568
|
-
// Reference
|
|
602
|
+
// Reference
|
|
569
603
|
if (v.reference_url) {
|
|
570
|
-
md +=
|
|
604
|
+
md += `[${lang === 'fr' ? 'Plus d\'informations' : 'Learn more'}](${v.reference_url})\n\n`;
|
|
571
605
|
}
|
|
572
606
|
|
|
573
|
-
md +=
|
|
607
|
+
md += `---\n\n`;
|
|
574
608
|
}
|
|
575
609
|
}
|
|
576
610
|
}
|
|
577
611
|
|
|
578
|
-
|
|
612
|
+
// Footer
|
|
613
|
+
md += `*${t('reportGeneratedBy')} [grepleaks](https://grepleaks.com)*\n`;
|
|
579
614
|
|
|
580
615
|
return md;
|
|
581
616
|
}
|