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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +304 -0
  3. package/dist/.DS_Store +0 -0
  4. package/dist/cli/index.d.ts +5 -0
  5. package/dist/cli/index.js +135 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/parser.d.ts +5 -0
  8. package/dist/cli/parser.js +61 -0
  9. package/dist/cli/parser.js.map +1 -0
  10. package/dist/config/index.d.ts +1 -0
  11. package/dist/config/index.js +3 -0
  12. package/dist/config/index.js.map +1 -0
  13. package/dist/config/loadConfig.d.ts +5 -0
  14. package/dist/config/loadConfig.js +49 -0
  15. package/dist/config/loadConfig.js.map +1 -0
  16. package/dist/detector/detectPackageManager.d.ts +14 -0
  17. package/dist/detector/detectPackageManager.js +68 -0
  18. package/dist/detector/detectPackageManager.js.map +1 -0
  19. package/dist/detector/index.d.ts +1 -0
  20. package/dist/detector/index.js +3 -0
  21. package/dist/detector/index.js.map +1 -0
  22. package/dist/executor/index.d.ts +1 -0
  23. package/dist/executor/index.js +3 -0
  24. package/dist/executor/index.js.map +1 -0
  25. package/dist/executor/runCommand.d.ts +9 -0
  26. package/dist/executor/runCommand.js +61 -0
  27. package/dist/executor/runCommand.js.map +1 -0
  28. package/dist/index.d.ts +8 -0
  29. package/dist/index.js +11 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/scanner/aiAnalyzer.d.ts +6 -0
  32. package/dist/scanner/aiAnalyzer.js +92 -0
  33. package/dist/scanner/aiAnalyzer.js.map +1 -0
  34. package/dist/scanner/analyzePackage.d.ts +5 -0
  35. package/dist/scanner/analyzePackage.js +155 -0
  36. package/dist/scanner/analyzePackage.js.map +1 -0
  37. package/dist/scanner/auditAnalyzer.d.ts +11 -0
  38. package/dist/scanner/auditAnalyzer.js +113 -0
  39. package/dist/scanner/auditAnalyzer.js.map +1 -0
  40. package/dist/scanner/heuristicAnalyzer.d.ts +5 -0
  41. package/dist/scanner/heuristicAnalyzer.js +228 -0
  42. package/dist/scanner/heuristicAnalyzer.js.map +1 -0
  43. package/dist/scanner/index.d.ts +6 -0
  44. package/dist/scanner/index.js +8 -0
  45. package/dist/scanner/index.js.map +1 -0
  46. package/dist/scanner/metadataAnalyzer.d.ts +5 -0
  47. package/dist/scanner/metadataAnalyzer.js +136 -0
  48. package/dist/scanner/metadataAnalyzer.js.map +1 -0
  49. package/dist/scanner/scriptAnalyzer.d.ts +5 -0
  50. package/dist/scanner/scriptAnalyzer.js +187 -0
  51. package/dist/scanner/scriptAnalyzer.js.map +1 -0
  52. package/dist/scanner-project/batchAnalyze.d.ts +1 -0
  53. package/dist/scanner-project/batchAnalyze.js +4 -0
  54. package/dist/scanner-project/batchAnalyze.js.map +1 -0
  55. package/dist/scanner-project/index.d.ts +4 -0
  56. package/dist/scanner-project/index.js +6 -0
  57. package/dist/scanner-project/index.js.map +1 -0
  58. package/dist/scanner-project/readDependencies.d.ts +5 -0
  59. package/dist/scanner-project/readDependencies.js +28 -0
  60. package/dist/scanner-project/readDependencies.js.map +1 -0
  61. package/dist/scanner-project/scanNodeModules.d.ts +1 -0
  62. package/dist/scanner-project/scanNodeModules.js +4 -0
  63. package/dist/scanner-project/scanNodeModules.js.map +1 -0
  64. package/dist/scanner-project/scanProject.d.ts +5 -0
  65. package/dist/scanner-project/scanProject.js +69 -0
  66. package/dist/scanner-project/scanProject.js.map +1 -0
  67. package/dist/test.d.ts +6 -0
  68. package/dist/test.js +153 -0
  69. package/dist/test.js.map +1 -0
  70. package/dist/types.d.ts +133 -0
  71. package/dist/types.js +2 -0
  72. package/dist/types.js.map +1 -0
  73. package/dist/ui/index.d.ts +4 -0
  74. package/dist/ui/index.js +6 -0
  75. package/dist/ui/index.js.map +1 -0
  76. package/dist/ui/logger.d.ts +24 -0
  77. package/dist/ui/logger.js +39 -0
  78. package/dist/ui/logger.js.map +1 -0
  79. package/dist/ui/promptUser.d.ts +12 -0
  80. package/dist/ui/promptUser.js +50 -0
  81. package/dist/ui/promptUser.js.map +1 -0
  82. package/dist/ui/riskReporter.d.ts +5 -0
  83. package/dist/ui/riskReporter.js +157 -0
  84. package/dist/ui/riskReporter.js.map +1 -0
  85. package/dist/ui/scanReporter.d.ts +1 -0
  86. package/dist/ui/scanReporter.js +4 -0
  87. package/dist/ui/scanReporter.js.map +1 -0
  88. package/package.json +61 -0
@@ -0,0 +1,68 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { execa } from "execa";
4
+ /**
5
+ * Detect package manager from lock files in the given directory
6
+ * Priority: pnpm > yarn > npm
7
+ */
8
+ export async function detectPackageManager(cwd = process.cwd()) {
9
+ // Check for lock files
10
+ const lockFileMap = [
11
+ { file: "pnpm-lock.yaml", manager: "pnpm" },
12
+ { file: "yarn.lock", manager: "yarn" },
13
+ { file: "package-lock.json", manager: "npm" },
14
+ ];
15
+ for (const { file, manager } of lockFileMap) {
16
+ if (existsSync(join(cwd, file))) {
17
+ return manager;
18
+ }
19
+ }
20
+ // Fallback: check which package manager binary is available
21
+ const availableManager = await detectAvailablePackageManager();
22
+ if (availableManager) {
23
+ return availableManager;
24
+ }
25
+ // Final fallback: npm (most commonly available)
26
+ return "npm";
27
+ }
28
+ /**
29
+ * Check which package manager binaries are available on the system
30
+ */
31
+ async function detectAvailablePackageManager() {
32
+ const managers = ["pnpm", "yarn", "npm"];
33
+ for (const manager of managers) {
34
+ try {
35
+ await execa("which", [manager]);
36
+ return manager;
37
+ }
38
+ catch {
39
+ // Binary not found, continue to next
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Check if a specific package manager is available
46
+ */
47
+ export async function isPackageManagerAvailable(manager) {
48
+ try {
49
+ await execa("which", [manager]);
50
+ return true;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ /**
57
+ * Get the version of a package manager
58
+ */
59
+ export async function getPackageManagerVersion(manager) {
60
+ try {
61
+ const { stdout } = await execa(manager, ["--version"]);
62
+ return stdout.trim();
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ //# sourceMappingURL=detectPackageManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectPackageManager.js","sourceRoot":"","sources":["../../src/detector/detectPackageManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,uBAAuB;IACvB,MAAM,WAAW,GAAqD;QACrE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE;QAC3C,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE;QACtC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE;KAC7C,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACjC,OAAO,OAAO,CAAC;QAChB,CAAC;IACF,CAAC;IAED,4DAA4D;IAC5D,MAAM,gBAAgB,GAAG,MAAM,6BAA6B,EAAE,CAAC;IAC/D,IAAI,gBAAgB,EAAE,CAAC;QACtB,OAAO,gBAAgB,CAAC;IACzB,CAAC;IAED,gDAAgD;IAChD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,6BAA6B;IAC3C,MAAM,QAAQ,GAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC;YACJ,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YAChC,OAAO,OAAO,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACR,qCAAqC;QACtC,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,OAAuB;IAEvB,IAAI,CAAC;QACJ,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,OAAuB;IAEvB,IAAI,CAAC;QACJ,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QACvD,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1 @@
1
+ export { detectPackageManager, isPackageManagerAvailable, getPackageManagerVersion, } from "./detectPackageManager.js";
@@ -0,0 +1,3 @@
1
+ // Package manager detector barrel exports
2
+ export { detectPackageManager, isPackageManagerAvailable, getPackageManagerVersion, } from "./detectPackageManager.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detector/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EACN,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,GACxB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./runCommand.js";
@@ -0,0 +1,3 @@
1
+ // Executor barrel exports
2
+ export * from "./runCommand.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PackageManager } from "../types.js";
2
+ /**
3
+ * Execute package manager install command
4
+ */
5
+ export declare function runInstallCommand(packageManager: PackageManager, packages: string[], options?: Record<string, unknown>): Promise<void>;
6
+ /**
7
+ * Execute arbitrary package manager command
8
+ */
9
+ export declare function runPackageManagerCommand(packageManager: PackageManager, args: string[]): Promise<void>;
@@ -0,0 +1,61 @@
1
+ import { execa } from "execa";
2
+ import { logError, logStep, logSuccess } from "../ui/logger.js";
3
+ /**
4
+ * Execute package manager install command
5
+ */
6
+ export async function runInstallCommand(packageManager, packages, options = {}) {
7
+ const args = [];
8
+ // Build command arguments based on package manager
9
+ if (packageManager === "npm") {
10
+ args.push("install");
11
+ if (options.saveDev)
12
+ args.push("--save-dev");
13
+ if (options.global)
14
+ args.push("--global");
15
+ }
16
+ else if (packageManager === "yarn") {
17
+ args.push("add");
18
+ if (options.saveDev)
19
+ args.push("--dev");
20
+ if (options.global)
21
+ args.push("global");
22
+ }
23
+ else if (packageManager === "pnpm") {
24
+ args.push("add");
25
+ if (options.saveDev)
26
+ args.push("--save-dev");
27
+ if (options.global)
28
+ args.push("--global");
29
+ }
30
+ // Add package names
31
+ args.push(...packages);
32
+ logStep(`Running: ${packageManager} ${args.join(" ")}`);
33
+ try {
34
+ // Run package manager command
35
+ await execa(packageManager, args, {
36
+ stdio: "inherit",
37
+ cwd: process.cwd(),
38
+ });
39
+ logSuccess(`Successfully installed ${packages.length} package(s)`);
40
+ }
41
+ catch (error) {
42
+ logError(`Installation failed: ${error instanceof Error ? error.message : String(error)}`);
43
+ throw error;
44
+ }
45
+ }
46
+ /**
47
+ * Execute arbitrary package manager command
48
+ */
49
+ export async function runPackageManagerCommand(packageManager, args) {
50
+ try {
51
+ await execa(packageManager, args, {
52
+ stdio: "inherit",
53
+ cwd: process.cwd(),
54
+ });
55
+ }
56
+ catch (error) {
57
+ logError(`Command failed: ${error instanceof Error ? error.message : String(error)}`);
58
+ throw error;
59
+ }
60
+ }
61
+ //# sourceMappingURL=runCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../../src/executor/runCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,cAA8B,EAC9B,QAAkB,EAClB,UAAmC,EAAE;IAErC,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,mDAAmD;IACnD,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrB,IAAI,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;SAAM,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;SAAM,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED,oBAAoB;IACpB,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAEvB,OAAO,CAAC,YAAY,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAExD,IAAI,CAAC;QACJ,8BAA8B;QAC9B,MAAM,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE;YACjC,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SAClB,CAAC,CAAC;QAEH,UAAU,CAAC,0BAA0B,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,QAAQ,CACP,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChF,CAAC;QACF,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,cAA8B,EAC9B,IAAc;IAEd,IAAI,CAAC;QACJ,MAAM,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE;YACjC,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SAClB,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,QAAQ,CACP,mBAAmB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC3E,CAAC;QACF,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from "./types.js";
2
+ export * from "./cli/index.js";
3
+ export * from "./config/index.js";
4
+ export * from "./detector/index.js";
5
+ export * from "./scanner/index.js";
6
+ export * from "./scanner-project/index.js";
7
+ export * from "./executor/index.js";
8
+ export * from "./ui/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ // Export all types
2
+ export * from "./types.js";
3
+ // Export module interfaces (implementations will be added in later phases)
4
+ export * from "./cli/index.js";
5
+ export * from "./config/index.js";
6
+ export * from "./detector/index.js";
7
+ export * from "./scanner/index.js";
8
+ export * from "./scanner-project/index.js";
9
+ export * from "./executor/index.js";
10
+ export * from "./ui/index.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,cAAc,YAAY,CAAC;AAE3B,2EAA2E;AAC3E,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { RiskReport } from "../types.js";
2
+ /**
3
+ * Enhance risk report with AI insights using Anthropic Claude
4
+ * This is optional and only runs if API key is provided
5
+ */
6
+ export declare function enhanceWithAI(report: RiskReport, apiKey: string): Promise<RiskReport>;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Enhance risk report with AI insights using Anthropic Claude
3
+ * This is optional and only runs if API key is provided
4
+ */
5
+ export async function enhanceWithAI(report, apiKey) {
6
+ try {
7
+ // Dynamically import Anthropic SDK (optional dependency)
8
+ const { default: Anthropic } = await import("@anthropic-ai/sdk");
9
+ const client = new Anthropic({
10
+ apiKey,
11
+ });
12
+ // Prepare analysis summary for Claude
13
+ const analysisContext = prepareAnalysisContext(report);
14
+ // Call Claude API
15
+ const message = await client.messages.create({
16
+ model: "claude-3-5-sonnet-20241022",
17
+ max_tokens: 500,
18
+ messages: [
19
+ {
20
+ role: "user",
21
+ content: `You are a security expert analyzing an npm package. Here's the automated analysis:
22
+
23
+ Package: ${report.packageName}
24
+ Risk Score: ${report.riskScore}/10
25
+ Risk Level: ${report.riskLevel}
26
+
27
+ Analysis Results:
28
+ ${analysisContext}
29
+
30
+ Provide a brief security assessment (2-3 sentences) explaining:
31
+ 1. The main security concerns or why it's safe
32
+ 2. Any additional context a developer should know
33
+ 3. Your recommendation
34
+
35
+ Be concise and focus on actionable insights.`,
36
+ },
37
+ ],
38
+ });
39
+ // Extract AI insights from response
40
+ const aiInsights = message.content[0]?.type === "text" ? message.content[0].text : "";
41
+ // Return enhanced report
42
+ return {
43
+ ...report,
44
+ analyzers: {
45
+ ...report.analyzers,
46
+ aiInsights,
47
+ },
48
+ };
49
+ }
50
+ catch (error) {
51
+ // If AI enhancement fails, return original report
52
+ // This ensures the tool still works without AI
53
+ return report;
54
+ }
55
+ }
56
+ /**
57
+ * Prepare analysis context for AI
58
+ */
59
+ function prepareAnalysisContext(report) {
60
+ const parts = [];
61
+ // Audit results
62
+ if (report.analyzers.audit) {
63
+ const audit = report.analyzers.audit;
64
+ parts.push(`- Vulnerabilities: ${audit.vulnerabilityCount} total (${audit.criticalCount} critical, ${audit.highCount} high)`);
65
+ }
66
+ // Metadata results
67
+ if (report.analyzers.metadata) {
68
+ const meta = report.analyzers.metadata;
69
+ parts.push(`- Downloads: ${meta.downloads.toLocaleString()}/week, ${meta.packageAge} days old`);
70
+ parts.push(`- Maintainers: ${meta.maintainerCount}, License: ${meta.hasLicense ? "Yes" : "No"}`);
71
+ }
72
+ // Script results
73
+ if (report.analyzers.script) {
74
+ const script = report.analyzers.script;
75
+ if (script.hasSuspiciousScripts) {
76
+ parts.push(`- Suspicious scripts detected: ${script.suspiciousScripts.join(", ")}`);
77
+ }
78
+ }
79
+ // Heuristic results
80
+ if (report.analyzers.heuristic) {
81
+ const heuristic = report.analyzers.heuristic;
82
+ if (heuristic.suspiciousPatterns.length > 0) {
83
+ parts.push(`- Pattern warnings: ${heuristic.suspiciousPatterns.join(", ")}`);
84
+ }
85
+ }
86
+ // Warnings
87
+ if (report.warnings.length > 0) {
88
+ parts.push(`- Warnings: ${report.warnings.map((w) => w.message).join("; ")}`);
89
+ }
90
+ return parts.join("\n");
91
+ }
92
+ //# sourceMappingURL=aiAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiAnalyzer.js","sourceRoot":"","sources":["../../src/scanner/aiAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Config, RiskReport } from "../types.js";
2
+ /**
3
+ * Main orchestrator that runs all analysis layers and combines results
4
+ */
5
+ export declare function analyzePackage(packageName: string, config: Config): Promise<RiskReport>;
@@ -0,0 +1,155 @@
1
+ import { enhanceWithAI } from "./aiAnalyzer.js";
2
+ import { analyzeWithAudit } from "./auditAnalyzer.js";
3
+ import { analyzeHeuristics } from "./heuristicAnalyzer.js";
4
+ import { analyzeMetadata } from "./metadataAnalyzer.js";
5
+ import { analyzeScripts } from "./scriptAnalyzer.js";
6
+ /**
7
+ * Main orchestrator that runs all analysis layers and combines results
8
+ */
9
+ export async function analyzePackage(packageName, config) {
10
+ // Run all analyzers in parallel for performance
11
+ const [auditResult, metadataResult, scriptResult] = await Promise.all([
12
+ analyzeWithAudit(packageName).catch(() => null), // Gracefully handle failures
13
+ analyzeMetadata(packageName).catch(() => null),
14
+ analyzeScripts(packageName).catch(() => null),
15
+ ]);
16
+ // Heuristic analyzer is synchronous
17
+ const heuristicResult = analyzeHeuristics(packageName);
18
+ // Calculate weighted risk score
19
+ // Weights: audit=40%, metadata=25%, scripts=25%, heuristics=10%
20
+ let totalScore = 0;
21
+ let totalWeight = 0;
22
+ if (auditResult) {
23
+ // Only count audit if there's actual package data
24
+ // If no vulnerabilities but also no package, don't count it as "safe"
25
+ if (auditResult.vulnerabilityCount > 0 ||
26
+ (metadataResult?.downloads ?? 0) > 0) {
27
+ totalScore += auditResult.riskScore * 0.4;
28
+ totalWeight += 0.4;
29
+ }
30
+ }
31
+ if (metadataResult) {
32
+ totalScore += metadataResult.riskScore * 0.25;
33
+ totalWeight += 0.25;
34
+ }
35
+ if (scriptResult) {
36
+ // Only count scripts if the package appears to exist
37
+ if (scriptResult.hasSuspiciousScripts ||
38
+ (metadataResult?.downloads ?? 0) > 0) {
39
+ totalScore += scriptResult.riskScore * 0.25;
40
+ totalWeight += 0.25;
41
+ }
42
+ }
43
+ if (heuristicResult) {
44
+ totalScore += heuristicResult.riskScore * 0.1;
45
+ totalWeight += 0.1;
46
+ }
47
+ // Normalize score based on available analyzers
48
+ // If metadata shows a risky package (high score, low downloads), ensure minimum risk
49
+ const normalizedScore = totalWeight > 0 ? Math.round(totalScore / totalWeight) : 5;
50
+ // Apply minimum risk for packages with concerning metadata
51
+ let riskScore = normalizedScore;
52
+ if (metadataResult &&
53
+ metadataResult.riskScore >= 7 &&
54
+ (metadataResult.downloads < 100 || metadataResult.maintainerCount === 0)) {
55
+ // Ensure packages with terrible metadata get at least medium risk
56
+ riskScore = Math.max(riskScore, 6);
57
+ }
58
+ // Determine risk level
59
+ const riskLevel = getRiskLevel(riskScore);
60
+ // Collect all warnings
61
+ const warnings = [];
62
+ if (auditResult && auditResult.vulnerabilityCount > 0) {
63
+ warnings.push({
64
+ severity: "critical",
65
+ message: `Found ${auditResult.vulnerabilityCount} vulnerabilities (${auditResult.criticalCount} critical, ${auditResult.highCount} high)`,
66
+ source: "audit",
67
+ });
68
+ }
69
+ if (metadataResult) {
70
+ if (metadataResult.downloads < 100) {
71
+ warnings.push({
72
+ severity: "medium",
73
+ message: `Low weekly downloads (${metadataResult.downloads})`,
74
+ source: "metadata",
75
+ });
76
+ }
77
+ if (metadataResult.maintainerCount === 0) {
78
+ warnings.push({
79
+ severity: "high",
80
+ message: "Package has no maintainers",
81
+ source: "metadata",
82
+ });
83
+ }
84
+ if (!metadataResult.hasLicense) {
85
+ warnings.push({
86
+ severity: "medium",
87
+ message: "Package has no license",
88
+ source: "metadata",
89
+ });
90
+ }
91
+ }
92
+ if (scriptResult?.hasSuspiciousScripts) {
93
+ warnings.push({
94
+ severity: "high",
95
+ message: `Suspicious scripts detected: ${scriptResult.suspiciousScripts.join(", ")}`,
96
+ source: "script",
97
+ });
98
+ }
99
+ if (heuristicResult && heuristicResult.suspiciousPatterns.length > 0) {
100
+ warnings.push({
101
+ severity: "medium",
102
+ message: `Pattern warnings: ${heuristicResult.suspiciousPatterns.join(", ")}`,
103
+ source: "heuristic",
104
+ });
105
+ }
106
+ // Determine recommendation
107
+ const recommendation = getRecommendation(riskLevel, warnings.length);
108
+ // Build initial report
109
+ let report = {
110
+ packageName,
111
+ version: metadataResult?.version ?? "unknown",
112
+ riskScore,
113
+ riskLevel,
114
+ warnings,
115
+ recommendation,
116
+ analyzers: {
117
+ audit: auditResult ?? undefined,
118
+ metadata: metadataResult ?? undefined,
119
+ script: scriptResult ?? undefined,
120
+ heuristic: heuristicResult ?? undefined,
121
+ },
122
+ analyzedAt: new Date(),
123
+ };
124
+ // Optional AI enhancement
125
+ if (config.anthropicApiKey) {
126
+ report = await enhanceWithAI(report, config.anthropicApiKey);
127
+ }
128
+ return report;
129
+ }
130
+ /**
131
+ * Map risk score to risk level
132
+ */
133
+ function getRiskLevel(score) {
134
+ if (score >= 7)
135
+ return "dangerous";
136
+ if (score >= 4)
137
+ return "caution";
138
+ return "safe";
139
+ }
140
+ /**
141
+ * Generate recommendation based on risk level and warnings
142
+ */
143
+ function getRecommendation(level, warningCount) {
144
+ if (level === "dangerous") {
145
+ return "❌ DO NOT INSTALL - Critical security risks detected";
146
+ }
147
+ if (level === "caution") {
148
+ return "⚠️ PROCEED WITH CAUTION - Review security warnings carefully";
149
+ }
150
+ if (warningCount > 0) {
151
+ return "✓ MOSTLY SAFE - Minor concerns detected";
152
+ }
153
+ return "✅ SAFE - No significant security concerns detected";
154
+ }
155
+ //# sourceMappingURL=analyzePackage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzePackage.js","sourceRoot":"","sources":["../../src/scanner/analyzePackage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AuditResult } from "../types.js";
2
+ /**
3
+ * Analyze a package using npm audit
4
+ * Note: This creates a temporary package.json to audit a specific package
5
+ */
6
+ export declare function analyzeWithAudit(packageName: string): Promise<AuditResult>;
7
+ /**
8
+ * Analyze a specific package by creating a temporary audit
9
+ * This is more accurate for checking a package before installation
10
+ */
11
+ export declare function analyzePackageAudit(packageName: string, version?: string): Promise<AuditResult>;
@@ -0,0 +1,113 @@
1
+ import { execa } from "execa";
2
+ /**
3
+ * Analyze a package using npm audit
4
+ * Note: This creates a temporary package.json to audit a specific package
5
+ */
6
+ export async function analyzeWithAudit(packageName) {
7
+ try {
8
+ // Try to run npm audit on the package
9
+ // We'll audit in the current context or create a minimal check
10
+ const { stdout } = await execa("npm", ["audit", "--json"], {
11
+ reject: false, // Don't throw on non-zero exit (audit returns exit code 1 if vulnerabilities found)
12
+ });
13
+ const auditData = JSON.parse(stdout);
14
+ return parseAuditOutput(auditData, packageName);
15
+ }
16
+ catch (error) {
17
+ // If audit fails, return empty result
18
+ return createEmptyAuditResult();
19
+ }
20
+ }
21
+ /**
22
+ * Parse npm audit JSON output
23
+ */
24
+ function parseAuditOutput(auditData, packageName) {
25
+ if (!auditData || typeof auditData !== "object") {
26
+ return createEmptyAuditResult();
27
+ }
28
+ // npm audit JSON format has vulnerabilities object
29
+ const vulnerabilities = auditData.vulnerabilities || {};
30
+ const metadata = auditData.metadata || {};
31
+ // Count vulnerabilities by severity
32
+ const vulnerabilitiesArray = [];
33
+ let criticalCount = 0;
34
+ let highCount = 0;
35
+ let moderateCount = 0;
36
+ let lowCount = 0;
37
+ // Parse vulnerabilities
38
+ for (const [vulnName, vulnData] of Object.entries(vulnerabilities)) {
39
+ const severity = (vulnData.severity || "moderate").toLowerCase();
40
+ // Count by severity
41
+ if (severity === "critical")
42
+ criticalCount++;
43
+ else if (severity === "high")
44
+ highCount++;
45
+ else if (severity === "moderate")
46
+ moderateCount++;
47
+ else if (severity === "low")
48
+ lowCount++;
49
+ // Extract via information
50
+ const via = Array.isArray(vulnData.via)
51
+ ? vulnData.via
52
+ .map((v) => (typeof v === "string" ? v : v.title || ""))
53
+ .filter(Boolean)
54
+ .join(", ")
55
+ : "Unknown";
56
+ vulnerabilitiesArray.push({
57
+ name: vulnName,
58
+ severity: severity,
59
+ via,
60
+ });
61
+ }
62
+ const vulnerabilityCount = criticalCount + highCount + moderateCount + lowCount;
63
+ // Calculate risk score based on vulnerability counts
64
+ // Critical = 10, High = 5, Moderate = 2, Low = 1
65
+ const riskScore = Math.min(10, criticalCount * 10 + highCount * 5 + moderateCount * 2 + lowCount * 1);
66
+ return {
67
+ vulnerabilityCount,
68
+ criticalCount,
69
+ highCount,
70
+ moderateCount,
71
+ lowCount,
72
+ vulnerabilities: vulnerabilitiesArray,
73
+ riskScore,
74
+ };
75
+ }
76
+ /**
77
+ * Create an empty audit result (no vulnerabilities found)
78
+ */
79
+ function createEmptyAuditResult() {
80
+ return {
81
+ vulnerabilityCount: 0,
82
+ criticalCount: 0,
83
+ highCount: 0,
84
+ moderateCount: 0,
85
+ lowCount: 0,
86
+ vulnerabilities: [],
87
+ riskScore: 0,
88
+ };
89
+ }
90
+ /**
91
+ * Analyze a specific package by creating a temporary audit
92
+ * This is more accurate for checking a package before installation
93
+ */
94
+ export async function analyzePackageAudit(packageName, version = "latest") {
95
+ try {
96
+ // Get package info to check for known vulnerabilities
97
+ // We can use npm view to get vulnerability information
98
+ const { stdout } = await execa("npm", [
99
+ "view",
100
+ `${packageName}@${version}`,
101
+ "--json",
102
+ ]);
103
+ const packageData = JSON.parse(stdout);
104
+ // Check if the package has any known security issues
105
+ // This is a simplified check - in production, you'd want to cross-reference with vulnerability databases
106
+ return createEmptyAuditResult();
107
+ }
108
+ catch (error) {
109
+ // Package not found or other error
110
+ return createEmptyAuditResult();
111
+ }
112
+ }
113
+ //# sourceMappingURL=auditAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auditAnalyzer.js","sourceRoot":"","sources":["../../src/scanner/auditAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { HeuristicScore } from "../types.js";
2
+ /**
3
+ * Analyze package name using heuristic patterns
4
+ */
5
+ export declare function analyzeHeuristics(packageName: string): HeuristicScore;