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.
Files changed (2) hide show
  1. package/bin/grepleaks.js +70 -35
  2. 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.2';
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(getLang() === 'fr' ? 'fr-FR' : 'en-US');
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
- let md = `# ${t('reportTitle')} - ${projectName}\n\n`;
498
- md += `**${t('reportDate')}** ${dateStr}\n`;
499
- md += `**${t('reportScore')}** ${score}/100 (${grade})\n`;
500
- md += `**${t('reportVulns')}** ${vulns.length}\n\n`;
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
- md += `### ${emoji} ${severity} (${items.length})\n\n`;
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
- for (const v of items) {
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
- // Location (file/line)
529
- if (v.location) {
530
- md += `- **${t('reportFile')}** \`${v.location}\`\n`;
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
- // Scanner source
534
- if (v.source) {
535
- md += `- **${t('reportScanner')}** ${v.source}\n`;
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 if available
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 (for Trivy findings)
579
+ // Package info
544
580
  if (v.package_name) {
545
- md += `- **Package:** ${v.package_name}`;
546
- if (v.current_version) md += ` (${v.current_version})`;
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 += `- **Fix:** Upgrade to ${v.fixed_version}\n`;
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
- // Description
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 += `\n\`\`\`\n${v.code_snippet}\n\`\`\`\n`;
593
+ md += `**${lang === 'fr' ? 'Code concerné' : 'Affected code'}:**\n\`\`\`\n${v.code_snippet}\n\`\`\`\n\n`;
561
594
  }
562
595
 
563
596
  // Recommendation
564
- if (v.recommendation || v.llm_recommendation) {
565
- md += `\n**${t('reportRecommendation')}** ${v.llm_recommendation || v.recommendation}\n`;
597
+ const rec = v.llm_recommendation || v.recommendation;
598
+ if (rec) {
599
+ md += `**${t('reportRecommendation')}:** ${rec}\n\n`;
566
600
  }
567
601
 
568
- // Reference URL
602
+ // Reference
569
603
  if (v.reference_url) {
570
- md += `\n**Reference:** ${v.reference_url}\n`;
604
+ md += `[${lang === 'fr' ? 'Plus d\'informations' : 'Learn more'}](${v.reference_url})\n\n`;
571
605
  }
572
606
 
573
- md += `\n---\n\n`;
607
+ md += `---\n\n`;
574
608
  }
575
609
  }
576
610
  }
577
611
 
578
- md += `\n---\n*${t('reportGeneratedBy')} [grepleaks](https://grepleaks.com)*\n`;
612
+ // Footer
613
+ md += `*${t('reportGeneratedBy')} [grepleaks](https://grepleaks.com)*\n`;
579
614
 
580
615
  return md;
581
616
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepleaks",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Security scanner for your code - detect vulnerabilities, secrets, and misconfigurations",
5
5
  "main": "bin/grepleaks.js",
6
6
  "bin": {