@vibedrift/cli 0.4.3 → 0.4.5
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/index.js +41 -46
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(function_extractor_exports, {
|
|
|
24
24
|
extractAllFunctions: () => extractAllFunctions,
|
|
25
25
|
extractFunctionsFromFile: () => extractFunctionsFromFile,
|
|
26
26
|
simpleHash: () => simpleHash,
|
|
27
|
+
toFunctionRef: () => toFunctionRef,
|
|
27
28
|
tokenizeBody: () => tokenizeBody
|
|
28
29
|
});
|
|
29
30
|
function detectDomainCategory(name, body) {
|
|
@@ -149,6 +150,9 @@ function extractAllFunctions(files) {
|
|
|
149
150
|
}
|
|
150
151
|
return allFunctions;
|
|
151
152
|
}
|
|
153
|
+
function toFunctionRef(fn) {
|
|
154
|
+
return { file: fn.file, relativePath: fn.relativePath, name: fn.name, line: fn.line };
|
|
155
|
+
}
|
|
152
156
|
var init_function_extractor = __esm({
|
|
153
157
|
"src/codedna/function-extractor.ts"() {
|
|
154
158
|
"use strict";
|
|
@@ -254,12 +258,9 @@ function fnv1aHash(str) {
|
|
|
254
258
|
const h2 = (hash2 >>> 0).toString(16).padStart(8, "0");
|
|
255
259
|
return h1 + h2;
|
|
256
260
|
}
|
|
257
|
-
function toRef(fn) {
|
|
258
|
-
return { file: fn.file, relativePath: fn.relativePath, name: fn.name, line: fn.line };
|
|
259
|
-
}
|
|
260
261
|
function computeSemanticFingerprints(functions) {
|
|
261
262
|
return functions.map((fn) => ({
|
|
262
|
-
functionRef:
|
|
263
|
+
functionRef: toFunctionRef(fn),
|
|
263
264
|
normalizedHash: fnv1aHash(normalizeBody(fn.rawBody, fn.language))
|
|
264
265
|
}));
|
|
265
266
|
}
|
|
@@ -321,6 +322,7 @@ var init_semantic_fingerprint = __esm({
|
|
|
321
322
|
"src/codedna/semantic-fingerprint.ts"() {
|
|
322
323
|
"use strict";
|
|
323
324
|
init_esm_shims();
|
|
325
|
+
init_function_extractor();
|
|
324
326
|
}
|
|
325
327
|
});
|
|
326
328
|
|
|
@@ -366,9 +368,6 @@ function classifyLine(line, language) {
|
|
|
366
368
|
}
|
|
367
369
|
return null;
|
|
368
370
|
}
|
|
369
|
-
function toRef2(fn) {
|
|
370
|
-
return { file: fn.file, relativePath: fn.relativePath, name: fn.name, line: fn.line };
|
|
371
|
-
}
|
|
372
371
|
function extractOperationSequences(functions) {
|
|
373
372
|
return functions.map((fn) => {
|
|
374
373
|
const lines = fn.rawBody.split("\n");
|
|
@@ -381,7 +380,7 @@ function extractOperationSequences(functions) {
|
|
|
381
380
|
}
|
|
382
381
|
}
|
|
383
382
|
}
|
|
384
|
-
return { functionRef:
|
|
383
|
+
return { functionRef: toFunctionRef(fn), sequence };
|
|
385
384
|
});
|
|
386
385
|
}
|
|
387
386
|
function lcsLength(a, b) {
|
|
@@ -456,6 +455,7 @@ var init_operation_sequence = __esm({
|
|
|
456
455
|
"src/codedna/operation-sequence.ts"() {
|
|
457
456
|
"use strict";
|
|
458
457
|
init_esm_shims();
|
|
458
|
+
init_function_extractor();
|
|
459
459
|
}
|
|
460
460
|
});
|
|
461
461
|
|
|
@@ -2735,10 +2735,13 @@ var importsAnalyzer = {
|
|
|
2735
2735
|
);
|
|
2736
2736
|
const esmFiles = [];
|
|
2737
2737
|
const cjsFiles = [];
|
|
2738
|
+
const SKIP_PATH = /(?:fixtures?|testdata|__fixtures__|__mocks__)[/\\]/i;
|
|
2738
2739
|
for (const file of jsFiles) {
|
|
2739
2740
|
if (CONFIG_FILE_PATTERN.test(file.relativePath)) continue;
|
|
2741
|
+
if (SKIP_PATH.test(file.relativePath)) continue;
|
|
2742
|
+
const stripped = file.content.replace(/\/[^/\n]+\/[gimsuvy]*/g, '""').replace(/`[^`]*`/g, '""');
|
|
2740
2743
|
const hasESM = ESM_PATTERN.test(file.content);
|
|
2741
|
-
const hasCJS = CJS_PATTERN.test(
|
|
2744
|
+
const hasCJS = CJS_PATTERN.test(stripped);
|
|
2742
2745
|
if (hasESM && hasCJS) {
|
|
2743
2746
|
findings.push({
|
|
2744
2747
|
analyzerId: "imports",
|
|
@@ -2908,8 +2911,11 @@ var NODE_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
2908
2911
|
]);
|
|
2909
2912
|
var JS_IMPORT_PATTERNS = [
|
|
2910
2913
|
/(?:import|from)\s+['"]([^./][^'"]*)['"]/g,
|
|
2911
|
-
/require\(\s*['"]([^./][^'"]*)['"]\s*\)/g
|
|
2914
|
+
/require\(\s*['"]([^./][^'"]*)['"]\s*\)/g,
|
|
2915
|
+
// Dynamic imports: await import("pkg") or import("pkg")
|
|
2916
|
+
/import\(\s*['"]([^./][^'"]*)['"]\s*\)/g
|
|
2912
2917
|
];
|
|
2918
|
+
var FIXTURE_PATH_PATTERN = /(?:fixtures?|testdata|__fixtures__|__mocks__)[/\\]/i;
|
|
2913
2919
|
function extractGoImports(content) {
|
|
2914
2920
|
const imports = [];
|
|
2915
2921
|
const singlePattern = /^import\s+"([^"]+)"/gm;
|
|
@@ -2998,7 +3004,7 @@ function analyzeJsDeps(ctx) {
|
|
|
2998
3004
|
const imported = /* @__PURE__ */ new Set();
|
|
2999
3005
|
const importLocations = /* @__PURE__ */ new Map();
|
|
3000
3006
|
const jsFiles = ctx.files.filter(
|
|
3001
|
-
(f) => f.language === "javascript" || f.language === "typescript"
|
|
3007
|
+
(f) => (f.language === "javascript" || f.language === "typescript") && !FIXTURE_PATH_PATTERN.test(f.relativePath)
|
|
3002
3008
|
);
|
|
3003
3009
|
for (const file of jsFiles) {
|
|
3004
3010
|
for (const pattern of JS_IMPORT_PATTERNS) {
|
|
@@ -3856,11 +3862,12 @@ var SECURITY_PATTERNS = [
|
|
|
3856
3862
|
id: "ssrf-risk",
|
|
3857
3863
|
name: "SSRF risk",
|
|
3858
3864
|
pattern: /(?:fetch|axios\.get|http\.get|requests\.get|httpClient)\s*\(\s*(?:[`'"].*\$\{|[^'"]*\+)/g,
|
|
3859
|
-
severity: "
|
|
3860
|
-
confidence: 0.
|
|
3861
|
-
message: "
|
|
3865
|
+
severity: "info",
|
|
3866
|
+
confidence: 0.4,
|
|
3867
|
+
message: "URL constructed from variable \u2014 review if the source is user-controlled",
|
|
3862
3868
|
languages: "all",
|
|
3863
|
-
tags: ["security", "ssrf"]
|
|
3869
|
+
tags: ["security", "ssrf"],
|
|
3870
|
+
negativeFilter: /(?:API_URL|BASE_URL|apiUrl|baseUrl|base\s*\+|endpoint|config\.|process\.env)/i
|
|
3864
3871
|
},
|
|
3865
3872
|
// === Python-specific ===
|
|
3866
3873
|
{
|
|
@@ -3916,7 +3923,9 @@ var securityAnalyzer = {
|
|
|
3916
3923
|
async analyze(ctx) {
|
|
3917
3924
|
const findings = [];
|
|
3918
3925
|
const projectLanguages = [...ctx.languageBreakdown.keys()];
|
|
3926
|
+
const PATTERN_DEF = /(?:pattern\s*:|regex\s*:|RegExp\s*\(|name\s*:|message\s*:|id\s*:|label\s*:)/;
|
|
3919
3927
|
for (const file of ctx.files) {
|
|
3928
|
+
if (/(?:fixtures?|testdata|__fixtures__|__mocks__)[/\\]/i.test(file.relativePath)) continue;
|
|
3920
3929
|
for (const pattern of SECURITY_PATTERNS) {
|
|
3921
3930
|
if (pattern.languages !== "all") {
|
|
3922
3931
|
if (!file.language || !pattern.languages.includes(file.language)) continue;
|
|
@@ -3924,10 +3933,11 @@ var securityAnalyzer = {
|
|
|
3924
3933
|
const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
|
|
3925
3934
|
let match;
|
|
3926
3935
|
while ((match = regex.exec(file.content)) !== null) {
|
|
3936
|
+
const lineStart = file.content.lastIndexOf("\n", match.index) + 1;
|
|
3937
|
+
const lineEnd = file.content.indexOf("\n", match.index);
|
|
3938
|
+
const line = file.content.slice(lineStart, lineEnd === -1 ? void 0 : lineEnd);
|
|
3939
|
+
if (PATTERN_DEF.test(line)) continue;
|
|
3927
3940
|
if (pattern.negativeFilter) {
|
|
3928
|
-
const lineStart2 = file.content.lastIndexOf("\n", match.index) + 1;
|
|
3929
|
-
const lineEnd2 = file.content.indexOf("\n", match.index);
|
|
3930
|
-
const line = file.content.slice(lineStart2, lineEnd2 === -1 ? void 0 : lineEnd2);
|
|
3931
3941
|
if (pattern.negativeFilter.test(line)) continue;
|
|
3932
3942
|
}
|
|
3933
3943
|
if (pattern.contextRequired) {
|
|
@@ -3939,9 +3949,7 @@ var securityAnalyzer = {
|
|
|
3939
3949
|
if (!pattern.contextRequired.test(context)) continue;
|
|
3940
3950
|
}
|
|
3941
3951
|
const lineNum = getLineNumber(file.content, match.index);
|
|
3942
|
-
const
|
|
3943
|
-
const lineEnd = file.content.indexOf("\n", match.index);
|
|
3944
|
-
const snippet = file.content.slice(lineStart, lineEnd === -1 ? void 0 : lineEnd).trim();
|
|
3952
|
+
const snippet = line.trim();
|
|
3945
3953
|
findings.push({
|
|
3946
3954
|
analyzerId: "security",
|
|
3947
3955
|
severity: pattern.severity,
|
|
@@ -4959,9 +4967,6 @@ var DRIFT_WEIGHTS = {
|
|
|
4959
4967
|
|
|
4960
4968
|
// src/drift/architectural-contradiction.ts
|
|
4961
4969
|
init_esm_shims();
|
|
4962
|
-
function getLine(content, index) {
|
|
4963
|
-
return content.slice(0, index).split("\n").length;
|
|
4964
|
-
}
|
|
4965
4970
|
function getLineContent(content, lineNum) {
|
|
4966
4971
|
return (content.split("\n")[lineNum - 1] ?? "").trim();
|
|
4967
4972
|
}
|
|
@@ -4970,7 +4975,7 @@ function extractEvidence(content, pattern, maxResults = 3) {
|
|
|
4970
4975
|
const regex = new RegExp(pattern.source, pattern.flags);
|
|
4971
4976
|
let match;
|
|
4972
4977
|
while ((match = regex.exec(content)) !== null && evidence.length < maxResults) {
|
|
4973
|
-
const line =
|
|
4978
|
+
const line = getLineNumber(content, match.index);
|
|
4974
4979
|
evidence.push({ line, code: getLineContent(content, line) });
|
|
4975
4980
|
}
|
|
4976
4981
|
return evidence;
|
|
@@ -8034,6 +8039,16 @@ function previewToken(token) {
|
|
|
8034
8039
|
if (token.length <= 12) return token.slice(0, 4) + "\u2026";
|
|
8035
8040
|
return token.slice(0, 12) + "\u2026";
|
|
8036
8041
|
}
|
|
8042
|
+
function describeSource(source) {
|
|
8043
|
+
switch (source) {
|
|
8044
|
+
case "flag":
|
|
8045
|
+
return "command-line flag";
|
|
8046
|
+
case "env":
|
|
8047
|
+
return "VIBEDRIFT_TOKEN environment variable";
|
|
8048
|
+
case "config":
|
|
8049
|
+
return "~/.vibedrift/config.json";
|
|
8050
|
+
}
|
|
8051
|
+
}
|
|
8037
8052
|
|
|
8038
8053
|
// src/auth/api.ts
|
|
8039
8054
|
init_esm_shims();
|
|
@@ -8832,16 +8847,6 @@ async function runStatus() {
|
|
|
8832
8847
|
}
|
|
8833
8848
|
console.log("");
|
|
8834
8849
|
}
|
|
8835
|
-
function describeSource(source) {
|
|
8836
|
-
switch (source) {
|
|
8837
|
-
case "flag":
|
|
8838
|
-
return "command-line flag";
|
|
8839
|
-
case "env":
|
|
8840
|
-
return "VIBEDRIFT_TOKEN environment variable";
|
|
8841
|
-
case "config":
|
|
8842
|
-
return "~/.vibedrift/config.json";
|
|
8843
|
-
}
|
|
8844
|
-
}
|
|
8845
8850
|
|
|
8846
8851
|
// src/cli/commands/usage.ts
|
|
8847
8852
|
init_esm_shims();
|
|
@@ -9038,7 +9043,7 @@ async function runDoctor() {
|
|
|
9038
9043
|
if (!resolved) {
|
|
9039
9044
|
info("Login state", "not logged in");
|
|
9040
9045
|
} else {
|
|
9041
|
-
ok("Token source",
|
|
9046
|
+
ok("Token source", describeSource(resolved.source));
|
|
9042
9047
|
ok("Token preview", previewToken(resolved.token));
|
|
9043
9048
|
if (resolved.source === "config") {
|
|
9044
9049
|
if (config.email) ok("Email", config.email);
|
|
@@ -9110,16 +9115,6 @@ function bad(value) {
|
|
|
9110
9115
|
function info(label, value) {
|
|
9111
9116
|
console.log(` ${chalk10.dim("\xB7")} ${label.padEnd(14)} ${chalk10.dim(value)}`);
|
|
9112
9117
|
}
|
|
9113
|
-
function describeSource2(source) {
|
|
9114
|
-
switch (source) {
|
|
9115
|
-
case "flag":
|
|
9116
|
-
return "command-line flag";
|
|
9117
|
-
case "env":
|
|
9118
|
-
return "VIBEDRIFT_TOKEN environment variable";
|
|
9119
|
-
case "config":
|
|
9120
|
-
return "~/.vibedrift/config.json";
|
|
9121
|
-
}
|
|
9122
|
-
}
|
|
9123
9118
|
|
|
9124
9119
|
// src/cli/commands/feedback.ts
|
|
9125
9120
|
init_esm_shims();
|