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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Georges Fouejio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# 🔒 safe-pkg
|
|
2
|
+
|
|
3
|
+
**Security-first package installer with multi-layer vulnerability analysis**
|
|
4
|
+
|
|
5
|
+
`safe-pkg` is a drop-in replacement for `npm install`, `yarn add`, and `pnpm add` that analyzes packages for security risks **before** installing them. It combines industry-standard vulnerability scanning with intelligent heuristics and optional AI enhancement to protect your projects from malicious packages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🔍 **4-Layer Security Analysis**
|
|
12
|
+
- NPM Audit integration for known vulnerabilities
|
|
13
|
+
- Package metadata analysis (downloads, age, maintainers)
|
|
14
|
+
- Suspicious script detection (postinstall hooks, dangerous commands)
|
|
15
|
+
- Heuristic pattern matching (typosquatting, malware signatures)
|
|
16
|
+
|
|
17
|
+
- 🤖 **Optional AI Enhancement**
|
|
18
|
+
- Natural language security insights powered by Claude
|
|
19
|
+
- Contextual risk explanations
|
|
20
|
+
- Smart recommendations
|
|
21
|
+
|
|
22
|
+
- 🎨 **Beautiful Terminal UI**
|
|
23
|
+
- Color-coded risk levels (🟢 Safe / 🟡 Caution / 🔴 Dangerous)
|
|
24
|
+
- Detailed security reports
|
|
25
|
+
- Interactive confirmation prompts
|
|
26
|
+
|
|
27
|
+
- 📦 **Universal Package Manager Support**
|
|
28
|
+
- Auto-detects npm, yarn, or pnpm
|
|
29
|
+
- Seamlessly forwards commands to your package manager
|
|
30
|
+
- Works with existing workflows
|
|
31
|
+
|
|
32
|
+
- 📊 **Project Scanning**
|
|
33
|
+
- Analyze all existing dependencies at once
|
|
34
|
+
- Identify risky packages in your codebase
|
|
35
|
+
- Continuous security monitoring
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 🚀 Installation
|
|
40
|
+
|
|
41
|
+
### Global Installation (Recommended)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Using npm
|
|
45
|
+
npm install -g safe-pkg
|
|
46
|
+
|
|
47
|
+
# Using pnpm
|
|
48
|
+
pnpm add -g safe-pkg
|
|
49
|
+
|
|
50
|
+
# Using yarn
|
|
51
|
+
yarn global add safe-pkg
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Local Development
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/joker7blue/safe-install.git
|
|
58
|
+
cd safe-install
|
|
59
|
+
pnpm install
|
|
60
|
+
pnpm build
|
|
61
|
+
pnpm link --global
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 📖 Usage
|
|
67
|
+
|
|
68
|
+
### Install Packages with Security Analysis
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Analyze and install a single package
|
|
72
|
+
safe-pkg install express
|
|
73
|
+
|
|
74
|
+
# Install multiple packages
|
|
75
|
+
safe-pkg install react vue lodash
|
|
76
|
+
|
|
77
|
+
# Save to devDependencies
|
|
78
|
+
safe-pkg install -D typescript eslint
|
|
79
|
+
|
|
80
|
+
# Skip analysis (direct install)
|
|
81
|
+
safe-pkg install axios --skip-analysis
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Check a Package Without Installing
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Analyze a package before deciding to install
|
|
88
|
+
safe-pkg check suspicious-package-name
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Scan Existing Project Dependencies
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Scan production dependencies
|
|
95
|
+
safe-pkg scan
|
|
96
|
+
|
|
97
|
+
# Include devDependencies
|
|
98
|
+
safe-pkg scan --dev
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Help & Options
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
safe-pkg --help
|
|
105
|
+
safe-pkg install --help
|
|
106
|
+
safe-pkg scan --help
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🔐 Security Layers Explained
|
|
112
|
+
|
|
113
|
+
### 1. **NPM Audit** (40% weight)
|
|
114
|
+
- Checks for known CVEs and security advisories
|
|
115
|
+
- Identifies critical, high, moderate, and low severity vulnerabilities
|
|
116
|
+
- Uses official npm audit database
|
|
117
|
+
|
|
118
|
+
### 2. **Metadata Analysis** (25% weight)
|
|
119
|
+
- Weekly download counts (flags packages with <100 downloads)
|
|
120
|
+
- Package age (warns about brand new or abandoned packages)
|
|
121
|
+
- Maintainer count (flags unmaintained packages)
|
|
122
|
+
- License verification
|
|
123
|
+
|
|
124
|
+
### 3. **Script Detection** (25% weight)
|
|
125
|
+
- Scans package.json scripts for dangerous commands
|
|
126
|
+
- Detects postinstall/preinstall hooks
|
|
127
|
+
- Identifies network calls, file system modifications, eval usage
|
|
128
|
+
- Flags obfuscated code patterns
|
|
129
|
+
|
|
130
|
+
### 4. **Heuristic Analysis** (10% weight)
|
|
131
|
+
- Typosquatting detection (Levenshtein distance from popular packages)
|
|
132
|
+
- Suspicious keywords ("hack", "crack", "free-premium")
|
|
133
|
+
- Name pattern analysis (excessive hyphens, random characters)
|
|
134
|
+
- Known malware signatures
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 🤖 AI Enhancement (Optional)
|
|
139
|
+
|
|
140
|
+
Enable AI-powered insights by setting your Anthropic API key:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Set environment variable
|
|
144
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
145
|
+
|
|
146
|
+
# Or create a config file
|
|
147
|
+
echo '{"anthropicApiKey": "sk-ant-..."}' > ~/.safe-pkgrc
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The AI layer provides:
|
|
151
|
+
- Natural language security explanations
|
|
152
|
+
- Context-aware risk assessment
|
|
153
|
+
- Actionable recommendations
|
|
154
|
+
- Human-readable insights
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 📊 Example Output
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
$ safe-pkg install tiny-package-that-doesnt-exist-12345
|
|
162
|
+
|
|
163
|
+
ℹ Using package manager: pnpm
|
|
164
|
+
|
|
165
|
+
🔒 Security Analysis
|
|
166
|
+
====================
|
|
167
|
+
|
|
168
|
+
ℹ Analyzing tiny-package-that-doesnt-exist-12345...
|
|
169
|
+
|
|
170
|
+
================================================================================
|
|
171
|
+
📦 tiny-package-that-doesnt-exist-12345 (unknown)
|
|
172
|
+
================================================================================
|
|
173
|
+
|
|
174
|
+
Risk Score: 6/10
|
|
175
|
+
Risk Level: CAUTION
|
|
176
|
+
|
|
177
|
+
Recommendation:
|
|
178
|
+
⚠️ PROCEED WITH CAUTION - Review security warnings carefully
|
|
179
|
+
|
|
180
|
+
Warnings: (4)
|
|
181
|
+
🟡 MEDIUM - Low weekly downloads (0)
|
|
182
|
+
Source: metadata
|
|
183
|
+
🟠 HIGH - Package has no maintainers
|
|
184
|
+
Source: metadata
|
|
185
|
+
🟡 MEDIUM - Package has no license
|
|
186
|
+
Source: metadata
|
|
187
|
+
🟡 MEDIUM - Pattern warnings: Excessive hyphens (5)
|
|
188
|
+
Source: heuristic
|
|
189
|
+
|
|
190
|
+
Analysis Details:
|
|
191
|
+
Audit: 0 vulnerabilities - Score: 0/10
|
|
192
|
+
Metadata: 0 weekly downloads, 0 days old - Score: 8/10
|
|
193
|
+
Maintainers: 0, License: No
|
|
194
|
+
Scripts: Clean - Score: 0/10
|
|
195
|
+
Heuristics: Clean - Score: 1/10
|
|
196
|
+
Patterns: Excessive hyphens (5)
|
|
197
|
+
|
|
198
|
+
⚠️ Package "tiny-package-that-doesnt-exist-12345" has warnings (score: 6/10). Continue? › (y/N)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## ⚙️ Configuration
|
|
204
|
+
|
|
205
|
+
Create a `.safe-pkgrc` file in your project root or home directory:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"anthropicApiKey": "sk-ant-...",
|
|
210
|
+
"riskThreshold": 7,
|
|
211
|
+
"autoConfirm": false
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Options:**
|
|
216
|
+
- `anthropicApiKey` - Your Anthropic API key for AI insights
|
|
217
|
+
- `riskThreshold` - Minimum risk score to trigger warnings (default: 7)
|
|
218
|
+
- `autoConfirm` - Skip confirmation for safe packages (default: false)
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 🛠️ Development
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Clone repository
|
|
226
|
+
git clone https://github.com/joker7blue/safe-install.git
|
|
227
|
+
cd safe-install
|
|
228
|
+
|
|
229
|
+
# Install dependencies
|
|
230
|
+
pnpm install
|
|
231
|
+
|
|
232
|
+
# Build TypeScript
|
|
233
|
+
pnpm build
|
|
234
|
+
|
|
235
|
+
# Run linter
|
|
236
|
+
pnpm check
|
|
237
|
+
|
|
238
|
+
# Run tests
|
|
239
|
+
pnpm test
|
|
240
|
+
|
|
241
|
+
# Link globally for testing
|
|
242
|
+
pnpm link --global
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Project Structure
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
src/
|
|
249
|
+
├── cli/ # Command-line interface
|
|
250
|
+
├── config/ # Configuration loader
|
|
251
|
+
├── detector/ # Package manager detection
|
|
252
|
+
├── executor/ # Command execution
|
|
253
|
+
├── scanner/ # Security analyzers
|
|
254
|
+
│ ├── auditAnalyzer.ts
|
|
255
|
+
│ ├── metadataAnalyzer.ts
|
|
256
|
+
│ ├── scriptAnalyzer.ts
|
|
257
|
+
│ ├── heuristicAnalyzer.ts
|
|
258
|
+
│ ├── aiAnalyzer.ts
|
|
259
|
+
│ └── analyzePackage.ts
|
|
260
|
+
├── scanner-project/ # Project dependency scanning
|
|
261
|
+
├── ui/ # Terminal UI components
|
|
262
|
+
└── types.ts # TypeScript definitions
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🤝 Contributing
|
|
268
|
+
|
|
269
|
+
Contributions are welcome! Please:
|
|
270
|
+
|
|
271
|
+
1. Fork the repository
|
|
272
|
+
2. Create a feature branch (`git checkout -b feat/amazing-feature`)
|
|
273
|
+
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
274
|
+
4. Push to the branch (`git push origin feat/amazing-feature`)
|
|
275
|
+
5. Open a Pull Request
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 📝 License
|
|
280
|
+
|
|
281
|
+
MIT © Georges Fouejio
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 🙏 Acknowledgments
|
|
286
|
+
|
|
287
|
+
- Built with [TypeScript](https://www.typescriptlang.org/)
|
|
288
|
+
- Styled with [Chalk](https://github.com/chalk/chalk)
|
|
289
|
+
- CLI powered by [Commander.js](https://github.com/tj/commander.js)
|
|
290
|
+
- AI enhancement via [Anthropic Claude](https://www.anthropic.com/)
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 🔗 Links
|
|
295
|
+
|
|
296
|
+
- [GitHub Repository](https://github.com/joker7blue/safe-install)
|
|
297
|
+
- [Issue Tracker](https://github.com/joker7blue/safe-install/issues)
|
|
298
|
+
- [NPM Package](https://www.npmjs.com/package/safe-pkg) *(coming soon)*
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## ⚠️ Disclaimer
|
|
303
|
+
|
|
304
|
+
While `safe-pkg` provides multiple layers of security analysis, no automated tool can guarantee 100% protection against all security threats. Always review package source code for critical applications and report suspicious packages to the npm security team.
|
package/dist/.DS_Store
ADDED
|
Binary file
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { loadConfig } from "../config/loadConfig.js";
|
|
4
|
+
import { detectPackageManager } from "../detector/detectPackageManager.js";
|
|
5
|
+
import { runInstallCommand } from "../executor/runCommand.js";
|
|
6
|
+
import { scanProject } from "../scanner-project/scanProject.js";
|
|
7
|
+
import { analyzePackage } from "../scanner/analyzePackage.js";
|
|
8
|
+
import { logError, logHeader, logNewline, logStep, logSuccess, } from "../ui/logger.js";
|
|
9
|
+
import { askUserConfirmation } from "../ui/promptUser.js";
|
|
10
|
+
import { displayRiskReport } from "../ui/riskReporter.js";
|
|
11
|
+
import { parseArguments } from "./parser.js";
|
|
12
|
+
/**
|
|
13
|
+
* Main CLI orchestrator
|
|
14
|
+
*/
|
|
15
|
+
export async function main() {
|
|
16
|
+
try {
|
|
17
|
+
// Parse command line arguments
|
|
18
|
+
const command = parseArguments(process.argv);
|
|
19
|
+
// Load configuration
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
// Handle different commands
|
|
22
|
+
if (command.action === "scan") {
|
|
23
|
+
await handleScanCommand(config, command.options);
|
|
24
|
+
}
|
|
25
|
+
else if (command.action === "check") {
|
|
26
|
+
await handleCheckCommand(command.packages[0] || "", config);
|
|
27
|
+
}
|
|
28
|
+
else if (command.action === "install") {
|
|
29
|
+
await handleInstallCommand(command.packages, config, command.options);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
logError("Unknown command");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
logError(`Fatal error: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Handle scan command - analyze existing project dependencies
|
|
43
|
+
*/
|
|
44
|
+
async function handleScanCommand(config, options) {
|
|
45
|
+
logHeader("🔍 Scanning Project Dependencies");
|
|
46
|
+
logNewline();
|
|
47
|
+
const result = await scanProject(process.cwd(), config, Boolean(options.dev));
|
|
48
|
+
// Display summary
|
|
49
|
+
logNewline();
|
|
50
|
+
logHeader("Scan Results");
|
|
51
|
+
console.log(`Total packages: ${chalk.bold(result.totalPackages)}`);
|
|
52
|
+
console.log(`${chalk.green("✓")} Safe: ${chalk.green.bold(result.summary.safe)}`);
|
|
53
|
+
console.log(`${chalk.yellow("⚠")} Caution: ${chalk.yellow.bold(result.summary.caution)}`);
|
|
54
|
+
console.log(`${chalk.red("✖")} Dangerous: ${chalk.red.bold(result.summary.dangerous)}`);
|
|
55
|
+
// Show detailed reports for risky packages
|
|
56
|
+
const riskyPackages = result.reports.filter((r) => r.riskLevel !== "safe");
|
|
57
|
+
if (riskyPackages.length > 0) {
|
|
58
|
+
logNewline();
|
|
59
|
+
logHeader("⚠️ Packages Requiring Attention");
|
|
60
|
+
for (const report of riskyPackages) {
|
|
61
|
+
displayRiskReport(report);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
logNewline();
|
|
66
|
+
logSuccess("All packages are safe! ✨");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Handle check command - analyze a single package
|
|
71
|
+
*/
|
|
72
|
+
async function handleCheckCommand(packageName, config) {
|
|
73
|
+
if (!packageName) {
|
|
74
|
+
logError("Package name required for check command");
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
logHeader(`🔍 Analyzing ${packageName}`);
|
|
78
|
+
logNewline();
|
|
79
|
+
const report = await analyzePackage(packageName, config);
|
|
80
|
+
displayRiskReport(report);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Handle install command - analyze and install packages
|
|
84
|
+
*/
|
|
85
|
+
async function handleInstallCommand(packages, config, options) {
|
|
86
|
+
if (packages.length === 0) {
|
|
87
|
+
logError("No packages specified");
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
// Detect package manager
|
|
91
|
+
const packageManager = (await detectPackageManager(process.cwd())) || "npm";
|
|
92
|
+
logStep(`Using package manager: ${chalk.cyan(packageManager)}`);
|
|
93
|
+
logNewline();
|
|
94
|
+
// Skip analysis if requested
|
|
95
|
+
if (options.skipAnalysis) {
|
|
96
|
+
await runInstallCommand(packageManager, packages, options);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Analyze each package
|
|
100
|
+
logHeader("🔒 Security Analysis");
|
|
101
|
+
logNewline();
|
|
102
|
+
const packagesToInstall = [];
|
|
103
|
+
for (const packageName of packages) {
|
|
104
|
+
logStep(`Analyzing ${chalk.cyan(packageName)}...`);
|
|
105
|
+
const report = await analyzePackage(packageName, config);
|
|
106
|
+
displayRiskReport(report);
|
|
107
|
+
logNewline();
|
|
108
|
+
// Check if user approves
|
|
109
|
+
const shouldInstall = config.autoConfirm && report.riskLevel === "safe"
|
|
110
|
+
? true
|
|
111
|
+
: await askUserConfirmation(packageName, report.riskLevel, report.riskScore);
|
|
112
|
+
if (shouldInstall) {
|
|
113
|
+
packagesToInstall.push(packageName);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
logError(`Skipping ${packageName}`);
|
|
117
|
+
}
|
|
118
|
+
logNewline();
|
|
119
|
+
}
|
|
120
|
+
// Install approved packages
|
|
121
|
+
if (packagesToInstall.length > 0) {
|
|
122
|
+
logHeader("📦 Installing Packages");
|
|
123
|
+
logNewline();
|
|
124
|
+
await runInstallCommand(packageManager, packagesToInstall, options);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
logError("No packages approved for installation");
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Run CLI if executed directly
|
|
132
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
133
|
+
main();
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* Parse CLI arguments and return structured command config
|
|
4
|
+
*/
|
|
5
|
+
export function parseArguments(argv) {
|
|
6
|
+
const program = new Command();
|
|
7
|
+
let commandConfig = {
|
|
8
|
+
action: "help",
|
|
9
|
+
packages: [],
|
|
10
|
+
options: {},
|
|
11
|
+
};
|
|
12
|
+
program
|
|
13
|
+
.name("safe-pkg")
|
|
14
|
+
.description("Secure package installer with built-in security analysis")
|
|
15
|
+
.version("0.0.1");
|
|
16
|
+
// Install command (default action)
|
|
17
|
+
program
|
|
18
|
+
.command("install [packages...]", { isDefault: true })
|
|
19
|
+
.alias("i")
|
|
20
|
+
.alias("add")
|
|
21
|
+
.description("Install packages after security analysis")
|
|
22
|
+
.option("-D, --save-dev", "Save to devDependencies")
|
|
23
|
+
.option("-g, --global", "Install globally")
|
|
24
|
+
.option("--skip-analysis", "Skip security analysis")
|
|
25
|
+
.option("--auto-yes", "Automatically proceed with safe packages")
|
|
26
|
+
.action((packages, options) => {
|
|
27
|
+
commandConfig = {
|
|
28
|
+
action: "install",
|
|
29
|
+
packages,
|
|
30
|
+
options,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
// Scan command
|
|
34
|
+
program
|
|
35
|
+
.command("scan")
|
|
36
|
+
.description("Scan existing project dependencies")
|
|
37
|
+
.option("--dev", "Include devDependencies")
|
|
38
|
+
.option("--json", "Output as JSON")
|
|
39
|
+
.action((options) => {
|
|
40
|
+
commandConfig = {
|
|
41
|
+
action: "scan",
|
|
42
|
+
packages: [],
|
|
43
|
+
options,
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
// Check command
|
|
47
|
+
program
|
|
48
|
+
.command("check <package>")
|
|
49
|
+
.description("Check a single package without installing")
|
|
50
|
+
.action((packageName) => {
|
|
51
|
+
commandConfig = {
|
|
52
|
+
action: "check",
|
|
53
|
+
packages: [packageName],
|
|
54
|
+
options: {},
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
// Parse argv
|
|
58
|
+
program.parse(argv);
|
|
59
|
+
return commandConfig;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/cli/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc;IAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,IAAI,aAAa,GAAkB;QAClC,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE;KACX,CAAC;IAEF,OAAO;SACL,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,0DAA0D,CAAC;SACvE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnB,mCAAmC;IACnC,OAAO;SACL,OAAO,CAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;SACrD,KAAK,CAAC,GAAG,CAAC;SACV,KAAK,CAAC,KAAK,CAAC;SACZ,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,yBAAyB,CAAC;SACnD,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC;SAC1C,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;SACnD,MAAM,CAAC,YAAY,EAAE,0CAA0C,CAAC;SAChE,MAAM,CAAC,CAAC,QAAkB,EAAE,OAAgC,EAAE,EAAE;QAChE,aAAa,GAAG;YACf,MAAM,EAAE,SAAS;YACjB,QAAQ;YACR,OAAO;SACP,CAAC;IACH,CAAC,CAAC,CAAC;IAEJ,eAAe;IACf,OAAO;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,OAAO,EAAE,yBAAyB,CAAC;SAC1C,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,CAAC,OAAgC,EAAE,EAAE;QAC5C,aAAa,GAAG;YACf,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,EAAE;YACZ,OAAO;SACP,CAAC;IACH,CAAC,CAAC,CAAC;IAEJ,gBAAgB;IAChB,OAAO;SACL,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,CAAC,WAAmB,EAAE,EAAE;QAC/B,aAAa,GAAG;YACf,MAAM,EAAE,OAAO;YACf,QAAQ,EAAE,CAAC,WAAW,CAAC;YACvB,OAAO,EAAE,EAAE;SACX,CAAC;IACH,CAAC,CAAC,CAAC;IAEJ,aAAa;IACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpB,OAAO,aAAa,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./loadConfig.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/**
|
|
5
|
+
* Load configuration from environment variables or config file
|
|
6
|
+
*/
|
|
7
|
+
export function loadConfig() {
|
|
8
|
+
// Default config
|
|
9
|
+
const config = {
|
|
10
|
+
riskThreshold: 7,
|
|
11
|
+
autoConfirm: false,
|
|
12
|
+
};
|
|
13
|
+
// Check for API key in environment variable
|
|
14
|
+
const envApiKey = process.env.ANTHROPIC_API_KEY;
|
|
15
|
+
if (envApiKey) {
|
|
16
|
+
config.anthropicApiKey = envApiKey;
|
|
17
|
+
}
|
|
18
|
+
// Try to load from config file if no env var
|
|
19
|
+
if (!config.anthropicApiKey) {
|
|
20
|
+
const configFromFile = loadConfigFile();
|
|
21
|
+
if (configFromFile.anthropicApiKey) {
|
|
22
|
+
config.anthropicApiKey = configFromFile.anthropicApiKey;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load configuration from file (.safe-pkgrc or ~/.safe-pkgrc)
|
|
29
|
+
*/
|
|
30
|
+
function loadConfigFile() {
|
|
31
|
+
const configPaths = [
|
|
32
|
+
join(process.cwd(), ".safe-pkgrc"),
|
|
33
|
+
join(homedir(), ".safe-pkgrc"),
|
|
34
|
+
];
|
|
35
|
+
for (const configPath of configPaths) {
|
|
36
|
+
if (existsSync(configPath)) {
|
|
37
|
+
try {
|
|
38
|
+
const content = readFileSync(configPath, "utf-8");
|
|
39
|
+
const config = JSON.parse(content);
|
|
40
|
+
return config;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// Invalid JSON or read error, skip to next file
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=loadConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../src/config/loadConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,iBAAiB;IACjB,MAAM,MAAM,GAAW;QACtB,aAAa,EAAE,CAAC;QAChB,WAAW,EAAE,KAAK;KAClB,CAAC;IAEF,4CAA4C;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAChD,IAAI,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,eAAe,GAAG,SAAS,CAAC;IACpC,CAAC;IAED,6CAA6C;IAC7C,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAG,cAAc,EAAE,CAAC;QACxC,IAAI,cAAc,CAAC,eAAe,EAAE,CAAC;YACpC,MAAM,CAAC,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC;QACzD,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACtB,MAAM,WAAW,GAAG;QACnB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC;QAClC,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC;KAC9B,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACtC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACJ,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACnC,OAAO,MAAyB,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,gDAAgD;YACjD,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,EAAE,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PackageManager } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Detect package manager from lock files in the given directory
|
|
4
|
+
* Priority: pnpm > yarn > npm
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectPackageManager(cwd?: string): Promise<PackageManager>;
|
|
7
|
+
/**
|
|
8
|
+
* Check if a specific package manager is available
|
|
9
|
+
*/
|
|
10
|
+
export declare function isPackageManagerAvailable(manager: PackageManager): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Get the version of a package manager
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPackageManagerVersion(manager: PackageManager): Promise<string | null>;
|