install-guard 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
@@ -0,0 +1,158 @@
1
+ # 🚨 Should You Trust That npm Package Before Installing?
2
+
3
+ **dep-shield** analyzes npm packages and tells you if they are safe to install — before you install them.
4
+
5
+ ---
6
+
7
+ <details>
8
+ <summary>Example</summary>
9
+
10
+ ```bash
11
+ npx dep-shield install some-random-lib
12
+ ```
13
+
14
+ ```
15
+ 📦 Analyzing some-random-lib...
16
+
17
+ Downloads (weekly): 120
18
+ Risk Score: 8/10 🚨 High Risk
19
+
20
+ ⚠ Very low downloads
21
+ ⚠ Uses install scripts
22
+ ⚠ Recently published
23
+
24
+ ❓ Do you still want to install this package? (y/n)
25
+ ```
26
+
27
+ </details>
28
+
29
+ ---
30
+
31
+ ## 😬 The Problem
32
+
33
+ Installing npm packages blindly is risky.
34
+
35
+ - Malicious packages are published daily
36
+ - Popular packages get compromised
37
+ - `npm audit` only checks known vulnerabilities — not trust
38
+
39
+ You shouldn't have to guess if a package is safe.
40
+
41
+ ---
42
+
43
+ ## 🛡️ The Solution
44
+
45
+ dep-shield gives you a **risk score before you install anything**.
46
+
47
+ ---
48
+
49
+ ## ⚡ Quick Start
50
+
51
+ Check a package:
52
+
53
+ ```bash
54
+ npx dep-shield axios
55
+ ```
56
+
57
+ Safely install a package:
58
+
59
+ ```bash
60
+ npx dep-shield install axios
61
+ ```
62
+
63
+ Scan your project:
64
+
65
+ ```bash
66
+ npx dep-shield scan
67
+ ```
68
+
69
+ ---
70
+
71
+ ## 🧠 How Risk Score Works
72
+
73
+ dep-shield analyzes:
74
+
75
+ - 📉 Weekly downloads (popularity)
76
+ - 🕒 Last update time
77
+ - ⚠ Install/postinstall scripts
78
+ - 📦 Version activity
79
+
80
+ Each factor contributes to a **risk score (0–10)**.
81
+
82
+ Lower score = safer package.
83
+
84
+ ---
85
+
86
+ ## 📊 Example Results
87
+
88
+ ### ✅ Safe package
89
+
90
+ ```
91
+ axios
92
+ Downloads: 20,000,000+
93
+ Risk: 1/10
94
+ ```
95
+
96
+ ---
97
+
98
+ ### 🚨 Risky package
99
+
100
+ ```
101
+ some-lib
102
+ Downloads: 200
103
+ Risk: 8/10
104
+
105
+ ⚠ Low downloads
106
+ ⚠ Uses install scripts
107
+ ```
108
+
109
+ ---
110
+
111
+ ## ✨ Features
112
+
113
+ - 🔍 Analyze any npm package instantly
114
+ - ⚠ Risk scoring (0–10)
115
+ - 🛑 Block risky installs
116
+ - 📦 Project-wide dependency scan
117
+ - ⚡ Zero setup (works with npx)
118
+
119
+ ---
120
+
121
+ ## 🤔 Why not npm audit?
122
+
123
+ | Feature | npm audit | dep-shield |
124
+ |-----------------------|-----------|------------|
125
+ | Known vulnerabilities | ✅ | ✅ |
126
+ | Trust analysis | ❌ | ✅ |
127
+ | Pre-install check | ❌ | ✅ |
128
+ | Install blocking | ❌ | ✅ |
129
+
130
+ ---
131
+
132
+ ## 📦 Install globally
133
+
134
+ ```bash
135
+ npm install -g dep-shield
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 🔮 Roadmap
141
+
142
+ - 🔍 GitHub activity analysis
143
+ - 🧠 Typosquatting detection
144
+ - 📊 Dependency tree visualization
145
+ - 🔌 CI/CD integration
146
+
147
+ ---
148
+
149
+ ## 🤝 Contributing
150
+
151
+ PRs welcome! Let's make npm safer together.
152
+
153
+ ---
154
+
155
+ ## ⭐ Support
156
+
157
+ If you find this useful, consider giving it a star ⭐
158
+ It helps others discover the project!
package/bin/cli.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import { analyzePackage } from "../src/index.js";
5
+ import { scanProject } from "../src/scan.js";
6
+
7
+ const program = new Command();
8
+
9
+ program
10
+ .name("dep-shield")
11
+ .description("Check npm package risk before installing");
12
+
13
+ program
14
+ .argument("[package]", "package name to analyze")
15
+ .action(async (pkg) => {
16
+ if (!pkg) {
17
+ console.log("Please provide a package name");
18
+ return;
19
+ }
20
+ await analyzePackage(pkg);
21
+ });
22
+
23
+ program
24
+ .command("scan")
25
+ .description("Scan current project dependencies")
26
+ .action(scanProject);
27
+
28
+ program
29
+ .command("install <pkg>")
30
+ .description("Analyze and install package safely")
31
+ .action(async (pkg) => {
32
+ const { analyzeAndPrompt } = await import("../src/install.js");
33
+ await analyzeAndPrompt(pkg);
34
+ });
35
+ program.parse();
Binary file
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "install-guard",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "bin": {
6
+ "npm-guard": "./bin/cli.js"
7
+ },
8
+
9
+ "type": "module",
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "author": "Sarthak Kumar Sahoo",
14
+ "license": "MIT",
15
+ "description": "Check if an npm package is safe before installing",
16
+ "dependencies": {
17
+ "chalk": "^5.6.2",
18
+ "commander": "^14.0.3",
19
+ "ora": "^9.3.0"
20
+ },
21
+ "keywords": ["npm", "security", "cli", "dependency", "audit"]
22
+ }
package/src/analyze.js ADDED
@@ -0,0 +1,34 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import { getPackageData } from "./npm.js";
4
+ import { calculateRisk } from "./score.js";
5
+
6
+ export async function analyze(pkgName) {
7
+ const spinner = ora(`Analyzing ${pkgName}...`).start();
8
+
9
+ try {
10
+ const data = await getPackageData(pkgName);
11
+ const { score, warnings } = calculateRisk(data);
12
+
13
+ spinner.stop();
14
+
15
+ console.log(chalk.bold(`\n📦 ${data.name}`));
16
+ console.log(`Version: ${data.version}`);
17
+ console.log(`Downloads (weekly): ${data.downloads.toLocaleString()}`);
18
+ console.log(`Risk Score: ${score}/10`);
19
+
20
+ if (score <= 3) {
21
+ console.log(chalk.green("✅ Low risk"));
22
+ } else if (score <= 6) {
23
+ console.log(chalk.yellow("⚠ Medium risk"));
24
+ } else {
25
+ console.log(chalk.red("🚨 High risk"));
26
+ }
27
+
28
+ warnings.forEach((w) => {
29
+ console.log(chalk.yellow(`⚠ ${w}`));
30
+ });
31
+ } catch (err) {
32
+ spinner.fail("Failed to fetch package");
33
+ }
34
+ }
package/src/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { analyze } from "./analyze.js";
2
+
3
+ export async function analyzePackage(pkg) {
4
+ await analyze(pkg);
5
+ }
package/src/install.js ADDED
@@ -0,0 +1,44 @@
1
+ import { execSync } from "child_process";
2
+ import readline from "readline";
3
+ import { getPackageData } from "./npm.js";
4
+ import { calculateRisk } from "./score.js";
5
+
6
+ function askQuestion(query) {
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout,
10
+ });
11
+
12
+ return new Promise((resolve) =>
13
+ rl.question(query, (ans) => {
14
+ rl.close();
15
+ resolve(ans);
16
+ })
17
+ );
18
+ }
19
+
20
+ export async function analyzeAndPrompt(pkgName) {
21
+ console.log(`\nAnalyzing ${pkgName}...\n`);
22
+
23
+ const data = await getPackageData(pkgName);
24
+ const { score, warnings } = calculateRisk(data);
25
+
26
+ console.log(`Risk Score: ${score}/10`);
27
+
28
+ warnings.forEach((w) => console.log(`⚠ ${w}`));
29
+
30
+ if (score >= 6) {
31
+ const ans = await askQuestion(
32
+ "\nHigh risk package. Continue install? (y/n): "
33
+ );
34
+
35
+ if (ans.toLowerCase() !== "y") {
36
+ console.log("Installation aborted.");
37
+ return;
38
+ }
39
+ }
40
+
41
+ console.log("\nInstalling...\n");
42
+
43
+ execSync(`npm install ${pkgName}`, { stdio: "inherit" });
44
+ }
package/src/npm.js ADDED
@@ -0,0 +1,27 @@
1
+ import axios from "axios";
2
+
3
+ export async function getPackageData(pkg) {
4
+ const registryUrl = `https://registry.npmjs.org/${pkg}`;
5
+ const downloadUrl = `https://api.npmjs.org/downloads/point/last-week/${pkg}`;
6
+
7
+ const [registryRes, downloadRes] = await Promise.all([
8
+ axios.get(registryUrl),
9
+ axios.get(downloadUrl),
10
+ ]);
11
+
12
+ const data = registryRes.data;
13
+ const latest = data["dist-tags"].latest;
14
+ const versionData = data.versions[latest];
15
+
16
+ return {
17
+ name: data.name,
18
+ maintainers: data.maintainers?.length || 0,
19
+ lastPublished: data.time?.[latest],
20
+ hasInstallScript:
21
+ versionData.scripts?.install ||
22
+ versionData.scripts?.postinstall ||
23
+ false,
24
+ version: latest,
25
+ downloads: downloadRes.data.downloads || 0,
26
+ };
27
+ }
package/src/scan.js ADDED
@@ -0,0 +1,15 @@
1
+ import fs from "fs";
2
+ import { analyzePackage } from "./index.js";
3
+
4
+ export async function scanProject() {
5
+ const pkg = JSON.parse(fs.readFileSync("package.json"));
6
+
7
+ const deps = {
8
+ ...pkg.dependencies,
9
+ ...pkg.devDependencies,
10
+ };
11
+
12
+ for (const dep of Object.keys(deps)) {
13
+ await analyzePackage(dep);
14
+ }
15
+ }
package/src/score.js ADDED
@@ -0,0 +1,47 @@
1
+ export function calculateRisk(pkg) {
2
+ let score = 0;
3
+ const warnings = [];
4
+
5
+ // 🟢 Popularity (VERY IMPORTANT)
6
+ if (pkg.downloads < 1000) {
7
+ score += 3;
8
+ warnings.push("Very low downloads");
9
+ } else if (pkg.downloads < 10000) {
10
+ score += 2;
11
+ warnings.push("Low downloads");
12
+ }
13
+
14
+ // 🟡 Update recency
15
+ const lastUpdate = new Date(pkg.lastPublished);
16
+ const now = new Date();
17
+ const diffMonths = (now - lastUpdate) / (1000 * 60 * 60 * 24 * 30);
18
+
19
+ if (diffMonths > 12) {
20
+ score += 3;
21
+ warnings.push("Not updated in over a year");
22
+ } else if (diffMonths > 6) {
23
+ score += 1;
24
+ warnings.push("Not updated recently");
25
+ }
26
+
27
+ // 🔴 Install scripts (HIGH RISK)
28
+ if (pkg.hasInstallScript) {
29
+ score += 3;
30
+ warnings.push("Uses install/postinstall scripts");
31
+ }
32
+
33
+ // 🟢 High trust signal
34
+ if (pkg.downloads > 1000000) {
35
+ score -= 2; // reduce risk
36
+ }
37
+
38
+ if (pkg.downloads > 5000000) {
39
+ score -= 2;
40
+ }
41
+
42
+ // Normalize
43
+ if (score < 0) score = 0;
44
+ if (score > 10) score = 10;
45
+
46
+ return { score, warnings };
47
+ }