safe-pkg 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/LICENSE +21 -0
- package/README.md +304 -0
- package/dist/.DS_Store +0 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +135 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parser.d.ts +5 -0
- package/dist/cli/parser.js +61 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loadConfig.d.ts +5 -0
- package/dist/config/loadConfig.js +49 -0
- package/dist/config/loadConfig.js.map +1 -0
- package/dist/detector/detectPackageManager.d.ts +14 -0
- package/dist/detector/detectPackageManager.js +68 -0
- package/dist/detector/detectPackageManager.js.map +1 -0
- package/dist/detector/index.d.ts +1 -0
- package/dist/detector/index.js +3 -0
- package/dist/detector/index.js.map +1 -0
- package/dist/executor/index.d.ts +1 -0
- package/dist/executor/index.js +3 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/runCommand.d.ts +9 -0
- package/dist/executor/runCommand.js +61 -0
- package/dist/executor/runCommand.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/aiAnalyzer.d.ts +6 -0
- package/dist/scanner/aiAnalyzer.js +92 -0
- package/dist/scanner/aiAnalyzer.js.map +1 -0
- package/dist/scanner/analyzePackage.d.ts +5 -0
- package/dist/scanner/analyzePackage.js +155 -0
- package/dist/scanner/analyzePackage.js.map +1 -0
- package/dist/scanner/auditAnalyzer.d.ts +11 -0
- package/dist/scanner/auditAnalyzer.js +113 -0
- package/dist/scanner/auditAnalyzer.js.map +1 -0
- package/dist/scanner/heuristicAnalyzer.d.ts +5 -0
- package/dist/scanner/heuristicAnalyzer.js +228 -0
- package/dist/scanner/heuristicAnalyzer.js.map +1 -0
- package/dist/scanner/index.d.ts +6 -0
- package/dist/scanner/index.js +8 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/metadataAnalyzer.d.ts +5 -0
- package/dist/scanner/metadataAnalyzer.js +136 -0
- package/dist/scanner/metadataAnalyzer.js.map +1 -0
- package/dist/scanner/scriptAnalyzer.d.ts +5 -0
- package/dist/scanner/scriptAnalyzer.js +187 -0
- package/dist/scanner/scriptAnalyzer.js.map +1 -0
- package/dist/scanner-project/batchAnalyze.d.ts +1 -0
- package/dist/scanner-project/batchAnalyze.js +4 -0
- package/dist/scanner-project/batchAnalyze.js.map +1 -0
- package/dist/scanner-project/index.d.ts +4 -0
- package/dist/scanner-project/index.js +6 -0
- package/dist/scanner-project/index.js.map +1 -0
- package/dist/scanner-project/readDependencies.d.ts +5 -0
- package/dist/scanner-project/readDependencies.js +28 -0
- package/dist/scanner-project/readDependencies.js.map +1 -0
- package/dist/scanner-project/scanNodeModules.d.ts +1 -0
- package/dist/scanner-project/scanNodeModules.js +4 -0
- package/dist/scanner-project/scanNodeModules.js.map +1 -0
- package/dist/scanner-project/scanProject.d.ts +5 -0
- package/dist/scanner-project/scanProject.js +69 -0
- package/dist/scanner-project/scanProject.js.map +1 -0
- package/dist/test.d.ts +6 -0
- package/dist/test.js +153 -0
- package/dist/test.js.map +1 -0
- package/dist/types.d.ts +133 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +6 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/logger.d.ts +24 -0
- package/dist/ui/logger.js +39 -0
- package/dist/ui/logger.js.map +1 -0
- package/dist/ui/promptUser.d.ts +12 -0
- package/dist/ui/promptUser.js +50 -0
- package/dist/ui/promptUser.js.map +1 -0
- package/dist/ui/riskReporter.d.ts +5 -0
- package/dist/ui/riskReporter.js +157 -0
- package/dist/ui/riskReporter.js.map +1 -0
- package/dist/ui/scanReporter.d.ts +1 -0
- package/dist/ui/scanReporter.js +4 -0
- package/dist/ui/scanReporter.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Read dependencies from package.json in the project
|
|
5
|
+
*/
|
|
6
|
+
export function readDependencies(cwd) {
|
|
7
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
8
|
+
try {
|
|
9
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
10
|
+
const packageJson = JSON.parse(content);
|
|
11
|
+
const deps = packageJson.dependencies || {};
|
|
12
|
+
const devDeps = packageJson.devDependencies || {};
|
|
13
|
+
return {
|
|
14
|
+
dependencies: deps,
|
|
15
|
+
devDependencies: devDeps,
|
|
16
|
+
total: Object.keys(deps).length + Object.keys(devDeps).length,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
// If package.json doesn't exist or can't be read, return empty
|
|
21
|
+
return {
|
|
22
|
+
dependencies: {},
|
|
23
|
+
devDependencies: {},
|
|
24
|
+
total: 0,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=readDependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readDependencies.js","sourceRoot":"","sources":["../../src/scanner-project/readDependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAElD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAGrC,CAAC;QAEF,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,IAAI,EAAE,CAAC;QAElD,OAAO;YACN,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,OAAO;YACxB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM;SAC7D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,+DAA+D;QAC/D,OAAO;YACN,YAAY,EAAE,EAAE;YAChB,eAAe,EAAE,EAAE;YACnB,KAAK,EAAE,CAAC;SACR,CAAC;IACH,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanNodeModules.js","sourceRoot":"","sources":["../../src/scanner-project/scanNodeModules.ts"],"names":[],"mappings":";AAAA,8BAA8B;AAC9B,iCAAiC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { analyzePackage } from "../scanner/analyzePackage.js";
|
|
3
|
+
import { logError, logStep, logSuccess, logWarning } from "../ui/logger.js";
|
|
4
|
+
import { readDependencies } from "./readDependencies.js";
|
|
5
|
+
/**
|
|
6
|
+
* Scan all dependencies in the current project
|
|
7
|
+
*/
|
|
8
|
+
export async function scanProject(cwd, config, includeDevDeps = false) {
|
|
9
|
+
logStep("Reading project dependencies...");
|
|
10
|
+
const deps = readDependencies(cwd);
|
|
11
|
+
const allDeps = {
|
|
12
|
+
...deps.dependencies,
|
|
13
|
+
...(includeDevDeps ? deps.devDependencies : {}),
|
|
14
|
+
};
|
|
15
|
+
const packageNames = Object.keys(allDeps);
|
|
16
|
+
if (packageNames.length === 0) {
|
|
17
|
+
logWarning("No dependencies found in package.json");
|
|
18
|
+
return {
|
|
19
|
+
totalPackages: 0,
|
|
20
|
+
scannedPackages: 0,
|
|
21
|
+
highRiskCount: 0,
|
|
22
|
+
criticalVulnerabilities: 0,
|
|
23
|
+
reports: [],
|
|
24
|
+
summary: {
|
|
25
|
+
safe: 0,
|
|
26
|
+
caution: 0,
|
|
27
|
+
dangerous: 0,
|
|
28
|
+
},
|
|
29
|
+
scannedAt: new Date(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
logStep(`Analyzing ${packageNames.length} packages...\n`);
|
|
33
|
+
const reports = [];
|
|
34
|
+
let analyzed = 0;
|
|
35
|
+
// Analyze packages sequentially to avoid rate limits
|
|
36
|
+
for (const packageName of packageNames) {
|
|
37
|
+
try {
|
|
38
|
+
analyzed++;
|
|
39
|
+
process.stdout.write(chalk.gray(` [${analyzed}/${packageNames.length}] Analyzing ${packageName}...\r`));
|
|
40
|
+
const report = await analyzePackage(packageName, config);
|
|
41
|
+
reports.push(report);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
// Log error but continue with other packages
|
|
45
|
+
logError(`Failed to analyze ${packageName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Clear progress line
|
|
49
|
+
process.stdout.write(`${" ".repeat(80)}\r`);
|
|
50
|
+
// Count by risk level
|
|
51
|
+
const safePackages = reports.filter((r) => r.riskLevel === "safe").length;
|
|
52
|
+
const cautionPackages = reports.filter((r) => r.riskLevel === "caution").length;
|
|
53
|
+
const dangerousPackages = reports.filter((r) => r.riskLevel === "dangerous").length;
|
|
54
|
+
logSuccess(`Analyzed ${reports.length}/${packageNames.length} packages`);
|
|
55
|
+
return {
|
|
56
|
+
totalPackages: packageNames.length,
|
|
57
|
+
scannedPackages: reports.length,
|
|
58
|
+
highRiskCount: cautionPackages + dangerousPackages,
|
|
59
|
+
criticalVulnerabilities: dangerousPackages,
|
|
60
|
+
reports,
|
|
61
|
+
summary: {
|
|
62
|
+
safe: safePackages,
|
|
63
|
+
caution: cautionPackages,
|
|
64
|
+
dangerous: dangerousPackages,
|
|
65
|
+
},
|
|
66
|
+
scannedAt: new Date(),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=scanProject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanProject.js","sourceRoot":"","sources":["../../src/scanner-project/scanProject.ts"],"names":[],"mappings":"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"}
|
package/dist/test.d.ts
ADDED
package/dist/test.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script for safe-pkg analysis engine
|
|
3
|
+
* Run with: node --loader ts-node/esm src/test.ts
|
|
4
|
+
* Or compile first: pnpm run build && node dist/test.js
|
|
5
|
+
*/
|
|
6
|
+
import { analyzePackage } from "./scanner/analyzePackage.js";
|
|
7
|
+
// ============================================
|
|
8
|
+
// HARDCODE YOUR ANTHROPIC API KEY HERE FOR TESTING
|
|
9
|
+
// ============================================
|
|
10
|
+
const ANTHROPIC_API_KEY = ""; // Add your key here: "sk-ant-..."
|
|
11
|
+
// Test configuration
|
|
12
|
+
const config = {
|
|
13
|
+
anthropicApiKey: ANTHROPIC_API_KEY || undefined,
|
|
14
|
+
riskThreshold: 7,
|
|
15
|
+
autoConfirm: false,
|
|
16
|
+
};
|
|
17
|
+
// Packages to test (mix of safe, risky, and unknown)
|
|
18
|
+
const TEST_PACKAGES = [
|
|
19
|
+
// Popular, well-maintained packages (should be safe)
|
|
20
|
+
"react",
|
|
21
|
+
"express",
|
|
22
|
+
"chalk",
|
|
23
|
+
// Less popular packages (might have warnings)
|
|
24
|
+
"tiny-package-that-doesnt-exist-12345",
|
|
25
|
+
// Package with potential security concerns (if any)
|
|
26
|
+
// Add any specific packages you want to test here
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Format and display risk report
|
|
30
|
+
*/
|
|
31
|
+
function displayReport(packageName, report) {
|
|
32
|
+
console.log(`\n${"=".repeat(80)}`);
|
|
33
|
+
console.log(`📦 Package: ${packageName}`);
|
|
34
|
+
console.log("=".repeat(80));
|
|
35
|
+
console.log(`\n🎯 Risk Score: ${report.riskScore}/10`);
|
|
36
|
+
console.log(`📊 Risk Level: ${report.riskLevel.toUpperCase()}`);
|
|
37
|
+
console.log(`✅ Version: ${report.version}`);
|
|
38
|
+
console.log(`🕐 Analyzed: ${report.analyzedAt.toISOString()}`);
|
|
39
|
+
// Display recommendation
|
|
40
|
+
console.log(`\n💡 Recommendation:\n ${report.recommendation}`);
|
|
41
|
+
// Display warnings
|
|
42
|
+
if (report.warnings.length > 0) {
|
|
43
|
+
console.log(`\n⚠️ Warnings (${report.warnings.length}):`);
|
|
44
|
+
for (const warning of report.warnings) {
|
|
45
|
+
const icon = warning.severity === "critical"
|
|
46
|
+
? "🔴"
|
|
47
|
+
: warning.severity === "high"
|
|
48
|
+
? "🟠"
|
|
49
|
+
: warning.severity === "medium"
|
|
50
|
+
? "🟡"
|
|
51
|
+
: "🔵";
|
|
52
|
+
console.log(` ${icon} [${warning.severity.toUpperCase()}] ${warning.message}`);
|
|
53
|
+
console.log(` Source: ${warning.source}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Display analyzer details
|
|
57
|
+
console.log("\n📋 Analyzer Results:");
|
|
58
|
+
if (report.analyzers.audit) {
|
|
59
|
+
const audit = report.analyzers.audit;
|
|
60
|
+
console.log(` • Audit: ${audit.vulnerabilityCount} vulnerabilities (score: ${audit.riskScore}/10)`);
|
|
61
|
+
if (audit.criticalCount > 0 || audit.highCount > 0) {
|
|
62
|
+
console.log(` - ${audit.criticalCount} critical, ${audit.highCount} high`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(" • Audit: N/A (failed or skipped)");
|
|
67
|
+
}
|
|
68
|
+
if (report.analyzers.metadata) {
|
|
69
|
+
const meta = report.analyzers.metadata;
|
|
70
|
+
console.log(` • Metadata: ${meta.downloads.toLocaleString()} weekly downloads (score: ${meta.riskScore}/10)`);
|
|
71
|
+
console.log(` - Age: ${meta.packageAge} days, Maintainers: ${meta.maintainerCount}, License: ${meta.hasLicense ? "Yes" : "No"}`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log(" • Metadata: N/A (failed or skipped)");
|
|
75
|
+
}
|
|
76
|
+
if (report.analyzers.script) {
|
|
77
|
+
const script = report.analyzers.script;
|
|
78
|
+
console.log(` • Scripts: ${script.hasSuspiciousScripts ? "⚠️ Suspicious" : "✓ Clean"} (score: ${script.riskScore}/10)`);
|
|
79
|
+
if (script.suspiciousScripts.length > 0) {
|
|
80
|
+
console.log(` - Found: ${script.suspiciousScripts.join(", ")}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(" • Scripts: N/A (failed or skipped)");
|
|
85
|
+
}
|
|
86
|
+
if (report.analyzers.heuristic) {
|
|
87
|
+
const heuristic = report.analyzers.heuristic;
|
|
88
|
+
console.log(` • Heuristics: ${heuristic.isPotentialTyposquat ? "⚠️ Typosquat risk" : "✓ Clean"} (score: ${heuristic.riskScore}/10)`);
|
|
89
|
+
if (heuristic.suspiciousPatterns.length > 0) {
|
|
90
|
+
console.log(` - Patterns: ${heuristic.suspiciousPatterns.join(", ")}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(" • Heuristics: N/A");
|
|
95
|
+
}
|
|
96
|
+
// Display AI insights if available
|
|
97
|
+
if (report.analyzers.aiInsights) {
|
|
98
|
+
console.log("\n🤖 AI Insights:");
|
|
99
|
+
console.log(` ${report.analyzers.aiInsights.replace(/\n/g, "\n ")}`);
|
|
100
|
+
}
|
|
101
|
+
else if (ANTHROPIC_API_KEY) {
|
|
102
|
+
console.log("\n🤖 AI Insights: N/A (enhancement failed)");
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log("\n🤖 AI Insights: Disabled (set ANTHROPIC_API_KEY to enable)");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Run tests on all packages
|
|
110
|
+
*/
|
|
111
|
+
async function runTests() {
|
|
112
|
+
console.log("🚀 Starting safe-pkg Analysis Engine Tests");
|
|
113
|
+
console.log(`🔑 Anthropic API: ${ANTHROPIC_API_KEY ? "✓ Enabled" : "✗ Disabled"}`);
|
|
114
|
+
console.log(`📦 Testing ${TEST_PACKAGES.length} packages...\n`);
|
|
115
|
+
const results = [];
|
|
116
|
+
for (const packageName of TEST_PACKAGES) {
|
|
117
|
+
try {
|
|
118
|
+
console.log(`\n⏳ Analyzing ${packageName}...`);
|
|
119
|
+
const report = await analyzePackage(packageName, config);
|
|
120
|
+
displayReport(packageName, report);
|
|
121
|
+
results.push({ package: packageName, success: true });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error(`\n❌ Error analyzing ${packageName}:`, error);
|
|
125
|
+
results.push({
|
|
126
|
+
package: packageName,
|
|
127
|
+
success: false,
|
|
128
|
+
error: error instanceof Error ? error.message : String(error),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Summary
|
|
133
|
+
console.log(`\n${"=".repeat(80)}`);
|
|
134
|
+
console.log("📊 TEST SUMMARY");
|
|
135
|
+
console.log("=".repeat(80));
|
|
136
|
+
const successful = results.filter((r) => r.success).length;
|
|
137
|
+
const failed = results.filter((r) => !r.success).length;
|
|
138
|
+
console.log(`✅ Successful: ${successful}/${TEST_PACKAGES.length}`);
|
|
139
|
+
console.log(`❌ Failed: ${failed}/${TEST_PACKAGES.length}`);
|
|
140
|
+
if (failed > 0) {
|
|
141
|
+
console.log("\nFailed packages:");
|
|
142
|
+
for (const result of results.filter((r) => !r.success)) {
|
|
143
|
+
console.log(` • ${result.package}: ${result.error}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log("\n✨ Tests completed!\n");
|
|
147
|
+
}
|
|
148
|
+
// Run tests
|
|
149
|
+
runTests().catch((error) => {
|
|
150
|
+
console.error("Fatal error running tests:", error);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported package managers
|
|
3
|
+
*/
|
|
4
|
+
export type PackageManager = "npm" | "yarn" | "pnpm";
|
|
5
|
+
/**
|
|
6
|
+
* Risk levels for package analysis
|
|
7
|
+
*/
|
|
8
|
+
export type RiskLevel = "safe" | "caution" | "dangerous";
|
|
9
|
+
/**
|
|
10
|
+
* Analyzer type that performed the analysis
|
|
11
|
+
*/
|
|
12
|
+
export type AnalyzerType = "audit" | "metadata" | "script" | "heuristic" | "ai";
|
|
13
|
+
/**
|
|
14
|
+
* Individual warning from an analyzer
|
|
15
|
+
*/
|
|
16
|
+
export interface Warning {
|
|
17
|
+
message: string;
|
|
18
|
+
severity: "low" | "medium" | "high" | "critical";
|
|
19
|
+
source: AnalyzerType;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Result from npm audit analysis
|
|
23
|
+
*/
|
|
24
|
+
export interface AuditResult {
|
|
25
|
+
vulnerabilityCount: number;
|
|
26
|
+
criticalCount: number;
|
|
27
|
+
highCount: number;
|
|
28
|
+
moderateCount: number;
|
|
29
|
+
lowCount: number;
|
|
30
|
+
vulnerabilities: Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
severity: "low" | "moderate" | "high" | "critical";
|
|
33
|
+
via: string;
|
|
34
|
+
}>;
|
|
35
|
+
riskScore: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result from package metadata analysis
|
|
39
|
+
*/
|
|
40
|
+
export interface MetadataScore {
|
|
41
|
+
version: string;
|
|
42
|
+
downloads: number;
|
|
43
|
+
lastPublishDate: Date;
|
|
44
|
+
maintainerCount: number;
|
|
45
|
+
hasLicense: boolean;
|
|
46
|
+
packageAge: number;
|
|
47
|
+
riskScore: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Result from script detection analysis
|
|
51
|
+
*/
|
|
52
|
+
export interface ScriptRisk {
|
|
53
|
+
hasSuspiciousScripts: boolean;
|
|
54
|
+
suspiciousScripts: string[];
|
|
55
|
+
dangerousCommands: string[];
|
|
56
|
+
riskScore: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Result from heuristic analysis
|
|
60
|
+
*/
|
|
61
|
+
export interface HeuristicScore {
|
|
62
|
+
suspiciousPatterns: string[];
|
|
63
|
+
isPotentialTyposquat: boolean;
|
|
64
|
+
riskScore: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Complete risk report for a package
|
|
68
|
+
*/
|
|
69
|
+
export interface RiskReport {
|
|
70
|
+
packageName: string;
|
|
71
|
+
version: string;
|
|
72
|
+
riskScore: number;
|
|
73
|
+
riskLevel: RiskLevel;
|
|
74
|
+
warnings: Warning[];
|
|
75
|
+
recommendation: string;
|
|
76
|
+
analyzers: {
|
|
77
|
+
audit?: AuditResult;
|
|
78
|
+
metadata?: MetadataScore;
|
|
79
|
+
script?: ScriptRisk;
|
|
80
|
+
heuristic?: HeuristicScore;
|
|
81
|
+
aiInsights?: string;
|
|
82
|
+
};
|
|
83
|
+
analyzedAt: Date;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Analysis result (can include errors)
|
|
87
|
+
*/
|
|
88
|
+
export interface AnalysisResult {
|
|
89
|
+
success: boolean;
|
|
90
|
+
report?: RiskReport;
|
|
91
|
+
error?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parsed command configuration
|
|
95
|
+
*/
|
|
96
|
+
export interface CommandConfig {
|
|
97
|
+
action: "install" | "scan" | "check" | "help";
|
|
98
|
+
packages: string[];
|
|
99
|
+
options: Record<string, unknown>;
|
|
100
|
+
packageManager?: PackageManager;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* List of dependencies from package.json
|
|
104
|
+
*/
|
|
105
|
+
export interface DependencyList {
|
|
106
|
+
dependencies: Record<string, string>;
|
|
107
|
+
devDependencies: Record<string, string>;
|
|
108
|
+
total: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Result from project scan
|
|
112
|
+
*/
|
|
113
|
+
export interface ProjectScanResult {
|
|
114
|
+
totalPackages: number;
|
|
115
|
+
scannedPackages: number;
|
|
116
|
+
highRiskCount: number;
|
|
117
|
+
criticalVulnerabilities: number;
|
|
118
|
+
reports: RiskReport[];
|
|
119
|
+
summary: {
|
|
120
|
+
safe: number;
|
|
121
|
+
caution: number;
|
|
122
|
+
dangerous: number;
|
|
123
|
+
};
|
|
124
|
+
scannedAt: Date;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Configuration loaded from env or file
|
|
128
|
+
*/
|
|
129
|
+
export interface Config {
|
|
130
|
+
anthropicApiKey?: string;
|
|
131
|
+
riskThreshold: number;
|
|
132
|
+
autoConfirm: boolean;
|
|
133
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log a step/info message
|
|
3
|
+
*/
|
|
4
|
+
export declare function logStep(message: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Log a success message
|
|
7
|
+
*/
|
|
8
|
+
export declare function logSuccess(message: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Log a warning message
|
|
11
|
+
*/
|
|
12
|
+
export declare function logWarning(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Log an error message
|
|
15
|
+
*/
|
|
16
|
+
export declare function logError(message: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Log a section header
|
|
19
|
+
*/
|
|
20
|
+
export declare function logHeader(message: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Log blank line for spacing
|
|
23
|
+
*/
|
|
24
|
+
export declare function logNewline(): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
/**
|
|
3
|
+
* Log a step/info message
|
|
4
|
+
*/
|
|
5
|
+
export function logStep(message) {
|
|
6
|
+
console.log(chalk.blue("ℹ"), message);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Log a success message
|
|
10
|
+
*/
|
|
11
|
+
export function logSuccess(message) {
|
|
12
|
+
console.log(chalk.green("✔"), message);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Log a warning message
|
|
16
|
+
*/
|
|
17
|
+
export function logWarning(message) {
|
|
18
|
+
console.log(chalk.yellow("⚠"), message);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Log an error message
|
|
22
|
+
*/
|
|
23
|
+
export function logError(message) {
|
|
24
|
+
console.log(chalk.red("✖"), message);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Log a section header
|
|
28
|
+
*/
|
|
29
|
+
export function logHeader(message) {
|
|
30
|
+
console.log(`\n${chalk.bold.cyan(message)}`);
|
|
31
|
+
console.log(chalk.gray("=".repeat(Math.min(message.length, 80))));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Log blank line for spacing
|
|
35
|
+
*/
|
|
36
|
+
export function logNewline() {
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe;IACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,OAAO,CAAC,GAAG,EAAE,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RiskLevel } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ask user for confirmation before installing a package
|
|
4
|
+
*/
|
|
5
|
+
export declare function askUserConfirmation(packageName: string, riskLevel: RiskLevel, riskScore: number): Promise<boolean>;
|
|
6
|
+
/**
|
|
7
|
+
* Ask user which packages to install from a list
|
|
8
|
+
*/
|
|
9
|
+
export declare function selectPackagesToInstall(packages: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
safe: boolean;
|
|
12
|
+
}>): Promise<string[]>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
/**
|
|
4
|
+
* Ask user for confirmation before installing a package
|
|
5
|
+
*/
|
|
6
|
+
export async function askUserConfirmation(packageName, riskLevel, riskScore) {
|
|
7
|
+
// Auto-deny for dangerous packages
|
|
8
|
+
if (riskLevel === "dangerous") {
|
|
9
|
+
const response = await prompts({
|
|
10
|
+
type: "confirm",
|
|
11
|
+
name: "proceed",
|
|
12
|
+
message: chalk.red.bold(`Package "${packageName}" is DANGEROUS (score: ${riskScore}/10). Install anyway?`),
|
|
13
|
+
initial: false,
|
|
14
|
+
});
|
|
15
|
+
return response.proceed ?? false;
|
|
16
|
+
}
|
|
17
|
+
// Warn for caution packages
|
|
18
|
+
if (riskLevel === "caution") {
|
|
19
|
+
const response = await prompts({
|
|
20
|
+
type: "confirm",
|
|
21
|
+
name: "proceed",
|
|
22
|
+
message: chalk.yellow(`Package "${packageName}" has warnings (score: ${riskScore}/10). Continue?`),
|
|
23
|
+
initial: false,
|
|
24
|
+
});
|
|
25
|
+
return response.proceed ?? false;
|
|
26
|
+
}
|
|
27
|
+
// Auto-proceed for safe packages (but can be overridden by config)
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ask user which packages to install from a list
|
|
32
|
+
*/
|
|
33
|
+
export async function selectPackagesToInstall(packages) {
|
|
34
|
+
const choices = packages.map((pkg) => ({
|
|
35
|
+
title: pkg.safe
|
|
36
|
+
? `${chalk.green("✓")} ${pkg.name}`
|
|
37
|
+
: `${chalk.red("✖")} ${pkg.name}`,
|
|
38
|
+
value: pkg.name,
|
|
39
|
+
selected: pkg.safe,
|
|
40
|
+
}));
|
|
41
|
+
const response = await prompts({
|
|
42
|
+
type: "multiselect",
|
|
43
|
+
name: "packages",
|
|
44
|
+
message: "Select packages to install:",
|
|
45
|
+
choices,
|
|
46
|
+
hint: "Space to select, Enter to confirm",
|
|
47
|
+
});
|
|
48
|
+
return response.packages ?? [];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=promptUser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptUser.js","sourceRoot":"","sources":["../../src/ui/promptUser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,WAAmB,EACnB,SAAoB,EACpB,SAAiB;IAEjB,mCAAmC;IACnC,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC9B,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CACtB,YAAY,WAAW,0BAA0B,SAAS,uBAAuB,CACjF;YACD,OAAO,EAAE,KAAK;SACd,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC;IAClC,CAAC;IAED,4BAA4B;IAC5B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC9B,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK,CAAC,MAAM,CACpB,YAAY,WAAW,0BAA0B,SAAS,iBAAiB,CAC3E;YACD,OAAO,EAAE,KAAK;SACd,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC;IAClC,CAAC;IAED,mEAAmE;IACnE,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,QAAgD;IAEhD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACtC,KAAK,EAAE,GAAG,CAAC,IAAI;YACd,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE;YACnC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE;QAClC,KAAK,EAAE,GAAG,CAAC,IAAI;QACf,QAAQ,EAAE,GAAG,CAAC,IAAI;KAClB,CAAC,CAAC,CAAC;IAEJ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;QAC9B,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,6BAA6B;QACtC,OAAO;QACP,IAAI,EAAE,mCAAmC;KACzC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;AAChC,CAAC"}
|