@vibecheckai/cli 3.2.2 → 3.2.4
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/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -121
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +117 -28
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +23 -14
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +72 -1
- package/bin/runners/lib/agent-firewall/interceptor/base.js +2 -2
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +6 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +34 -3
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +29 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +12 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +21 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/analyzers.js +606 -325
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +213 -213
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/interactive-menu.js +1496 -1496
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report-output.js +187 -187
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/scan-output.js +525 -190
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/status-output.js +253 -253
- package/bin/runners/lib/terminal-ui.js +351 -271
- package/bin/runners/lib/upsell.js +510 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +8 -0
- package/bin/runners/runReality.js +14 -0
- package/bin/runners/runScan.js +17 -1
- package/bin/runners/runTruth.js +15 -3
- package/mcp-server/tier-auth.js +4 -4
- package/mcp-server/tools/index.js +72 -72
- package/package.json +1 -1
|
@@ -1,325 +1,325 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dependencies Diagnostics Module
|
|
3
|
-
*
|
|
4
|
-
* Checks for outdated packages, vulnerabilities, and dependency health
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const { execSync } = require('child_process');
|
|
10
|
-
const { SEVERITY, CATEGORY, FIX_TYPE } = require('../types');
|
|
11
|
-
|
|
12
|
-
const MODULE_ID = 'dependencies';
|
|
13
|
-
|
|
14
|
-
function createDiagnostics(projectPath) {
|
|
15
|
-
return [
|
|
16
|
-
{
|
|
17
|
-
id: `${MODULE_ID}.outdated`,
|
|
18
|
-
name: 'Outdated Packages',
|
|
19
|
-
category: CATEGORY.DEPENDENCIES,
|
|
20
|
-
parallel: true,
|
|
21
|
-
check: async () => {
|
|
22
|
-
try {
|
|
23
|
-
// Try npm outdated (returns non-zero if outdated packages exist)
|
|
24
|
-
const result = execSync('npm outdated --json 2>/dev/null || echo "{}"', {
|
|
25
|
-
cwd: projectPath,
|
|
26
|
-
encoding: 'utf8',
|
|
27
|
-
timeout: 30000,
|
|
28
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
-
}).trim();
|
|
30
|
-
|
|
31
|
-
const outdated = JSON.parse(result || '{}');
|
|
32
|
-
const count = Object.keys(outdated).length;
|
|
33
|
-
|
|
34
|
-
const metadata = { count, packages: outdated };
|
|
35
|
-
|
|
36
|
-
// Check for major version updates
|
|
37
|
-
const majorUpdates = Object.entries(outdated).filter(([_, info]) => {
|
|
38
|
-
const current = parseInt((info.current || '0').split('.')[0]);
|
|
39
|
-
const latest = parseInt((info.latest || '0').split('.')[0]);
|
|
40
|
-
return latest > current;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
if (majorUpdates.length > 0) {
|
|
44
|
-
return {
|
|
45
|
-
severity: SEVERITY.INFO,
|
|
46
|
-
message: `${count} outdated (${majorUpdates.length} major)`,
|
|
47
|
-
detail: `Major updates: ${majorUpdates.slice(0, 3).map(([n]) => n).join(', ')}${majorUpdates.length > 3 ? '...' : ''}`,
|
|
48
|
-
metadata,
|
|
49
|
-
fixes: [{
|
|
50
|
-
type: FIX_TYPE.COMMAND,
|
|
51
|
-
description: 'Update all packages',
|
|
52
|
-
command: 'npm update',
|
|
53
|
-
autoFixable: false,
|
|
54
|
-
}],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (count > 0) {
|
|
59
|
-
return {
|
|
60
|
-
severity: SEVERITY.INFO,
|
|
61
|
-
message: `${count} minor/patch updates available`,
|
|
62
|
-
metadata,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
severity: SEVERITY.PASS,
|
|
68
|
-
message: 'All packages up to date',
|
|
69
|
-
metadata,
|
|
70
|
-
};
|
|
71
|
-
} catch {
|
|
72
|
-
return {
|
|
73
|
-
severity: SEVERITY.INFO,
|
|
74
|
-
message: 'Could not check for outdated packages',
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
id: `${MODULE_ID}.audit`,
|
|
81
|
-
name: 'Security Vulnerabilities',
|
|
82
|
-
category: CATEGORY.DEPENDENCIES,
|
|
83
|
-
parallel: true,
|
|
84
|
-
check: async () => {
|
|
85
|
-
try {
|
|
86
|
-
const result = execSync('npm audit --json 2>/dev/null || echo "{}"', {
|
|
87
|
-
cwd: projectPath,
|
|
88
|
-
encoding: 'utf8',
|
|
89
|
-
timeout: 60000,
|
|
90
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
91
|
-
}).trim();
|
|
92
|
-
|
|
93
|
-
let audit;
|
|
94
|
-
try {
|
|
95
|
-
audit = JSON.parse(result || '{}');
|
|
96
|
-
} catch {
|
|
97
|
-
return {
|
|
98
|
-
severity: SEVERITY.INFO,
|
|
99
|
-
message: 'Could not parse audit results',
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const vulnerabilities = audit.metadata?.vulnerabilities || {};
|
|
104
|
-
const total = vulnerabilities.total || 0;
|
|
105
|
-
const critical = vulnerabilities.critical || 0;
|
|
106
|
-
const high = vulnerabilities.high || 0;
|
|
107
|
-
const moderate = vulnerabilities.moderate || 0;
|
|
108
|
-
const low = vulnerabilities.low || 0;
|
|
109
|
-
|
|
110
|
-
const metadata = { total, critical, high, moderate, low };
|
|
111
|
-
|
|
112
|
-
if (critical > 0) {
|
|
113
|
-
return {
|
|
114
|
-
severity: SEVERITY.ERROR,
|
|
115
|
-
message: `${critical} critical vulnerabilities`,
|
|
116
|
-
detail: `Total: ${total} (${high} high, ${moderate} moderate, ${low} low)`,
|
|
117
|
-
metadata,
|
|
118
|
-
fixes: [
|
|
119
|
-
{
|
|
120
|
-
type: FIX_TYPE.COMMAND,
|
|
121
|
-
description: 'Auto-fix vulnerabilities',
|
|
122
|
-
command: 'npm audit fix',
|
|
123
|
-
autoFixable: true,
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
type: FIX_TYPE.COMMAND,
|
|
127
|
-
description: 'Force fix (may have breaking changes)',
|
|
128
|
-
command: 'npm audit fix --force',
|
|
129
|
-
dangerous: true,
|
|
130
|
-
autoFixable: false,
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (high > 0) {
|
|
137
|
-
return {
|
|
138
|
-
severity: SEVERITY.WARNING,
|
|
139
|
-
message: `${high} high severity vulnerabilities`,
|
|
140
|
-
detail: `Total: ${total} (${moderate} moderate, ${low} low)`,
|
|
141
|
-
metadata,
|
|
142
|
-
fixes: [{
|
|
143
|
-
type: FIX_TYPE.COMMAND,
|
|
144
|
-
description: 'Auto-fix vulnerabilities',
|
|
145
|
-
command: 'npm audit fix',
|
|
146
|
-
autoFixable: true,
|
|
147
|
-
}],
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (total > 0) {
|
|
152
|
-
return {
|
|
153
|
-
severity: SEVERITY.INFO,
|
|
154
|
-
message: `${total} low/moderate vulnerabilities`,
|
|
155
|
-
metadata,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
severity: SEVERITY.PASS,
|
|
161
|
-
message: 'No known vulnerabilities',
|
|
162
|
-
metadata,
|
|
163
|
-
};
|
|
164
|
-
} catch {
|
|
165
|
-
return {
|
|
166
|
-
severity: SEVERITY.INFO,
|
|
167
|
-
message: 'Could not run security audit',
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
id: `${MODULE_ID}.peer_deps`,
|
|
174
|
-
name: 'Peer Dependencies',
|
|
175
|
-
category: CATEGORY.DEPENDENCIES,
|
|
176
|
-
parallel: true,
|
|
177
|
-
check: async () => {
|
|
178
|
-
try {
|
|
179
|
-
const result = execSync('npm ls --json 2>&1 || true', {
|
|
180
|
-
cwd: projectPath,
|
|
181
|
-
encoding: 'utf8',
|
|
182
|
-
timeout: 30000,
|
|
183
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// Look for peer dependency warnings
|
|
187
|
-
const peerWarnings = (result.match(/WARN.*peer/gi) || []).length;
|
|
188
|
-
const missingPeers = (result.match(/missing peer/gi) || []).length;
|
|
189
|
-
|
|
190
|
-
const metadata = { peerWarnings, missingPeers };
|
|
191
|
-
|
|
192
|
-
if (missingPeers > 0) {
|
|
193
|
-
return {
|
|
194
|
-
severity: SEVERITY.WARNING,
|
|
195
|
-
message: `${missingPeers} missing peer dependencies`,
|
|
196
|
-
metadata,
|
|
197
|
-
fixes: [{
|
|
198
|
-
type: FIX_TYPE.COMMAND,
|
|
199
|
-
description: 'Install peer dependencies',
|
|
200
|
-
command: 'npm install --legacy-peer-deps',
|
|
201
|
-
autoFixable: false,
|
|
202
|
-
}],
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
severity: SEVERITY.PASS,
|
|
208
|
-
message: 'Peer dependencies satisfied',
|
|
209
|
-
metadata,
|
|
210
|
-
};
|
|
211
|
-
} catch {
|
|
212
|
-
return {
|
|
213
|
-
severity: SEVERITY.INFO,
|
|
214
|
-
message: 'Could not check peer dependencies',
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
id: `${MODULE_ID}.duplicate`,
|
|
221
|
-
name: 'Duplicate Packages',
|
|
222
|
-
category: CATEGORY.DEPENDENCIES,
|
|
223
|
-
parallel: true,
|
|
224
|
-
check: async () => {
|
|
225
|
-
try {
|
|
226
|
-
const result = execSync('npm dedupe --dry-run 2>&1 || true', {
|
|
227
|
-
cwd: projectPath,
|
|
228
|
-
encoding: 'utf8',
|
|
229
|
-
timeout: 30000,
|
|
230
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
const wouldDedupe = result.includes('removed') || result.includes('dedupe');
|
|
234
|
-
|
|
235
|
-
if (wouldDedupe) {
|
|
236
|
-
return {
|
|
237
|
-
severity: SEVERITY.INFO,
|
|
238
|
-
message: 'Deduplication possible',
|
|
239
|
-
fixes: [{
|
|
240
|
-
type: FIX_TYPE.COMMAND,
|
|
241
|
-
description: 'Deduplicate packages',
|
|
242
|
-
command: 'npm dedupe',
|
|
243
|
-
autoFixable: true,
|
|
244
|
-
}],
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return {
|
|
249
|
-
severity: SEVERITY.PASS,
|
|
250
|
-
message: 'No duplicates found',
|
|
251
|
-
};
|
|
252
|
-
} catch {
|
|
253
|
-
return {
|
|
254
|
-
severity: SEVERITY.INFO,
|
|
255
|
-
message: 'Could not check for duplicates',
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
id: `${MODULE_ID}.engines`,
|
|
262
|
-
name: 'Engine Requirements',
|
|
263
|
-
category: CATEGORY.DEPENDENCIES,
|
|
264
|
-
parallel: true,
|
|
265
|
-
check: async () => {
|
|
266
|
-
const pkgPath = path.join(projectPath, 'package.json');
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
270
|
-
|
|
271
|
-
if (!pkg.engines) {
|
|
272
|
-
return {
|
|
273
|
-
severity: SEVERITY.INFO,
|
|
274
|
-
message: 'No engine requirements specified',
|
|
275
|
-
fixes: [{
|
|
276
|
-
type: FIX_TYPE.MANUAL,
|
|
277
|
-
description: 'Add "engines" field to package.json to enforce Node version',
|
|
278
|
-
autoFixable: false,
|
|
279
|
-
}],
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const nodeReq = pkg.engines.node;
|
|
284
|
-
const npmReq = pkg.engines.npm;
|
|
285
|
-
|
|
286
|
-
const metadata = { nodeReq, npmReq };
|
|
287
|
-
|
|
288
|
-
// Basic semver check against current version
|
|
289
|
-
if (nodeReq) {
|
|
290
|
-
const currentMajor = parseInt(process.version.slice(1).split('.')[0]);
|
|
291
|
-
const minMatch = nodeReq.match(/>=?\s*(\d+)/);
|
|
292
|
-
const minRequired = minMatch ? parseInt(minMatch[1]) : 0;
|
|
293
|
-
|
|
294
|
-
if (currentMajor < minRequired) {
|
|
295
|
-
return {
|
|
296
|
-
severity: SEVERITY.ERROR,
|
|
297
|
-
message: `Node ${process.version} does not satisfy "${nodeReq}"`,
|
|
298
|
-
metadata,
|
|
299
|
-
fixes: [{
|
|
300
|
-
type: FIX_TYPE.COMMAND,
|
|
301
|
-
description: `Upgrade to Node ${minRequired}+`,
|
|
302
|
-
command: `nvm install ${minRequired}`,
|
|
303
|
-
autoFixable: false,
|
|
304
|
-
}],
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
severity: SEVERITY.PASS,
|
|
311
|
-
message: nodeReq ? `node: ${nodeReq}` : 'Specified',
|
|
312
|
-
metadata,
|
|
313
|
-
};
|
|
314
|
-
} catch {
|
|
315
|
-
return {
|
|
316
|
-
severity: SEVERITY.INFO,
|
|
317
|
-
message: 'Could not check engine requirements',
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
];
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
module.exports = { MODULE_ID, createDiagnostics };
|
|
1
|
+
/**
|
|
2
|
+
* Dependencies Diagnostics Module
|
|
3
|
+
*
|
|
4
|
+
* Checks for outdated packages, vulnerabilities, and dependency health
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
const { SEVERITY, CATEGORY, FIX_TYPE } = require('../types');
|
|
11
|
+
|
|
12
|
+
const MODULE_ID = 'dependencies';
|
|
13
|
+
|
|
14
|
+
function createDiagnostics(projectPath) {
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
id: `${MODULE_ID}.outdated`,
|
|
18
|
+
name: 'Outdated Packages',
|
|
19
|
+
category: CATEGORY.DEPENDENCIES,
|
|
20
|
+
parallel: true,
|
|
21
|
+
check: async () => {
|
|
22
|
+
try {
|
|
23
|
+
// Try npm outdated (returns non-zero if outdated packages exist)
|
|
24
|
+
const result = execSync('npm outdated --json 2>/dev/null || echo "{}"', {
|
|
25
|
+
cwd: projectPath,
|
|
26
|
+
encoding: 'utf8',
|
|
27
|
+
timeout: 30000,
|
|
28
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
+
}).trim();
|
|
30
|
+
|
|
31
|
+
const outdated = JSON.parse(result || '{}');
|
|
32
|
+
const count = Object.keys(outdated).length;
|
|
33
|
+
|
|
34
|
+
const metadata = { count, packages: outdated };
|
|
35
|
+
|
|
36
|
+
// Check for major version updates
|
|
37
|
+
const majorUpdates = Object.entries(outdated).filter(([_, info]) => {
|
|
38
|
+
const current = parseInt((info.current || '0').split('.')[0]);
|
|
39
|
+
const latest = parseInt((info.latest || '0').split('.')[0]);
|
|
40
|
+
return latest > current;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (majorUpdates.length > 0) {
|
|
44
|
+
return {
|
|
45
|
+
severity: SEVERITY.INFO,
|
|
46
|
+
message: `${count} outdated (${majorUpdates.length} major)`,
|
|
47
|
+
detail: `Major updates: ${majorUpdates.slice(0, 3).map(([n]) => n).join(', ')}${majorUpdates.length > 3 ? '...' : ''}`,
|
|
48
|
+
metadata,
|
|
49
|
+
fixes: [{
|
|
50
|
+
type: FIX_TYPE.COMMAND,
|
|
51
|
+
description: 'Update all packages',
|
|
52
|
+
command: 'npm update',
|
|
53
|
+
autoFixable: false,
|
|
54
|
+
}],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (count > 0) {
|
|
59
|
+
return {
|
|
60
|
+
severity: SEVERITY.INFO,
|
|
61
|
+
message: `${count} minor/patch updates available`,
|
|
62
|
+
metadata,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
severity: SEVERITY.PASS,
|
|
68
|
+
message: 'All packages up to date',
|
|
69
|
+
metadata,
|
|
70
|
+
};
|
|
71
|
+
} catch {
|
|
72
|
+
return {
|
|
73
|
+
severity: SEVERITY.INFO,
|
|
74
|
+
message: 'Could not check for outdated packages',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: `${MODULE_ID}.audit`,
|
|
81
|
+
name: 'Security Vulnerabilities',
|
|
82
|
+
category: CATEGORY.DEPENDENCIES,
|
|
83
|
+
parallel: true,
|
|
84
|
+
check: async () => {
|
|
85
|
+
try {
|
|
86
|
+
const result = execSync('npm audit --json 2>/dev/null || echo "{}"', {
|
|
87
|
+
cwd: projectPath,
|
|
88
|
+
encoding: 'utf8',
|
|
89
|
+
timeout: 60000,
|
|
90
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
91
|
+
}).trim();
|
|
92
|
+
|
|
93
|
+
let audit;
|
|
94
|
+
try {
|
|
95
|
+
audit = JSON.parse(result || '{}');
|
|
96
|
+
} catch {
|
|
97
|
+
return {
|
|
98
|
+
severity: SEVERITY.INFO,
|
|
99
|
+
message: 'Could not parse audit results',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const vulnerabilities = audit.metadata?.vulnerabilities || {};
|
|
104
|
+
const total = vulnerabilities.total || 0;
|
|
105
|
+
const critical = vulnerabilities.critical || 0;
|
|
106
|
+
const high = vulnerabilities.high || 0;
|
|
107
|
+
const moderate = vulnerabilities.moderate || 0;
|
|
108
|
+
const low = vulnerabilities.low || 0;
|
|
109
|
+
|
|
110
|
+
const metadata = { total, critical, high, moderate, low };
|
|
111
|
+
|
|
112
|
+
if (critical > 0) {
|
|
113
|
+
return {
|
|
114
|
+
severity: SEVERITY.ERROR,
|
|
115
|
+
message: `${critical} critical vulnerabilities`,
|
|
116
|
+
detail: `Total: ${total} (${high} high, ${moderate} moderate, ${low} low)`,
|
|
117
|
+
metadata,
|
|
118
|
+
fixes: [
|
|
119
|
+
{
|
|
120
|
+
type: FIX_TYPE.COMMAND,
|
|
121
|
+
description: 'Auto-fix vulnerabilities',
|
|
122
|
+
command: 'npm audit fix',
|
|
123
|
+
autoFixable: true,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: FIX_TYPE.COMMAND,
|
|
127
|
+
description: 'Force fix (may have breaking changes)',
|
|
128
|
+
command: 'npm audit fix --force',
|
|
129
|
+
dangerous: true,
|
|
130
|
+
autoFixable: false,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (high > 0) {
|
|
137
|
+
return {
|
|
138
|
+
severity: SEVERITY.WARNING,
|
|
139
|
+
message: `${high} high severity vulnerabilities`,
|
|
140
|
+
detail: `Total: ${total} (${moderate} moderate, ${low} low)`,
|
|
141
|
+
metadata,
|
|
142
|
+
fixes: [{
|
|
143
|
+
type: FIX_TYPE.COMMAND,
|
|
144
|
+
description: 'Auto-fix vulnerabilities',
|
|
145
|
+
command: 'npm audit fix',
|
|
146
|
+
autoFixable: true,
|
|
147
|
+
}],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (total > 0) {
|
|
152
|
+
return {
|
|
153
|
+
severity: SEVERITY.INFO,
|
|
154
|
+
message: `${total} low/moderate vulnerabilities`,
|
|
155
|
+
metadata,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
severity: SEVERITY.PASS,
|
|
161
|
+
message: 'No known vulnerabilities',
|
|
162
|
+
metadata,
|
|
163
|
+
};
|
|
164
|
+
} catch {
|
|
165
|
+
return {
|
|
166
|
+
severity: SEVERITY.INFO,
|
|
167
|
+
message: 'Could not run security audit',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: `${MODULE_ID}.peer_deps`,
|
|
174
|
+
name: 'Peer Dependencies',
|
|
175
|
+
category: CATEGORY.DEPENDENCIES,
|
|
176
|
+
parallel: true,
|
|
177
|
+
check: async () => {
|
|
178
|
+
try {
|
|
179
|
+
const result = execSync('npm ls --json 2>&1 || true', {
|
|
180
|
+
cwd: projectPath,
|
|
181
|
+
encoding: 'utf8',
|
|
182
|
+
timeout: 30000,
|
|
183
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Look for peer dependency warnings
|
|
187
|
+
const peerWarnings = (result.match(/WARN.*peer/gi) || []).length;
|
|
188
|
+
const missingPeers = (result.match(/missing peer/gi) || []).length;
|
|
189
|
+
|
|
190
|
+
const metadata = { peerWarnings, missingPeers };
|
|
191
|
+
|
|
192
|
+
if (missingPeers > 0) {
|
|
193
|
+
return {
|
|
194
|
+
severity: SEVERITY.WARNING,
|
|
195
|
+
message: `${missingPeers} missing peer dependencies`,
|
|
196
|
+
metadata,
|
|
197
|
+
fixes: [{
|
|
198
|
+
type: FIX_TYPE.COMMAND,
|
|
199
|
+
description: 'Install peer dependencies',
|
|
200
|
+
command: 'npm install --legacy-peer-deps',
|
|
201
|
+
autoFixable: false,
|
|
202
|
+
}],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
severity: SEVERITY.PASS,
|
|
208
|
+
message: 'Peer dependencies satisfied',
|
|
209
|
+
metadata,
|
|
210
|
+
};
|
|
211
|
+
} catch {
|
|
212
|
+
return {
|
|
213
|
+
severity: SEVERITY.INFO,
|
|
214
|
+
message: 'Could not check peer dependencies',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: `${MODULE_ID}.duplicate`,
|
|
221
|
+
name: 'Duplicate Packages',
|
|
222
|
+
category: CATEGORY.DEPENDENCIES,
|
|
223
|
+
parallel: true,
|
|
224
|
+
check: async () => {
|
|
225
|
+
try {
|
|
226
|
+
const result = execSync('npm dedupe --dry-run 2>&1 || true', {
|
|
227
|
+
cwd: projectPath,
|
|
228
|
+
encoding: 'utf8',
|
|
229
|
+
timeout: 30000,
|
|
230
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const wouldDedupe = result.includes('removed') || result.includes('dedupe');
|
|
234
|
+
|
|
235
|
+
if (wouldDedupe) {
|
|
236
|
+
return {
|
|
237
|
+
severity: SEVERITY.INFO,
|
|
238
|
+
message: 'Deduplication possible',
|
|
239
|
+
fixes: [{
|
|
240
|
+
type: FIX_TYPE.COMMAND,
|
|
241
|
+
description: 'Deduplicate packages',
|
|
242
|
+
command: 'npm dedupe',
|
|
243
|
+
autoFixable: true,
|
|
244
|
+
}],
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
severity: SEVERITY.PASS,
|
|
250
|
+
message: 'No duplicates found',
|
|
251
|
+
};
|
|
252
|
+
} catch {
|
|
253
|
+
return {
|
|
254
|
+
severity: SEVERITY.INFO,
|
|
255
|
+
message: 'Could not check for duplicates',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
id: `${MODULE_ID}.engines`,
|
|
262
|
+
name: 'Engine Requirements',
|
|
263
|
+
category: CATEGORY.DEPENDENCIES,
|
|
264
|
+
parallel: true,
|
|
265
|
+
check: async () => {
|
|
266
|
+
const pkgPath = path.join(projectPath, 'package.json');
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
270
|
+
|
|
271
|
+
if (!pkg.engines) {
|
|
272
|
+
return {
|
|
273
|
+
severity: SEVERITY.INFO,
|
|
274
|
+
message: 'No engine requirements specified',
|
|
275
|
+
fixes: [{
|
|
276
|
+
type: FIX_TYPE.MANUAL,
|
|
277
|
+
description: 'Add "engines" field to package.json to enforce Node version',
|
|
278
|
+
autoFixable: false,
|
|
279
|
+
}],
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const nodeReq = pkg.engines.node;
|
|
284
|
+
const npmReq = pkg.engines.npm;
|
|
285
|
+
|
|
286
|
+
const metadata = { nodeReq, npmReq };
|
|
287
|
+
|
|
288
|
+
// Basic semver check against current version
|
|
289
|
+
if (nodeReq) {
|
|
290
|
+
const currentMajor = parseInt(process.version.slice(1).split('.')[0]);
|
|
291
|
+
const minMatch = nodeReq.match(/>=?\s*(\d+)/);
|
|
292
|
+
const minRequired = minMatch ? parseInt(minMatch[1]) : 0;
|
|
293
|
+
|
|
294
|
+
if (currentMajor < minRequired) {
|
|
295
|
+
return {
|
|
296
|
+
severity: SEVERITY.ERROR,
|
|
297
|
+
message: `Node ${process.version} does not satisfy "${nodeReq}"`,
|
|
298
|
+
metadata,
|
|
299
|
+
fixes: [{
|
|
300
|
+
type: FIX_TYPE.COMMAND,
|
|
301
|
+
description: `Upgrade to Node ${minRequired}+`,
|
|
302
|
+
command: `nvm install ${minRequired}`,
|
|
303
|
+
autoFixable: false,
|
|
304
|
+
}],
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
severity: SEVERITY.PASS,
|
|
311
|
+
message: nodeReq ? `node: ${nodeReq}` : 'Specified',
|
|
312
|
+
metadata,
|
|
313
|
+
};
|
|
314
|
+
} catch {
|
|
315
|
+
return {
|
|
316
|
+
severity: SEVERITY.INFO,
|
|
317
|
+
message: 'Could not check engine requirements',
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
module.exports = { MODULE_ID, createDiagnostics };
|