cybersentinel-cli 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/index.js +197 -2
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -72,7 +72,21 @@ $ s*" .u@*"" '""\\dP"
72
72
  """"* RL d>
73
73
  "$u. .$
74
74
  ^"*bo@" tony
75
- `) + "\n" + chalk.green.bold(' CYBERSENTINEL - Audit Platform CLI\n');
75
+ `) + "\n" +
76
+ chalk.green.bold('================================================================================\n') +
77
+ chalk.green.bold(' CYBERSENTINEL - Audit Platform CLI\n') +
78
+ chalk.green.bold('================================================================================\n') +
79
+ chalk.green('INTRODUCTION & PURPOSE:\n') +
80
+ chalk.white(' CyberSentinel CLI is a secure, interactive terminal-based auditing gateway\n') +
81
+ chalk.white(' designed for white-hat penetration testers and compliance officers. It executes\n') +
82
+ chalk.white(' automated vulnerability assessments, facilitates manual control checkpoints, and\n') +
83
+ chalk.white(' synchronizes verified ratings and uploads directly to the management database.\n\n') +
84
+ chalk.green('CREATOR & LEAD DEVELOPER:\n') +
85
+ chalk.white(' Engr. Brian Perez\n\n') +
86
+ chalk.green('PROPRIETARY LICENSE & COPYRIGHT:\n') +
87
+ chalk.white(' This software package and its distribution binaries are exclusively owned by\n') +
88
+ chalk.white(' the Inspire Alliance Fund Group Incorporated. All rights reserved.\n') +
89
+ chalk.green.bold('================================================================================\n');
76
90
 
77
91
  const SNAKE_SPINNER = {
78
92
  interval: 100,
@@ -122,6 +136,36 @@ function getMtlsClient(config) {
122
136
  });
123
137
  }
124
138
 
139
+ // Wait for user to decide to quit by pressing Ctrl + C or /exit command
140
+ async function waitToExit() {
141
+ console.log(chalk.gray('\n=================================================='));
142
+ console.log(chalk.green('Task execution complete. Session remains active.'));
143
+ console.log(chalk.green('Type "/exit" or press Ctrl+C to close the connection and exit.'));
144
+ console.log(chalk.gray('==================================================\n'));
145
+
146
+ const readline = require('readline');
147
+ const rl = readline.createInterface({
148
+ input: process.stdin,
149
+ output: process.stdout
150
+ });
151
+
152
+ return new Promise((resolve) => {
153
+ const ask = () => {
154
+ rl.question(chalk.green('cybersentinel> '), (answer) => {
155
+ if (answer.trim() === '/exit') {
156
+ console.log(chalk.yellow('Closing session...'));
157
+ rl.close();
158
+ process.exit(0);
159
+ } else {
160
+ console.log(chalk.gray(`Unknown command "${answer.trim()}". Type "/exit" to quit.`));
161
+ ask();
162
+ }
163
+ });
164
+ };
165
+ ask();
166
+ });
167
+ }
168
+
125
169
  // Print startup banner
126
170
  console.log(VIPER_BANNER);
127
171
 
@@ -253,6 +297,7 @@ program
253
297
  console.log(chalk.green(`Files saved to: ${CONFIG_DIR}`));
254
298
  console.log(chalk.green(`PKCS12 Container: client.p12 (encrypted)\n`));
255
299
 
300
+ await waitToExit();
256
301
  } catch (error) {
257
302
  spinner.fail(chalk.red('Registration failed!'));
258
303
  if (error.response) {
@@ -270,6 +315,7 @@ program
270
315
  } else {
271
316
  console.error(chalk.red(`Error: ${error.message}`));
272
317
  }
318
+ await waitToExit();
273
319
  }
274
320
  });
275
321
 
@@ -277,7 +323,7 @@ program
277
323
  program
278
324
  .command('init')
279
325
  .description('Verify credential certificate files status')
280
- .action(() => {
326
+ .action(async () => {
281
327
  if (hasCertificates()) {
282
328
  try {
283
329
  const config = loadConfig();
@@ -292,6 +338,7 @@ program
292
338
  console.log(chalk.yellow('⚠ No active client certificate found. Please run:'));
293
339
  console.log(chalk.cyan(' cybersentinel register'));
294
340
  }
341
+ await waitToExit();
295
342
  });
296
343
 
297
344
  // Command: audit
@@ -303,6 +350,7 @@ program
303
350
  .action(async (options) => {
304
351
  if (!hasCertificates()) {
305
352
  console.error(chalk.red('Error: Local certificate files not found. Run "cybersentinel register" first.'));
353
+ await waitToExit();
306
354
  process.exit(1);
307
355
  }
308
356
 
@@ -311,6 +359,7 @@ program
311
359
  config = loadConfig();
312
360
  } catch (err) {
313
361
  console.error(chalk.red(err.message));
362
+ await waitToExit();
314
363
  process.exit(1);
315
364
  }
316
365
 
@@ -335,6 +384,7 @@ program
335
384
  } else {
336
385
  console.error(chalk.red(`Connection error: ${err.message}`));
337
386
  }
387
+ await waitToExit();
338
388
  process.exit(1);
339
389
  }
340
390
 
@@ -483,6 +533,29 @@ program
483
533
  console.log(chalk.gray(`Current: Rating: ${currentVal.rating} | Notes: ${currentVal.notes}`));
484
534
  }
485
535
 
536
+ const actionPrompt = await inquirer.prompt([
537
+ {
538
+ type: 'list',
539
+ name: 'action',
540
+ message: 'Choose action for this checkpoint:',
541
+ choices: [
542
+ { name: 'Audit / Rate this item', value: 'audit' },
543
+ { name: 'Skip this item', value: 'skip' },
544
+ { name: chalk.yellow('Exit & Save Session'), value: 'exit' }
545
+ ]
546
+ }
547
+ ]);
548
+
549
+ if (actionPrompt.action === 'exit') {
550
+ console.log(chalk.yellow('\n✔ Session progress saved. Exiting audit session. Goodbye!'));
551
+ process.exit(0);
552
+ }
553
+
554
+ if (actionPrompt.action === 'skip') {
555
+ console.log(chalk.gray(`Skipping item ${item.id}.`));
556
+ continue;
557
+ }
558
+
486
559
  const itemAnswers = await inquirer.prompt([
487
560
  {
488
561
  type: 'list',
@@ -564,6 +637,128 @@ program
564
637
  }
565
638
 
566
639
  console.log(chalk.green.bold(`\n✔ Completed Category ${selectedCategory.id} Audit!\n`));
640
+ await waitToExit();
641
+ });
642
+
643
+ function startProxyServer(port, targetFilter) {
644
+ const http = require('http');
645
+ const net = require('net');
646
+ const url = require('url');
647
+
648
+ const server = http.createServer((req, res) => {
649
+ try {
650
+ const parsedUrl = url.parse(req.url);
651
+ const host = req.headers.host || '';
652
+
653
+ const shouldLog = !targetFilter || host.includes(targetFilter);
654
+ if (shouldLog) {
655
+ console.log(chalk.green(`[HTTP Request] ${req.method} ${req.url}`));
656
+ }
657
+
658
+ const options = {
659
+ hostname: parsedUrl.hostname || host.split(':')[0],
660
+ port: parsedUrl.port || 80,
661
+ path: parsedUrl.path,
662
+ method: req.method,
663
+ headers: req.headers
664
+ };
665
+
666
+ const proxyReq = http.request(options, (proxyRes) => {
667
+ if (shouldLog) {
668
+ console.log(chalk.cyan(`[HTTP Response] ${req.method} ${req.url} -> Status: ${proxyRes.statusCode}`));
669
+ }
670
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
671
+ proxyRes.pipe(res);
672
+ });
673
+
674
+ proxyReq.on('error', (err) => {
675
+ if (shouldLog) {
676
+ console.error(chalk.red(`[HTTP Error] ${req.method} ${req.url} -> Error: ${err.message}`));
677
+ }
678
+ res.writeHead(502);
679
+ res.end(`Proxy Gateway Error: ${err.message}`);
680
+ });
681
+
682
+ req.pipe(proxyReq);
683
+ } catch (err) {
684
+ console.error(chalk.red(`Proxy Request Handler Error: ${err.message}`));
685
+ }
686
+ });
687
+
688
+ server.on('connect', (req, clientSocket, head) => {
689
+ try {
690
+ const parts = req.url.split(':');
691
+ const targetHost = parts[0];
692
+ const targetPort = parseInt(parts[1] || '443', 10);
693
+
694
+ const shouldLog = !targetFilter || targetHost.includes(targetFilter);
695
+ if (shouldLog) {
696
+ console.log(chalk.yellow(`[HTTPS CONNECT Tunnel] ${targetHost}:${targetPort}`));
697
+ }
698
+
699
+ const serverSocket = net.connect(targetPort, targetHost, () => {
700
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
701
+ serverSocket.write(head);
702
+ serverSocket.pipe(clientSocket);
703
+ clientSocket.pipe(serverSocket);
704
+ });
705
+
706
+ serverSocket.on('error', (err) => {
707
+ if (shouldLog) {
708
+ console.error(chalk.red(`[HTTPS Tunnel Error] Tunnel to ${targetHost}:${targetPort} failed: ${err.message}`));
709
+ }
710
+ clientSocket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
711
+ });
712
+
713
+ clientSocket.on('error', () => {
714
+ serverSocket.end();
715
+ });
716
+ } catch (err) {
717
+ console.error(chalk.red(`Proxy CONNECT Handler Error: ${err.message}`));
718
+ }
719
+ });
720
+
721
+ server.listen(port, () => {
722
+ console.log(chalk.green.bold(`\n⚡ CyberSentinel Interception Proxy Active!`));
723
+ console.log(chalk.green(`Listening on local port: ${port}`));
724
+ if (targetFilter) {
725
+ console.log(chalk.green(`Filtering target host: ${targetFilter}`));
726
+ }
727
+ console.log(chalk.gray(`Configure your browser (e.g. Chrome) to use HTTP/HTTPS proxy 127.0.0.1:${port}`));
728
+ console.log(chalk.gray(`Type "/exit" or press Ctrl+C to stop the proxy server.\n`));
729
+ });
730
+
731
+ const readline = require('readline');
732
+ const rl = readline.createInterface({
733
+ input: process.stdin,
734
+ output: process.stdout
735
+ });
736
+
737
+ const ask = () => {
738
+ rl.question('', (answer) => {
739
+ if (answer.trim() === '/exit') {
740
+ console.log(chalk.yellow('Stopping proxy server and closing session...'));
741
+ server.close();
742
+ rl.close();
743
+ process.exit(0);
744
+ } else {
745
+ ask();
746
+ }
747
+ });
748
+ };
749
+ ask();
750
+ }
751
+
752
+ // Command: proxy
753
+ program
754
+ .command('proxy')
755
+ .description('Start a local interception proxy server (like Burp Suite CLI)')
756
+ .option('-p, --port <port>', 'Port to listen on', '8088')
757
+ .option('-t, --target <host>', 'Filter logs by target host domain')
758
+ .action((options) => {
759
+ const port = parseInt(options.port, 10);
760
+ startProxyServer(port, options.target);
567
761
  });
568
762
 
569
763
  program.parse(process.argv);
764
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cybersentinel-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "CyberSentinel Cybersecurity Auditor CLI Tool",
5
5
  "main": "bin/index.js",
6
6
  "type": "commonjs",