grepleaks 1.0.4 → 1.1.0

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 +95 -215
  2. package/package.json +1 -1
package/bin/grepleaks.js CHANGED
@@ -9,185 +9,86 @@ const readline = require('readline');
9
9
  const { exec } = require('child_process');
10
10
  const archiver = require('archiver');
11
11
 
12
- const VERSION = '1.0.4';
12
+ const VERSION = '1.1.0';
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');
16
16
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
17
17
  const CREDENTIALS_FILE = path.join(CONFIG_DIR, 'credentials.json');
18
18
 
19
- // Translations
20
- const translations = {
21
- en: {
22
- // General
23
- tagline: 'Security scanner for your code',
24
- version: 'grepleaks v',
25
-
26
- // Help
27
- helpUsage: 'USAGE:',
28
- helpCommands: 'COMMANDS:',
29
- helpOptions: 'OPTIONS:',
30
- helpExamples: 'EXAMPLES:',
31
- helpMoreInfo: 'MORE INFO:',
32
- helpLoginDesc: 'Login (email or GitHub)',
33
- helpLogoutDesc: 'Logout',
34
- helpScanDesc: 'Scan a directory',
35
- helpLangDesc: 'Set language (en/fr)',
36
- helpShowHelp: 'Show help',
37
- helpShowVersion: 'Show version',
38
-
39
- // Login
40
- loginTitle: 'Login to grepleaks',
41
- loginChooseMethod: 'Choose login method:',
42
- loginOptionEmail: 'Email / Password',
43
- loginOptionGitHub: 'GitHub',
44
- loginChoice: 'Your choice (1 or 2): ',
45
- loginBrowserTitle: 'Login via browser',
46
- loginGitHubTitle: 'Login with GitHub',
47
- loginOpeningBrowser: 'Opening browser...',
48
- loginTokenPrompt: 'After logging in on the website, copy your token and paste it here.',
49
- loginTokenInput: 'Token: ',
50
- loginTokenRequired: 'Token required',
51
- loginVerifying: 'Verifying token...',
52
- loginInvalidToken: 'Invalid token',
53
- loginEmail: 'Email: ',
54
- loginPassword: 'Password: ',
55
- loginEmailPasswordRequired: 'Email and password required',
56
- loginInProgress: 'Logging in...',
57
- loginFailed: 'Login failed',
58
- loginSuccess: 'Logged in as',
59
-
60
- // Logout
61
- logoutSuccess: 'Logged out',
62
-
63
- // Scan
64
- scanTitle: 'Security scan',
65
- scanMustLogin: 'You must be logged in to scan.',
66
- scanPathNotFound: 'Path not found:',
67
- scanMustBeDir: 'Path must be a directory:',
68
- scanProject: 'Project:',
69
- scanPath: 'Path:',
70
- scanPreparing: 'Preparing files...',
71
- scanArchiveCreated: 'Archive created',
72
- scanUploading: 'Uploading to server...',
73
- scanUploadFailed: 'Upload failed',
74
- scanStarted: 'Scan started',
75
- scanAnalyzing: 'Analyzing...',
76
- scanStatusFailed: 'Failed to check status',
77
- scanFailed: 'Scan failed',
78
- scanComplete: 'Scan complete!',
79
- scanResults: 'Results:',
80
- scanScore: 'Score:',
81
- scanVulnerabilities: 'Vulnerabilities:',
82
- scanReportSaved: 'Report saved:',
83
-
84
- // Report
85
- reportTitle: 'Security Report',
86
- reportDate: 'Date:',
87
- reportScore: 'Score:',
88
- reportVulns: 'Vulnerabilities:',
89
- reportNoVulns: 'No vulnerabilities detected',
90
- reportCongrats: 'Congratulations! Your code has no known vulnerabilities.',
91
- reportVulnsDetected: 'Vulnerabilities detected',
92
- reportFile: 'File:',
93
- reportLine: 'Line:',
94
- reportScanner: 'Scanner:',
95
- reportRecommendation: 'Recommendation:',
96
- reportGeneratedBy: 'Report generated by',
97
-
98
- // Language
99
- langSet: 'Language set to',
100
- langInvalid: 'Invalid language. Use: en, fr',
101
-
102
- // Errors
103
- errorUnknownCmd: 'Unknown command:',
104
- errorUseHelp: "Use 'grepleaks --help' for help."
105
- },
106
- fr: {
107
- // General
108
- tagline: 'Scanner de securite pour votre code',
109
- version: 'grepleaks v',
110
-
111
- // Help
112
- helpUsage: 'USAGE:',
113
- helpCommands: 'COMMANDES:',
114
- helpOptions: 'OPTIONS:',
115
- helpExamples: 'EXEMPLES:',
116
- helpMoreInfo: 'PLUS D\'INFO:',
117
- helpLoginDesc: 'Connexion (email ou GitHub)',
118
- helpLogoutDesc: 'Deconnexion',
119
- helpScanDesc: 'Scanner un dossier',
120
- helpLangDesc: 'Changer la langue (en/fr)',
121
- helpShowHelp: 'Afficher l\'aide',
122
- helpShowVersion: 'Afficher la version',
123
-
124
- // Login
125
- loginTitle: 'Connexion a grepleaks',
126
- loginChooseMethod: 'Choisissez votre methode de connexion:',
127
- loginOptionEmail: 'Email / Mot de passe',
128
- loginOptionGitHub: 'GitHub',
129
- loginChoice: 'Votre choix (1 ou 2): ',
130
- loginBrowserTitle: 'Connexion via navigateur',
131
- loginGitHubTitle: 'Connexion avec GitHub',
132
- loginOpeningBrowser: 'Ouverture du navigateur...',
133
- loginTokenPrompt: 'Apres connexion sur le site, copiez votre token et collez-le ici.',
134
- loginTokenInput: 'Token: ',
135
- loginTokenRequired: 'Token requis',
136
- loginVerifying: 'Verification du token...',
137
- loginInvalidToken: 'Token invalide',
138
- loginEmail: 'Email: ',
139
- loginPassword: 'Mot de passe: ',
140
- loginEmailPasswordRequired: 'Email et mot de passe requis',
141
- loginInProgress: 'Connexion en cours...',
142
- loginFailed: 'Echec de connexion',
143
- loginSuccess: 'Connecte en tant que',
144
-
145
- // Logout
146
- logoutSuccess: 'Deconnecte',
147
-
148
- // Scan
149
- scanTitle: 'Scan de securite',
150
- scanMustLogin: 'Vous devez etre connecte pour scanner.',
151
- scanPathNotFound: 'Chemin introuvable:',
152
- scanMustBeDir: 'Le chemin doit etre un dossier:',
153
- scanProject: 'Projet:',
154
- scanPath: 'Chemin:',
155
- scanPreparing: 'Preparation des fichiers...',
156
- scanArchiveCreated: 'Archive creee',
157
- scanUploading: 'Envoi au serveur...',
158
- scanUploadFailed: 'Echec de l\'upload',
159
- scanStarted: 'Scan demarre',
160
- scanAnalyzing: 'Analyse en cours...',
161
- scanStatusFailed: 'Echec de verification du statut',
162
- scanFailed: 'Le scan a echoue',
163
- scanComplete: 'Scan termine!',
164
- scanResults: 'Resultats:',
165
- scanScore: 'Score:',
166
- scanVulnerabilities: 'Vulnerabilites:',
167
- scanReportSaved: 'Rapport sauvegarde:',
168
-
169
- // Report
170
- reportTitle: 'Rapport de Securite',
171
- reportDate: 'Date:',
172
- reportScore: 'Score:',
173
- reportVulns: 'Vulnerabilites:',
174
- reportNoVulns: 'Aucune vulnerabilite detectee',
175
- reportCongrats: 'Felicitations! Votre code ne presente aucune vulnerabilite connue.',
176
- reportVulnsDetected: 'Vulnerabilites detectees',
177
- reportFile: 'Fichier:',
178
- reportLine: 'Ligne:',
179
- reportScanner: 'Scanner:',
180
- reportRecommendation: 'Recommandation:',
181
- reportGeneratedBy: 'Rapport genere par',
182
-
183
- // Language
184
- langSet: 'Langue definie:',
185
- langInvalid: 'Langue invalide. Utilisez: en, fr',
186
-
187
- // Errors
188
- errorUnknownCmd: 'Commande inconnue:',
189
- errorUseHelp: "Utilisez 'grepleaks --help' pour l'aide."
190
- }
19
+ // Text strings (English only)
20
+ const TEXT = {
21
+ // General
22
+ tagline: 'Security scanner for your code',
23
+ version: 'grepleaks v',
24
+
25
+ // Help
26
+ helpUsage: 'USAGE:',
27
+ helpCommands: 'COMMANDS:',
28
+ helpOptions: 'OPTIONS:',
29
+ helpExamples: 'EXAMPLES:',
30
+ helpMoreInfo: 'MORE INFO:',
31
+ helpLoginDesc: 'Login (email or GitHub)',
32
+ helpLogoutDesc: 'Logout',
33
+ helpScanDesc: 'Scan a directory',
34
+ helpShowHelp: 'Show help',
35
+ helpShowVersion: 'Show version',
36
+
37
+ // Login
38
+ loginTitle: 'Login to grepleaks',
39
+ loginChooseMethod: 'Choose login method:',
40
+ loginOptionEmail: 'Email / Password',
41
+ loginOptionGitHub: 'GitHub',
42
+ loginChoice: 'Your choice (1 or 2): ',
43
+ loginGitHubTitle: 'Login with GitHub',
44
+ loginOpeningBrowser: 'Opening browser...',
45
+ loginTokenPrompt: 'After logging in on the website, copy your token and paste it here.',
46
+ loginTokenInput: 'Token: ',
47
+ loginTokenRequired: 'Token required',
48
+ loginVerifying: 'Verifying token...',
49
+ loginInvalidToken: 'Invalid token',
50
+ loginEmail: 'Email: ',
51
+ loginPassword: 'Password: ',
52
+ loginEmailPasswordRequired: 'Email and password required',
53
+ loginInProgress: 'Logging in...',
54
+ loginFailed: 'Login failed',
55
+ loginSuccess: 'Logged in as',
56
+
57
+ // Logout
58
+ logoutSuccess: 'Logged out',
59
+
60
+ // Scan
61
+ scanTitle: 'Security scan',
62
+ scanMustLogin: 'You must be logged in to scan.',
63
+ scanPathNotFound: 'Path not found:',
64
+ scanMustBeDir: 'Path must be a directory:',
65
+ scanProject: 'Project:',
66
+ scanPath: 'Path:',
67
+ scanPreparing: 'Preparing files...',
68
+ scanArchiveCreated: 'Archive created',
69
+ scanUploading: 'Uploading to server...',
70
+ scanUploadFailed: 'Upload failed',
71
+ scanStarted: 'Scan started',
72
+ scanAnalyzing: 'Analyzing...',
73
+ scanStatusFailed: 'Failed to check status',
74
+ scanFailed: 'Scan failed',
75
+ scanComplete: 'Scan complete!',
76
+ scanResults: 'Results:',
77
+ scanScore: 'Score:',
78
+ scanVulnerabilities: 'Vulnerabilities:',
79
+ scanReportSaved: 'Report saved:',
80
+
81
+ // Report
82
+ reportTitle: 'Security Report',
83
+ reportNoVulns: 'No vulnerabilities detected',
84
+ reportCongrats: 'Congratulations! Your code has no known vulnerabilities.',
85
+ reportVulnsDetected: 'Vulnerabilities detected',
86
+ reportRecommendation: 'Recommendation',
87
+ reportGeneratedBy: 'Report generated by',
88
+
89
+ // Errors
90
+ errorUnknownCmd: 'Unknown command:',
91
+ errorUseHelp: "Use 'grepleaks --help' for help."
191
92
  };
192
93
 
193
94
  // Files/folders to skip when zipping
@@ -215,16 +116,9 @@ const c = {
215
116
  gray: '\x1b[90m'
216
117
  };
217
118
 
218
- // Get current language
219
- function getLang() {
220
- const config = loadConfig();
221
- return config.lang || 'en';
222
- }
223
-
224
- // Get translation
119
+ // Get text string
225
120
  function t(key) {
226
- const lang = getLang();
227
- return translations[lang]?.[key] || translations['en'][key] || key;
121
+ return TEXT[key] || key;
228
122
  }
229
123
 
230
124
  // Helpers
@@ -491,9 +385,8 @@ function generateMarkdownReport(result) {
491
385
  const score = result.security_score || 0;
492
386
  const grade = result.grade_level || 'N/A';
493
387
  const projectName = result.project_name || 'Unknown Project';
494
- const lang = getLang();
495
388
 
496
- const dateStr = new Date().toLocaleDateString(lang === 'fr' ? 'fr-FR' : 'en-US', {
389
+ const dateStr = new Date().toLocaleDateString('en-US', {
497
390
  year: 'numeric',
498
391
  month: 'long',
499
392
  day: 'numeric'
@@ -512,11 +405,11 @@ function generateMarkdownReport(result) {
512
405
 
513
406
  // Score card
514
407
  const scoreEmoji = score >= 90 ? '🛡️' : score >= 75 ? '✅' : score >= 50 ? '⚠️' : '🚨';
515
- md += `## ${scoreEmoji} ${lang === 'fr' ? 'Score de Sécurité' : 'Security Score'}: ${score}/100 (${grade})\n\n`;
408
+ md += `## ${scoreEmoji} Security Score: ${score}/100 (${grade})\n\n`;
516
409
 
517
410
  // Summary table
518
411
  if (vulns.length > 0) {
519
- md += `| ${lang === 'fr' ? 'Sévérité' : 'Severity'} | ${lang === 'fr' ? 'Nombre' : 'Count'} |\n`;
412
+ md += `| Severity | Count |\n`;
520
413
  md += `|----------|-------|\n`;
521
414
  if (counts.critical > 0) md += `| 🔴 Critical | ${counts.critical} |\n`;
522
415
  if (counts.high > 0) md += `| 🟠 High | ${counts.high} |\n`;
@@ -546,9 +439,7 @@ function generateMarkdownReport(result) {
546
439
  severity === 'HIGH' ? '🟠' :
547
440
  severity === 'MEDIUM' ? '🟡' : '🟢';
548
441
 
549
- const severityLabel = lang === 'fr'
550
- ? { CRITICAL: 'Critique', HIGH: 'Élevée', MEDIUM: 'Moyenne', LOW: 'Faible' }[severity]
551
- : severity.charAt(0) + severity.slice(1).toLowerCase();
442
+ const severityLabel = severity.charAt(0) + severity.slice(1).toLowerCase();
552
443
 
553
444
  md += `### ${emoji} ${severityLabel}\n\n`;
554
445
 
@@ -568,7 +459,7 @@ function generateMarkdownReport(result) {
568
459
 
569
460
  // Location
570
461
  if (v.location) {
571
- md += `- **${lang === 'fr' ? 'Fichier' : 'File'}:** \`${v.location}\`\n`;
462
+ md += `- **File:** \`${v.location}\`\n`;
572
463
  }
573
464
 
574
465
  // CVE
@@ -582,7 +473,7 @@ function generateMarkdownReport(result) {
582
473
  if (v.current_version) md += ` v${v.current_version}`;
583
474
  md += `\n`;
584
475
  if (v.fixed_version) {
585
- md += `- **${lang === 'fr' ? 'Correction' : 'Fix'}:** ${lang === 'fr' ? 'Mettre à jour vers' : 'Upgrade to'} v${v.fixed_version}\n`;
476
+ md += `- **Fix:** Upgrade to v${v.fixed_version}\n`;
586
477
  }
587
478
  }
588
479
 
@@ -590,7 +481,7 @@ function generateMarkdownReport(result) {
590
481
 
591
482
  // Code snippet
592
483
  if (v.code_snippet) {
593
- md += `**${lang === 'fr' ? 'Code concerné' : 'Affected code'}:**\n\`\`\`\n${v.code_snippet}\n\`\`\`\n\n`;
484
+ md += `**Affected code:**\n\`\`\`\n${v.code_snippet}\n\`\`\`\n\n`;
594
485
  }
595
486
 
596
487
  // Recommendation
@@ -601,7 +492,7 @@ function generateMarkdownReport(result) {
601
492
 
602
493
  // Reference
603
494
  if (v.reference_url) {
604
- md += `[${lang === 'fr' ? 'Plus d\'informations' : 'Learn more'}](${v.reference_url})\n\n`;
495
+ md += `[Learn more](${v.reference_url})\n\n`;
605
496
  }
606
497
 
607
498
  md += `---\n\n`;
@@ -697,21 +588,6 @@ async function cmdLogout() {
697
588
  success(t('logoutSuccess'));
698
589
  }
699
590
 
700
- async function cmdLang(args) {
701
- const lang = args[1];
702
-
703
- if (!lang) {
704
- log(`Current language: ${getLang()}`);
705
- return;
706
- }
707
-
708
- if (!['en', 'fr'].includes(lang)) {
709
- error(t('langInvalid'));
710
- }
711
-
712
- saveConfig({ lang });
713
- success(`${t('langSet')} ${lang}`);
714
- }
715
591
 
716
592
  async function cmdScan(args) {
717
593
  const creds = loadCredentials();
@@ -818,11 +694,20 @@ async function cmdScan(args) {
818
694
  if (low) log(` ${c.gray}● Low: ${low}${c.reset}`);
819
695
  }
820
696
 
821
- const report = generateMarkdownReport({ ...scanResult, project_name: projectName });
697
+ // Use AI-generated report from backend if available, otherwise generate locally
698
+ let report;
699
+ if (scanResult.report_markdown && scanResult.report_markdown.trim().length > 0) {
700
+ report = scanResult.report_markdown;
701
+ log(`\n${c.cyan}ℹ${c.reset} Using AI-generated report from server`);
702
+ } else {
703
+ report = generateMarkdownReport({ ...scanResult, project_name: projectName });
704
+ log(`\n${c.cyan}ℹ${c.reset} Generated report locally (AI report not available)`);
705
+ }
706
+
822
707
  const reportPath = path.join(absolutePath, 'grepleaks-report.md');
823
708
  fs.writeFileSync(reportPath, report);
824
709
 
825
- log(`\n${c.green}✓${c.reset} ${t('scanReportSaved')} ${c.cyan}${reportPath}${c.reset}\n`);
710
+ log(`${c.green}✓${c.reset} ${t('scanReportSaved')} ${c.cyan}${reportPath}${c.reset}\n`);
826
711
 
827
712
  } finally {
828
713
  if (fs.existsSync(tempZip)) {
@@ -842,7 +727,6 @@ ${c.bold}${t('helpCommands')}${c.reset}
842
727
  login ${t('helpLoginDesc')}
843
728
  logout ${t('helpLogoutDesc')}
844
729
  scan <path> ${t('helpScanDesc')}
845
- lang <en|fr> ${t('helpLangDesc')}
846
730
 
847
731
  ${c.bold}${t('helpOptions')}${c.reset}
848
732
  -h, --help ${t('helpShowHelp')}
@@ -852,7 +736,6 @@ ${c.bold}${t('helpExamples')}${c.reset}
852
736
  grepleaks login
853
737
  grepleaks scan .
854
738
  grepleaks scan ./my-project
855
- grepleaks lang fr
856
739
 
857
740
  ${c.bold}${t('helpMoreInfo')}${c.reset}
858
741
  ${c.cyan}https://grepleaks.com${c.reset}
@@ -883,9 +766,6 @@ async function main() {
883
766
  case 'logout':
884
767
  await cmdLogout();
885
768
  break;
886
- case 'lang':
887
- await cmdLang(args);
888
- break;
889
769
  case 'scan':
890
770
  await cmdScan(args);
891
771
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepleaks",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Security scanner for your code - detect vulnerabilities, secrets, and misconfigurations",
5
5
  "main": "bin/grepleaks.js",
6
6
  "bin": {