@refentse/gatekeeper-cli 1.0.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.
package/README.md ADDED
Binary file
package/index.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { program } from 'commander';
4
+ import inquirer from 'inquirer';
5
+ import { spawn } from 'child_process';
6
+ import chalk from 'chalk';
7
+ import { checkPackage } from './src/scanner.js';
8
+
9
+ program
10
+ .version('1.0.0')
11
+ .description('npm-gatekeeper: Zero-Trust Package Management');
12
+
13
+ program
14
+ .command('install <package>')
15
+ .description('Intercepts and safely installs an npm package')
16
+ .action(async (packageName) => {
17
+
18
+ // 1. Run Gatekeeper Heuristics
19
+ const scanResult = await checkPackage(packageName);
20
+
21
+ // 2. The Interception Logic
22
+ if (scanResult.hardBlock) {
23
+ console.log(chalk.bgRed.white.bold('\n 🚫 HARD BLOCK ACTIVATED. Installation aborted to protect your environment. '));
24
+ process.exit(1);
25
+ }
26
+
27
+ if (!scanResult.isSafe) {
28
+ const answers = await inquirer.prompt([
29
+ {
30
+ type: 'confirm',
31
+ name: 'override',
32
+ message: chalk.red.bold('Threats detected. Do you want to OVERRIDE and install anyway?'),
33
+ default: false
34
+ }
35
+ ]);
36
+
37
+ if (!answers.override) {
38
+ console.log(chalk.red.bold('\n🚫 Installation blocked by Gatekeeper. Your machine is safe.'));
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ // 3. Pass-Through Execution
44
+ console.log(chalk.cyan(`\nšŸš€ Handing off to native npm to install ${packageName}...\n`));
45
+
46
+ // THE FIX: Explicitly call cmd.exe on Windows to avoid the shell: true warning
47
+ const isWindows = process.platform === 'win32';
48
+ const command = isWindows ? 'cmd.exe' : 'npm';
49
+ const args = isWindows ? ['/c', 'npm', 'install', packageName] : ['install', packageName];
50
+
51
+ const child = spawn(command, args, {
52
+ stdio: 'inherit',
53
+ shell: false // Kept false for maximum security
54
+ });
55
+
56
+ child.on('close', (code) => {
57
+ if (code === 0) {
58
+ console.log(chalk.green(`\nšŸ”’ gatekeeper: ${packageName} installed successfully.`));
59
+ } else {
60
+ console.log(chalk.red(`\nāŒ native npm exited with error code ${code}`));
61
+ }
62
+ });
63
+ });
64
+
65
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@refentse/gatekeeper-cli",
3
+ "version": "1.0.0",
4
+ "description": "Zero-Trust Package Management",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "gatekeeper": "index.js"
9
+ },
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "security",
15
+ "zero-trust",
16
+ "npm",
17
+ "malware",
18
+ "osv",
19
+ "devsecops"
20
+ ],
21
+ "author": "Quincy Refentse Moeng",
22
+ "license": "ISC",
23
+ "dependencies": {
24
+ "chalk": "^5.6.2",
25
+ "commander": "^14.0.3",
26
+ "inquirer": "^13.3.2"
27
+ }
28
+ }
package/src/scanner.js ADDED
@@ -0,0 +1,71 @@
1
+ import chalk from 'chalk';
2
+
3
+ export async function checkPackage(packageName) {
4
+ console.log(chalk.blue(`\nšŸ” Gatekeeper is inspecting metadata for: ${packageName}...`));
5
+
6
+ let isSafe = true;
7
+ let hardBlock = false;
8
+
9
+ try {
10
+ const response = await fetch(`https://registry.npmjs.org/${packageName}`);
11
+
12
+ if (!response.ok) {
13
+ throw new Error(`Registry returned status ${response.status}`);
14
+ }
15
+
16
+ const fullMetadata = await response.json();
17
+ const latestVersion = fullMetadata['dist-tags'].latest;
18
+ const latestData = fullMetadata.versions[latestVersion];
19
+ const scripts = latestData.scripts || {};
20
+
21
+ // šŸ›”ļø CHECK 1: Google OSV Vulnerability Database (HARD BLOCK)
22
+ console.log(chalk.gray(` Checking Google OSV database for known vulnerabilities...`));
23
+ const osvResponse = await fetch('https://api.osv.dev/v1/query', {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' },
26
+ body: JSON.stringify({
27
+ version: latestVersion,
28
+ package: { name: packageName, ecosystem: "npm" }
29
+ })
30
+ });
31
+
32
+ if (osvResponse.ok) {
33
+ const osvData = await osvResponse.json();
34
+ if (osvData.vulns && osvData.vulns.length > 0) {
35
+ console.log(chalk.red.bold(`\n🚨 CRITICAL: KNOWN MALWARE DETECTED IN OSV DATABASE 🚨`));
36
+ console.log(chalk.red(` Package: ${packageName}@${latestVersion}`));
37
+ console.log(chalk.red(` Vulnerabilities found: ${osvData.vulns.length}`));
38
+ console.log(chalk.red(` This payload will be hard-blocked. No override permitted.`));
39
+ return { isSafe: false, hardBlock: true };
40
+ }
41
+ }
42
+
43
+ // 🚨 CHECK 2: Malicious Lifecycle Scripts
44
+ if (scripts.postinstall || scripts.preinstall || scripts.install) {
45
+ console.log(chalk.red.bold(`\nāš ļø WARNING: ${packageName} contains hidden installation scripts.`));
46
+ console.log(chalk.yellow(` Script found: ${scripts.postinstall || scripts.preinstall || scripts.install}`));
47
+ isSafe = false;
48
+ }
49
+
50
+ // šŸ•’ CHECK 3: Package Age
51
+ const publishTimeString = fullMetadata.time[latestVersion];
52
+ const publishTime = new Date(publishTimeString || Date.now());
53
+ const ageInHours = (new Date() - publishTime) / (1000 * 60 * 60);
54
+
55
+ if (ageInHours < 48) {
56
+ console.log(chalk.yellow(`\nāš ļø NEW PACKAGE ALERT: Version ${latestVersion} was published only ${Math.round(ageInHours)} hours ago.`));
57
+ isSafe = false;
58
+ }
59
+
60
+ if (isSafe) {
61
+ console.log(chalk.green(`āœ… ${packageName}@${latestVersion} passed heuristics scan. No obvious threats detected.`));
62
+ }
63
+
64
+ return { isSafe, hardBlock };
65
+
66
+ } catch (error) {
67
+ console.error(chalk.red(`\nāŒ Could not fetch package data for '${packageName}'.`));
68
+ console.error(chalk.gray(` Error details: ${error.message}`));
69
+ return { isSafe: false, hardBlock: false };
70
+ }
71
+ }