@safetnsr/vet 1.7.0 → 1.8.2
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/dist/checks/debt.js +17 -4
- package/dist/checks/deps.js +146 -135
- package/dist/checks/diff.js +23 -4
- package/dist/checks/integrity.js +94 -17
- package/dist/checks/memory.js +6 -10
- package/dist/checks/models.js +60 -13
- package/dist/checks/owasp/asi01-goal-hijack.d.ts +5 -0
- package/dist/checks/owasp/asi01-goal-hijack.js +49 -0
- package/dist/checks/owasp/asi02-tool-misuse.d.ts +5 -0
- package/dist/checks/owasp/asi02-tool-misuse.js +98 -0
- package/dist/checks/owasp/asi03-identity-abuse.d.ts +5 -0
- package/dist/checks/owasp/asi03-identity-abuse.js +80 -0
- package/dist/checks/owasp/asi04-supply-chain.d.ts +5 -0
- package/dist/checks/owasp/asi04-supply-chain.js +79 -0
- package/dist/checks/owasp/asi05-code-execution.d.ts +5 -0
- package/dist/checks/owasp/asi05-code-execution.js +67 -0
- package/dist/checks/owasp/asi06-memory-poisoning.d.ts +5 -0
- package/dist/checks/owasp/asi06-memory-poisoning.js +61 -0
- package/dist/checks/owasp/asi07-inter-agent.d.ts +5 -0
- package/dist/checks/owasp/asi07-inter-agent.js +62 -0
- package/dist/checks/owasp/asi08-cascading.d.ts +5 -0
- package/dist/checks/owasp/asi08-cascading.js +36 -0
- package/dist/checks/owasp/asi09-trust-exploitation.d.ts +5 -0
- package/dist/checks/owasp/asi09-trust-exploitation.js +65 -0
- package/dist/checks/owasp/asi10-rogue-agents.d.ts +5 -0
- package/dist/checks/owasp/asi10-rogue-agents.js +31 -0
- package/dist/checks/owasp/index.d.ts +11 -0
- package/dist/checks/owasp/index.js +11 -0
- package/dist/checks/owasp/shared.d.ts +11 -0
- package/dist/checks/owasp/shared.js +61 -0
- package/dist/checks/owasp.js +1 -1
- package/dist/checks/ready.js +42 -7
- package/dist/checks/receipt.js +2 -16
- package/dist/checks/scan.js +54 -6
- package/dist/checks/secrets.js +2 -20
- package/dist/checks/tests.d.ts +3 -0
- package/dist/checks/tests.js +10 -0
- package/dist/checks/verify.js +35 -2
- package/dist/cli.js +111 -69
- package/dist/util.d.ts +0 -1
- package/dist/util.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -106,22 +106,40 @@ if (configContent) {
|
|
|
106
106
|
}
|
|
107
107
|
const ignore = config.ignore || [];
|
|
108
108
|
if (command === 'init') {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
try {
|
|
110
|
+
const { init } = await import('./init.js');
|
|
111
|
+
await init(cwd);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
console.error(`${c.red}init failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
111
117
|
process.exit(0);
|
|
112
118
|
}
|
|
113
119
|
if (command === 'receipt') {
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
try {
|
|
121
|
+
const format = isJSON ? 'json' : 'ascii';
|
|
122
|
+
await runReceiptCommand(format);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
console.error(`${c.red}receipt failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
116
128
|
process.exit(0);
|
|
117
129
|
}
|
|
118
130
|
if (command === 'map') {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
131
|
+
try {
|
|
132
|
+
const result = await checkMap(cwd);
|
|
133
|
+
if (isJSON) {
|
|
134
|
+
console.log(renderMapReport(result, true));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log(renderMapReport(result, false));
|
|
138
|
+
}
|
|
122
139
|
}
|
|
123
|
-
|
|
124
|
-
console.
|
|
140
|
+
catch (e) {
|
|
141
|
+
console.error(`${c.red}map failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
142
|
+
process.exit(1);
|
|
125
143
|
}
|
|
126
144
|
process.exit(0);
|
|
127
145
|
}
|
|
@@ -155,61 +173,79 @@ if (!isGitRepo(cwd)) {
|
|
|
155
173
|
}
|
|
156
174
|
// --fix mode
|
|
157
175
|
if (isFix) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
176
|
+
try {
|
|
177
|
+
console.log(`\n ${c.bold}vet --fix${c.reset}\n`);
|
|
178
|
+
const { fixConfig } = await import('./fix/config.js');
|
|
179
|
+
const { fixModels } = await import('./fix/models.js');
|
|
180
|
+
const configResult = fixConfig(cwd);
|
|
181
|
+
const modelsResult = fixModels(cwd, ignore);
|
|
182
|
+
const allMessages = [...configResult.messages, ...modelsResult.messages];
|
|
183
|
+
const totalFixed = configResult.fixed + modelsResult.fixed;
|
|
184
|
+
if (allMessages.length > 0) {
|
|
185
|
+
for (const msg of allMessages)
|
|
186
|
+
console.log(msg);
|
|
187
|
+
}
|
|
188
|
+
console.log(`\n ${totalFixed > 0 ? c.green : c.dim}fixed ${totalFixed} issue${totalFixed !== 1 ? 's' : ''}${c.reset}\n`);
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
console.error(`${c.red}fix failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
192
|
+
process.exit(1);
|
|
168
193
|
}
|
|
169
|
-
console.log(`\n ${totalFixed > 0 ? c.green : c.dim}fixed ${totalFixed} issue${totalFixed !== 1 ? 's' : ''}${c.reset}\n`);
|
|
170
194
|
process.exit(0);
|
|
171
195
|
}
|
|
172
196
|
async function runChecks() {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
Promise.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
197
|
+
try {
|
|
198
|
+
// Run all checks, grouped into categories
|
|
199
|
+
// Security: scan, secrets, config, models, owasp, permissions
|
|
200
|
+
const [scanResult, secretsResult, configResult, modelsResult, owaspResult] = await Promise.all([
|
|
201
|
+
Promise.resolve(checkScan(cwd)),
|
|
202
|
+
checkSecrets(cwd),
|
|
203
|
+
Promise.resolve(checkConfig(cwd, ignore)),
|
|
204
|
+
checkModels(cwd, ignore),
|
|
205
|
+
Promise.resolve(checkOwasp(cwd)),
|
|
206
|
+
]);
|
|
207
|
+
const permissionsResult = checkPermissions(cwd);
|
|
208
|
+
// Integrity: diff, integrity checks
|
|
209
|
+
const diffResult = checkDiff(cwd, { since });
|
|
210
|
+
const integrityResult = await checkIntegrity(cwd, ignore);
|
|
211
|
+
// Debt: ready, history, debt
|
|
212
|
+
const [readyResult, debtResult] = await Promise.all([
|
|
213
|
+
checkReady(cwd, ignore),
|
|
214
|
+
checkDebt(cwd, ignore),
|
|
215
|
+
]);
|
|
216
|
+
const historyResult = checkHistory(cwd);
|
|
217
|
+
// Deps: deps
|
|
218
|
+
const depsResult = await checkDeps(cwd);
|
|
219
|
+
// Receipt is informational — fold into integrity category but keep low weight
|
|
220
|
+
const receiptResult = await checkReceipt(cwd);
|
|
221
|
+
// Memory: stale facts in agent memory files
|
|
222
|
+
const memoryResult = checkMemory(cwd);
|
|
223
|
+
// Verify: agent claim validation
|
|
224
|
+
const verifyResult = checkVerify(cwd, since);
|
|
225
|
+
// Tests: test theater detection
|
|
226
|
+
const testsResult = checkTests(cwd, ignore);
|
|
227
|
+
return score(cwd, {
|
|
228
|
+
security: [scanResult, secretsResult, configResult, modelsResult, owaspResult, permissionsResult],
|
|
229
|
+
integrity: [diffResult, integrityResult, receiptResult, memoryResult, verifyResult, testsResult],
|
|
230
|
+
debt: [readyResult, historyResult, debtResult],
|
|
231
|
+
deps: [depsResult],
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
console.error('check failed:', e instanceof Error ? e.message : e);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
208
238
|
}
|
|
209
239
|
// --badge mode
|
|
210
240
|
if (isBadge && !isWatch) {
|
|
211
|
-
|
|
212
|
-
|
|
241
|
+
try {
|
|
242
|
+
const result = await runChecks();
|
|
243
|
+
console.log(reportBadge(result));
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
console.error(`${c.red}badge failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
213
249
|
process.exit(0);
|
|
214
250
|
}
|
|
215
251
|
// --watch mode
|
|
@@ -247,18 +283,24 @@ if (isWatch) {
|
|
|
247
283
|
}
|
|
248
284
|
else {
|
|
249
285
|
// Normal run
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
286
|
+
try {
|
|
287
|
+
const result = await runChecks();
|
|
288
|
+
if (isJSON) {
|
|
289
|
+
console.log(reportJSON(result));
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
console.log(reportPretty(result));
|
|
293
|
+
}
|
|
294
|
+
if (isCI || isHook) {
|
|
295
|
+
// --hook uses grade C (60) as threshold
|
|
296
|
+
// --ci uses config threshold or grade C default
|
|
297
|
+
const minScore = isHook ? 60 : (config.thresholds?.min ?? 60);
|
|
298
|
+
const minGrade = isHook ? 'C' : (config.thresholds?.grade ?? 'C');
|
|
299
|
+
process.exit(result.score >= minScore ? 0 : 1);
|
|
300
|
+
}
|
|
256
301
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const minScore = isHook ? 60 : (config.thresholds?.min ?? 60);
|
|
261
|
-
const minGrade = isHook ? 'C' : (config.thresholds?.grade ?? 'C');
|
|
262
|
-
process.exit(result.score >= minScore ? 0 : 1);
|
|
302
|
+
catch (e) {
|
|
303
|
+
console.error(`${c.red}vet failed:${c.reset}`, e instanceof Error ? e.message : e);
|
|
304
|
+
process.exit(1);
|
|
263
305
|
}
|
|
264
306
|
}
|
package/dist/util.d.ts
CHANGED
|
@@ -22,4 +22,3 @@ export declare function walkFiles(dir: string, ignore?: string[]): string[];
|
|
|
22
22
|
export declare function isTextFile(filePath: string): boolean;
|
|
23
23
|
/** Recursively collect all file paths under a directory */
|
|
24
24
|
export declare function collectDirFiles(dir: string): string[];
|
|
25
|
-
export declare function matchesAny(file: string, patterns: string[]): boolean;
|
package/dist/util.js
CHANGED
|
@@ -103,7 +103,7 @@ export function collectDirFiles(dir) {
|
|
|
103
103
|
catch { /* skip */ }
|
|
104
104
|
return files;
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
function matchesAny(file, patterns) {
|
|
107
107
|
return patterns.some(p => {
|
|
108
108
|
if (p.endsWith('/'))
|
|
109
109
|
return file.startsWith(p) || file.includes('/' + p);
|