@node9/proxy 2.6.2 → 2.7.1
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/cli.js +221 -145
- package/dist/cli.mjs +1009 -934
- package/dist/dashboard.mjs +159 -116
- package/dist/scan-ink.mjs +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -243,8 +243,8 @@ function sanitizeConfig(raw) {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
const lines = result.error.issues.map((issue) => {
|
|
246
|
-
const
|
|
247
|
-
return ` \u2022 ${
|
|
246
|
+
const path74 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
247
|
+
return ` \u2022 ${path74}: ${issue.message}`;
|
|
248
248
|
});
|
|
249
249
|
return {
|
|
250
250
|
sanitized,
|
|
@@ -624,9 +624,9 @@ function matchesPattern(text, patterns) {
|
|
|
624
624
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
625
625
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
626
626
|
}
|
|
627
|
-
function getNestedValue(obj,
|
|
627
|
+
function getNestedValue(obj, path74) {
|
|
628
628
|
if (!obj || typeof obj !== "object") return null;
|
|
629
|
-
const segments =
|
|
629
|
+
const segments = path74.split(".");
|
|
630
630
|
for (const seg of segments) {
|
|
631
631
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
632
632
|
}
|
|
@@ -2561,8 +2561,7 @@ function extractSessionLevelFindings(calls, ctx) {
|
|
|
2561
2561
|
occurrenceCount: 1,
|
|
2562
2562
|
loopCount: verdict.count,
|
|
2563
2563
|
loopKind: "loop",
|
|
2564
|
-
commandPreview: previewArgs(call.args, DEDUPE_PREVIEW_LEN)
|
|
2565
|
-
costUsd: verdict.count * COST_PER_LOOP_ITER_USD
|
|
2564
|
+
commandPreview: previewArgs(call.args, DEDUPE_PREVIEW_LEN)
|
|
2566
2565
|
});
|
|
2567
2566
|
}
|
|
2568
2567
|
return out;
|
|
@@ -2632,7 +2631,7 @@ function* stringValues(obj, depth = 0) {
|
|
|
2632
2631
|
}
|
|
2633
2632
|
for (const v of Object.values(obj)) yield* stringValues(v, depth + 1);
|
|
2634
2633
|
}
|
|
2635
|
-
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, MAX, UNTRUSTED_TOOLS, SIGNALS, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, DLP_SCAN_LIMITS, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, INTERP_LEADING_TARGET, NET_BINARIES, VALUE_FLAGS, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_HEREDOC_OPS, DEFAULT_EGRESS_ALLOWLIST, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, VERDICT_RANK, SQL_DML_KEYWORDS, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE,
|
|
2634
|
+
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, MAX, UNTRUSTED_TOOLS, SIGNALS, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, DLP_SCAN_LIMITS, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, INTERP_LEADING_TARGET, NET_BINARIES, VALUE_FLAGS, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_HEREDOC_OPS, DEFAULT_EGRESS_ALLOWLIST, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, VERDICT_RANK, SQL_DML_KEYWORDS, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, TERMINAL_ESCAPE_RE, ENGINE_VERSION;
|
|
2636
2635
|
var init_dist = __esm({
|
|
2637
2636
|
"packages/policy-engine/dist/index.mjs"() {
|
|
2638
2637
|
"use strict";
|
|
@@ -4439,7 +4438,6 @@ var init_dist = __esm({
|
|
|
4439
4438
|
longOutputRedactions: 1
|
|
4440
4439
|
};
|
|
4441
4440
|
LOOP_THRESHOLD_FOR_WASTE = 3;
|
|
4442
|
-
COST_PER_LOOP_ITER_USD = 6e-3;
|
|
4443
4441
|
DESTRUCTIVE_OP_RE = /\brm\s+-[rRf]+\b|\bDROP\s+(TABLE|DATABASE|COLLECTION|SCHEMA)\b|\bTRUNCATE\s+TABLE\b|\bgit\s+push\s+(--force|-f)\b|\bFLUSHALL\b|\bFLUSHDB\b|\bkubectl\s+delete\b|\bhelm\s+uninstall\b/i;
|
|
4444
4442
|
SENSITIVE_PATH_RE = /\.aws\/(credentials|config)\b|\.ssh\/(id_rsa|id_ed25519|id_ecdsa|id_dsa)\b|\.env(\.|$|\b)|\.config\/gcloud\/credentials\.db\b|\.docker\/config\.json\b|\.netrc\b|\.npmrc\b|\.node9\/credentials\.json\b/i;
|
|
4445
4443
|
FILE_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -5425,13 +5423,13 @@ function getConfig(cwd) {
|
|
|
5425
5423
|
}
|
|
5426
5424
|
if (Array.isArray(mc.jailPaths)) {
|
|
5427
5425
|
for (const jp of mc.jailPaths) {
|
|
5428
|
-
const
|
|
5429
|
-
if (!
|
|
5426
|
+
const path74 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
5427
|
+
if (!path74) continue;
|
|
5430
5428
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
5431
|
-
for (const r of pathRules(
|
|
5429
|
+
for (const r of pathRules(path74, verdict, "org-managed jail")) {
|
|
5432
5430
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
5433
5431
|
}
|
|
5434
|
-
mergedPolicy.managedJailPaths.push({ path:
|
|
5432
|
+
mergedPolicy.managedJailPaths.push({ path: path74, verdict });
|
|
5435
5433
|
}
|
|
5436
5434
|
}
|
|
5437
5435
|
if (Array.isArray(mc.trustedHosts)) {
|
|
@@ -11403,14 +11401,15 @@ var init_keyed_guard = __esm({
|
|
|
11403
11401
|
function normalizeModel(raw) {
|
|
11404
11402
|
return raw.replace(/-\d{8}$/, "").toLowerCase();
|
|
11405
11403
|
}
|
|
11406
|
-
function readCache() {
|
|
11404
|
+
function readCache(opts) {
|
|
11407
11405
|
try {
|
|
11408
11406
|
const raw = JSON.parse(import_fs17.default.readFileSync(CACHE_FILE(), "utf-8"));
|
|
11409
11407
|
if (typeof raw.fetchedAt !== "string" || typeof raw.prices !== "object" || raw.prices === null) {
|
|
11410
11408
|
return null;
|
|
11411
11409
|
}
|
|
11412
11410
|
const ageMs = Date.now() - new Date(raw.fetchedAt).getTime();
|
|
11413
|
-
if (ageMs
|
|
11411
|
+
if (!Number.isFinite(ageMs) || ageMs < 0) return null;
|
|
11412
|
+
if (opts.requireFresh && ageMs > TTL_MS) return null;
|
|
11414
11413
|
return raw.prices;
|
|
11415
11414
|
} catch {
|
|
11416
11415
|
return null;
|
|
@@ -11476,7 +11475,7 @@ async function fetchLiteLLMPricing() {
|
|
|
11476
11475
|
}
|
|
11477
11476
|
async function ensurePricingLoaded() {
|
|
11478
11477
|
if (memCache !== null && Date.now() - memCacheAt < TTL_MS) return;
|
|
11479
|
-
const fromDisk = readCache();
|
|
11478
|
+
const fromDisk = readCache({ requireFresh: true });
|
|
11480
11479
|
if (fromDisk && Object.keys(fromDisk).length > 0) {
|
|
11481
11480
|
memCache = fromDisk;
|
|
11482
11481
|
memCacheAt = Date.now();
|
|
@@ -11501,7 +11500,7 @@ function pricingFor(model) {
|
|
|
11501
11500
|
if (cached !== void 0) return cached;
|
|
11502
11501
|
if (memCache === null && !diskChecked) {
|
|
11503
11502
|
diskChecked = true;
|
|
11504
|
-
const disk = readCache();
|
|
11503
|
+
const disk = readCache({ requireFresh: false });
|
|
11505
11504
|
if (disk && Object.keys(disk).length > 0) {
|
|
11506
11505
|
memCache = disk;
|
|
11507
11506
|
memCacheAt = Date.now();
|
|
@@ -11962,6 +11961,31 @@ function agentColorName(agent) {
|
|
|
11962
11961
|
return "cyan";
|
|
11963
11962
|
}
|
|
11964
11963
|
}
|
|
11964
|
+
function computeLoopWaste(loops, perSession) {
|
|
11965
|
+
const rate = /* @__PURE__ */ new Map();
|
|
11966
|
+
for (const s of perSession) {
|
|
11967
|
+
if (!(s.toolCalls > 0) || !(s.costUSD > 0)) continue;
|
|
11968
|
+
const r = s.costUSD / s.toolCalls;
|
|
11969
|
+
if (!Number.isFinite(r) || r <= 0 || r > MAX_PLAUSIBLE_RATE_USD) continue;
|
|
11970
|
+
rate.set(s.sessionId, r);
|
|
11971
|
+
}
|
|
11972
|
+
let usd = 0;
|
|
11973
|
+
let pricedIterations = 0;
|
|
11974
|
+
let unpricedIterations = 0;
|
|
11975
|
+
for (const l of loops) {
|
|
11976
|
+
if (l.kind === "long-iteration") continue;
|
|
11977
|
+
const wasted = Math.max(0, l.count - LOOP_THRESHOLD_FOR_WASTE);
|
|
11978
|
+
if (!Number.isFinite(wasted) || wasted === 0) continue;
|
|
11979
|
+
const r = rate.get(l.sessionId);
|
|
11980
|
+
if (r === void 0) {
|
|
11981
|
+
unpricedIterations += wasted;
|
|
11982
|
+
continue;
|
|
11983
|
+
}
|
|
11984
|
+
usd += wasted * r;
|
|
11985
|
+
pricedIterations += wasted;
|
|
11986
|
+
}
|
|
11987
|
+
return { usd, pricedIterations, unpricedIterations };
|
|
11988
|
+
}
|
|
11965
11989
|
function buildScanSummary(agents) {
|
|
11966
11990
|
const stats = {
|
|
11967
11991
|
sessions: 0,
|
|
@@ -12022,8 +12046,11 @@ function buildScanSummary(agents) {
|
|
|
12022
12046
|
costUSD: a.scan.totalCostUSD
|
|
12023
12047
|
})).filter((s) => s.sessions > 0 || s.findings > 0);
|
|
12024
12048
|
const sections = buildSections(allFindings);
|
|
12025
|
-
const
|
|
12026
|
-
|
|
12049
|
+
const loopWaste = computeLoopWaste(
|
|
12050
|
+
allLoops,
|
|
12051
|
+
agents.flatMap((a) => a.scan.perSession)
|
|
12052
|
+
);
|
|
12053
|
+
const loopWastedUSD = loopWaste.usd;
|
|
12027
12054
|
return {
|
|
12028
12055
|
stats,
|
|
12029
12056
|
byVerdict,
|
|
@@ -12031,7 +12058,8 @@ function buildScanSummary(agents) {
|
|
|
12031
12058
|
sections,
|
|
12032
12059
|
leaks: allLeaks,
|
|
12033
12060
|
loops: allLoops,
|
|
12034
|
-
loopWastedUSD
|
|
12061
|
+
loopWastedUSD,
|
|
12062
|
+
loopWaste
|
|
12035
12063
|
};
|
|
12036
12064
|
}
|
|
12037
12065
|
function buildSections(findings) {
|
|
@@ -12138,7 +12166,7 @@ function fullCommandOf(input) {
|
|
|
12138
12166
|
const raw = input.command ?? input.query ?? input.file_path ?? JSON.stringify(input);
|
|
12139
12167
|
return String(raw).replace(/\s+/g, " ").trim();
|
|
12140
12168
|
}
|
|
12141
|
-
var AGENT_SHORT, AGENT_LONG;
|
|
12169
|
+
var AGENT_SHORT, AGENT_LONG, MAX_PLAUSIBLE_RATE_USD;
|
|
12142
12170
|
var init_scan_summary = __esm({
|
|
12143
12171
|
"src/scan-summary.ts"() {
|
|
12144
12172
|
"use strict";
|
|
@@ -12161,6 +12189,7 @@ var init_scan_summary = __esm({
|
|
|
12161
12189
|
copilot: "GitHub Copilot",
|
|
12162
12190
|
shell: "Shell"
|
|
12163
12191
|
};
|
|
12192
|
+
MAX_PLAUSIBLE_RATE_USD = 50;
|
|
12164
12193
|
}
|
|
12165
12194
|
});
|
|
12166
12195
|
|
|
@@ -12368,7 +12397,7 @@ function topRulesByVerdict(sections, verdict, n) {
|
|
|
12368
12397
|
}
|
|
12369
12398
|
return matched.sort((a, b) => b.count - a.count).slice(0, n);
|
|
12370
12399
|
}
|
|
12371
|
-
function
|
|
12400
|
+
function computeLoopWaste2(loops, totalToolCalls) {
|
|
12372
12401
|
const wastedCalls = loops.reduce((s, l) => s + Math.max(0, l.count - 1), 0);
|
|
12373
12402
|
const wastePct = totalToolCalls > 0 ? Math.round(wastedCalls / totalToolCalls * 100) : 0;
|
|
12374
12403
|
return { wastedCalls, wastePct };
|
|
@@ -12478,6 +12507,38 @@ var init_scan_json = __esm({
|
|
|
12478
12507
|
}
|
|
12479
12508
|
});
|
|
12480
12509
|
|
|
12510
|
+
// src/session-files.ts
|
|
12511
|
+
function listSessionFiles(dir, maxDepth = 6) {
|
|
12512
|
+
const out = [];
|
|
12513
|
+
const walk = (d, rel, depth) => {
|
|
12514
|
+
if (depth > maxDepth) return;
|
|
12515
|
+
let entries;
|
|
12516
|
+
try {
|
|
12517
|
+
entries = fs22.readdirSync(d, { withFileTypes: true });
|
|
12518
|
+
} catch {
|
|
12519
|
+
return;
|
|
12520
|
+
}
|
|
12521
|
+
for (const e of entries) {
|
|
12522
|
+
const childRel = rel ? path24.join(rel, e.name) : e.name;
|
|
12523
|
+
if (e.isDirectory()) walk(path24.join(d, e.name), childRel, depth + 1);
|
|
12524
|
+
else if (e.name.endsWith(".jsonl")) out.push(childRel);
|
|
12525
|
+
}
|
|
12526
|
+
};
|
|
12527
|
+
walk(dir, "", 0);
|
|
12528
|
+
return out;
|
|
12529
|
+
}
|
|
12530
|
+
function sessionIdOf(relPath) {
|
|
12531
|
+
return path24.basename(relPath).replace(/\.jsonl$/, "");
|
|
12532
|
+
}
|
|
12533
|
+
var fs22, path24;
|
|
12534
|
+
var init_session_files = __esm({
|
|
12535
|
+
"src/session-files.ts"() {
|
|
12536
|
+
"use strict";
|
|
12537
|
+
fs22 = __toESM(require("fs"));
|
|
12538
|
+
path24 = __toESM(require("path"));
|
|
12539
|
+
}
|
|
12540
|
+
});
|
|
12541
|
+
|
|
12481
12542
|
// src/cli/render/scan-history.ts
|
|
12482
12543
|
function defaultHistoryPath() {
|
|
12483
12544
|
return import_path23.default.join(import_os20.default.homedir(), ".node9", "scan-history.json");
|
|
@@ -12841,6 +12902,7 @@ var init_costSync = __esm({
|
|
|
12841
12902
|
init_cost_codex();
|
|
12842
12903
|
init_cost_gemini();
|
|
12843
12904
|
init_cost_copilot();
|
|
12905
|
+
init_session_files();
|
|
12844
12906
|
SYNC_INTERVAL_MS = 10 * 60 * 1e3;
|
|
12845
12907
|
claudeSource = {
|
|
12846
12908
|
id: "claude",
|
|
@@ -12866,7 +12928,7 @@ var init_costSync = __esm({
|
|
|
12866
12928
|
}
|
|
12867
12929
|
let files;
|
|
12868
12930
|
try {
|
|
12869
|
-
files =
|
|
12931
|
+
files = listSessionFiles(dirPath);
|
|
12870
12932
|
} catch {
|
|
12871
12933
|
continue;
|
|
12872
12934
|
}
|
|
@@ -13920,7 +13982,7 @@ function countScanFiles() {
|
|
|
13920
13982
|
const dp = import_path28.default.join(mp, day);
|
|
13921
13983
|
try {
|
|
13922
13984
|
if (!import_fs26.default.statSync(dp).isDirectory()) continue;
|
|
13923
|
-
total +=
|
|
13985
|
+
total += listSessionFiles(dp).length;
|
|
13924
13986
|
} catch {
|
|
13925
13987
|
continue;
|
|
13926
13988
|
}
|
|
@@ -13953,7 +14015,8 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
13953
14015
|
result.filesScanned++;
|
|
13954
14016
|
result.sessions++;
|
|
13955
14017
|
onProgress?.(result.filesScanned);
|
|
13956
|
-
const sessionId = file
|
|
14018
|
+
const sessionId = sessionIdOf(file);
|
|
14019
|
+
const session = { sessionId, costUSD: 0, toolCalls: 0 };
|
|
13957
14020
|
let raw;
|
|
13958
14021
|
try {
|
|
13959
14022
|
raw = import_fs26.default.readFileSync(import_path28.default.join(projPath, file), "utf-8");
|
|
@@ -14041,7 +14104,9 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
14041
14104
|
if (usage && model) {
|
|
14042
14105
|
const p = claudeModelPrice(model);
|
|
14043
14106
|
if (p) {
|
|
14044
|
-
|
|
14107
|
+
const rowCost = (usage.input_tokens ?? 0) * p.i + (usage.output_tokens ?? 0) * p.o + (usage.cache_creation_input_tokens ?? 0) * p.cw + (usage.cache_read_input_tokens ?? 0) * p.cr;
|
|
14108
|
+
result.totalCostUSD += rowCost;
|
|
14109
|
+
session.costUSD += rowCost;
|
|
14045
14110
|
}
|
|
14046
14111
|
}
|
|
14047
14112
|
const content = entry.message?.content;
|
|
@@ -14049,6 +14114,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
14049
14114
|
for (const block of content) {
|
|
14050
14115
|
if (block.type !== "tool_use") continue;
|
|
14051
14116
|
result.totalToolCalls++;
|
|
14117
|
+
session.toolCalls++;
|
|
14052
14118
|
const toolName = block.name ?? "";
|
|
14053
14119
|
const toolNameLower = toolName.toLowerCase();
|
|
14054
14120
|
const input = block.input ?? {};
|
|
@@ -14160,6 +14226,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
14160
14226
|
if (firstDlpTs !== null && (firstEditTs === null || firstDlpTs < firstEditTs)) {
|
|
14161
14227
|
result.sessionsWithEarlySecrets++;
|
|
14162
14228
|
}
|
|
14229
|
+
result.perSession.push(session);
|
|
14163
14230
|
}
|
|
14164
14231
|
function processClaudeProject(proj, projectsDir, ruleSources, startDate, result, dedup, onProgress, onLine) {
|
|
14165
14232
|
const projPath = import_path28.default.join(projectsDir, proj);
|
|
@@ -14174,7 +14241,7 @@ function processClaudeProject(proj, projectsDir, ruleSources, startDate, result,
|
|
|
14174
14241
|
);
|
|
14175
14242
|
let files;
|
|
14176
14243
|
try {
|
|
14177
|
-
files =
|
|
14244
|
+
files = listSessionFiles(projPath);
|
|
14178
14245
|
} catch {
|
|
14179
14246
|
return;
|
|
14180
14247
|
}
|
|
@@ -14204,7 +14271,8 @@ function emptyClaudeScan() {
|
|
|
14204
14271
|
totalCostUSD: 0,
|
|
14205
14272
|
firstDate: null,
|
|
14206
14273
|
lastDate: null,
|
|
14207
|
-
sessionsWithEarlySecrets: 0
|
|
14274
|
+
sessionsWithEarlySecrets: 0,
|
|
14275
|
+
perSession: []
|
|
14208
14276
|
};
|
|
14209
14277
|
}
|
|
14210
14278
|
function scanClaudeHistory(startDate, onProgress, onLine) {
|
|
@@ -14246,7 +14314,8 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
14246
14314
|
totalCostUSD: 0,
|
|
14247
14315
|
firstDate: null,
|
|
14248
14316
|
lastDate: null,
|
|
14249
|
-
sessionsWithEarlySecrets: 0
|
|
14317
|
+
sessionsWithEarlySecrets: 0,
|
|
14318
|
+
perSession: []
|
|
14250
14319
|
};
|
|
14251
14320
|
const dedup = emptyScanDedup();
|
|
14252
14321
|
if (!import_fs26.default.existsSync(tmpDir)) return result;
|
|
@@ -14484,7 +14553,8 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
14484
14553
|
// transcripts carry no token/model data
|
|
14485
14554
|
firstDate: null,
|
|
14486
14555
|
lastDate: null,
|
|
14487
|
-
sessionsWithEarlySecrets: 0
|
|
14556
|
+
sessionsWithEarlySecrets: 0,
|
|
14557
|
+
perSession: []
|
|
14488
14558
|
};
|
|
14489
14559
|
const dedup = emptyScanDedup();
|
|
14490
14560
|
const brainDirs = antigravityBrainDirs();
|
|
@@ -14680,7 +14750,8 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
14680
14750
|
// event logs carry no token/cost rollup
|
|
14681
14751
|
firstDate: null,
|
|
14682
14752
|
lastDate: null,
|
|
14683
|
-
sessionsWithEarlySecrets: 0
|
|
14753
|
+
sessionsWithEarlySecrets: 0,
|
|
14754
|
+
perSession: []
|
|
14684
14755
|
};
|
|
14685
14756
|
const dedup = emptyScanDedup();
|
|
14686
14757
|
if (!import_fs26.default.existsSync(sessionDir)) return result;
|
|
@@ -14862,7 +14933,8 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
14862
14933
|
totalCostUSD: 0,
|
|
14863
14934
|
firstDate: null,
|
|
14864
14935
|
lastDate: null,
|
|
14865
|
-
sessionsWithEarlySecrets: 0
|
|
14936
|
+
sessionsWithEarlySecrets: 0,
|
|
14937
|
+
perSession: []
|
|
14866
14938
|
};
|
|
14867
14939
|
const dedup = emptyScanDedup();
|
|
14868
14940
|
if (!import_fs26.default.existsSync(sessionsBase)) return result;
|
|
@@ -15141,7 +15213,8 @@ function mergeScans(a, b) {
|
|
|
15141
15213
|
totalCostUSD: a.totalCostUSD + b.totalCostUSD,
|
|
15142
15214
|
firstDate: dates.length ? dates.sort()[0] : null,
|
|
15143
15215
|
lastDate: lastDates.length ? lastDates.sort().at(-1) : null,
|
|
15144
|
-
sessionsWithEarlySecrets: a.sessionsWithEarlySecrets + b.sessionsWithEarlySecrets
|
|
15216
|
+
sessionsWithEarlySecrets: a.sessionsWithEarlySecrets + b.sessionsWithEarlySecrets,
|
|
15217
|
+
perSession: [...a.perSession, ...b.perSession]
|
|
15145
15218
|
};
|
|
15146
15219
|
}
|
|
15147
15220
|
function verdictIcon(verdict) {
|
|
@@ -15225,9 +15298,9 @@ function renderCompactScorecard(input) {
|
|
|
15225
15298
|
const realLoops = scan.loopFindings.filter((l) => l.kind !== "long-iteration");
|
|
15226
15299
|
const longIterations = scan.loopFindings.filter((l) => l.kind === "long-iteration");
|
|
15227
15300
|
if (realLoops.length > 0) {
|
|
15228
|
-
const { wastePct, wastedCalls } =
|
|
15301
|
+
const { wastePct, wastedCalls } = computeLoopWaste2(realLoops, scan.totalToolCalls);
|
|
15229
15302
|
const wasteParts = [];
|
|
15230
|
-
if (wastedCalls > 0) wasteParts.push(`${wastedCalls}
|
|
15303
|
+
if (wastedCalls > 0) wasteParts.push(`${wastedCalls} repeat calls (${wastePct}% of all calls)`);
|
|
15231
15304
|
if (summary.loopWastedUSD > 0) wasteParts.push("~" + fmtCost(summary.loopWastedUSD));
|
|
15232
15305
|
const wasteSummary = wasteParts.length ? `(${wasteParts.join(" \xB7 ")})` : "";
|
|
15233
15306
|
console.log(
|
|
@@ -15305,10 +15378,10 @@ function renderNarrativeScorecard(input) {
|
|
|
15305
15378
|
});
|
|
15306
15379
|
}
|
|
15307
15380
|
if (scan.loopFindings.length > 0) {
|
|
15308
|
-
const { wastePct, wastedCalls } =
|
|
15381
|
+
const { wastePct, wastedCalls } = computeLoopWaste2(scan.loopFindings, scan.totalToolCalls);
|
|
15309
15382
|
const cost = summary.loopWastedUSD > 0 ? `, ~${fmtCost(summary.loopWastedUSD)} wasted` : "";
|
|
15310
15383
|
medium.push({
|
|
15311
|
-
label: `${scan.loopFindings.length} agent loops (${wastedCalls}
|
|
15384
|
+
label: `${scan.loopFindings.length} agent loops (${wastedCalls} repeat calls, ${wastePct}% of calls${cost})`,
|
|
15312
15385
|
count: scan.loopFindings.length
|
|
15313
15386
|
});
|
|
15314
15387
|
}
|
|
@@ -15420,13 +15493,13 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
|
|
|
15420
15493
|
);
|
|
15421
15494
|
}
|
|
15422
15495
|
if (scan.loopFindings.length > 0) {
|
|
15423
|
-
const { wastePct, wastedCalls } =
|
|
15496
|
+
const { wastePct, wastedCalls } = computeLoopWaste2(scan.loopFindings, scan.totalToolCalls);
|
|
15424
15497
|
const byTool = /* @__PURE__ */ new Map();
|
|
15425
15498
|
for (const f of scan.loopFindings) {
|
|
15426
15499
|
byTool.set(f.toolName, (byTool.get(f.toolName) ?? 0) + Math.max(0, f.count - 1));
|
|
15427
15500
|
}
|
|
15428
15501
|
const top = [...byTool.entries()].sort((a, b) => b[1] - a[1])[0];
|
|
15429
|
-
const wasteSuffix = wastedCalls > 0 ? `, ${wastedCalls}
|
|
15502
|
+
const wasteSuffix = wastedCalls > 0 ? `, ${wastedCalls} repeat calls \xB7 ${wastePct}% of calls` : "";
|
|
15430
15503
|
const detail = top ? `(${top[0]} dominates${wasteSuffix})` : "";
|
|
15431
15504
|
topLines.push(
|
|
15432
15505
|
mkLine(
|
|
@@ -15518,7 +15591,7 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
|
|
|
15518
15591
|
console.log("");
|
|
15519
15592
|
}
|
|
15520
15593
|
if (scan.loopFindings.length > 0) {
|
|
15521
|
-
const { wastePct, wastedCalls } =
|
|
15594
|
+
const { wastePct, wastedCalls } = computeLoopWaste2(scan.loopFindings, scan.totalToolCalls);
|
|
15522
15595
|
const byTool = /* @__PURE__ */ new Map();
|
|
15523
15596
|
let totalRepeats = 0;
|
|
15524
15597
|
for (const f of scan.loopFindings) {
|
|
@@ -15548,7 +15621,7 @@ function renderPanelScorecard(input, now = /* @__PURE__ */ new Date()) {
|
|
|
15548
15621
|
loopLines.push(mkLine([`\xD7${num(f.count).padEnd(4)} `, import_chalk6.default.bold], [target, import_chalk6.default.dim]));
|
|
15549
15622
|
}
|
|
15550
15623
|
}
|
|
15551
|
-
const wasteSuffix = wastedCalls > 0 ? ` \xB7 ${wastedCalls}
|
|
15624
|
+
const wasteSuffix = wastedCalls > 0 ? ` \xB7 ${wastedCalls} repeat calls (${wastePct}% of all calls)` : "";
|
|
15552
15625
|
const title = `AGENT LOOPS \xB7 ${scan.loopFindings.length} pattern${scan.loopFindings.length !== 1 ? "s" : ""}${wasteSuffix}`;
|
|
15553
15626
|
for (const ln of boxPanel(title, loopLines)) console.log(" " + ln);
|
|
15554
15627
|
console.log("");
|
|
@@ -15883,7 +15956,7 @@ function registerScanCommand(program2) {
|
|
|
15883
15956
|
);
|
|
15884
15957
|
}
|
|
15885
15958
|
if (scan.loopFindings.length > 0) {
|
|
15886
|
-
const { wastePct } =
|
|
15959
|
+
const { wastePct } = computeLoopWaste2(scan.loopFindings, scan.totalToolCalls);
|
|
15887
15960
|
const wasteSuffix = wastePct > 0 ? import_chalk6.default.dim(` (${wastePct}% of calls)`) : "";
|
|
15888
15961
|
cardParts.push(
|
|
15889
15962
|
import_chalk6.default.yellow("\u{1F501} ") + import_chalk6.default.yellow.bold(String(scan.loopFindings.length)) + import_chalk6.default.dim(" loops") + wasteSuffix
|
|
@@ -16189,6 +16262,7 @@ var init_scan = __esm({
|
|
|
16189
16262
|
init_protection();
|
|
16190
16263
|
import_string_width2 = __toESM(require("string-width"));
|
|
16191
16264
|
init_scan_json();
|
|
16265
|
+
init_session_files();
|
|
16192
16266
|
init_scan_history();
|
|
16193
16267
|
toolInspectionMap = DEFAULT_CONFIG.policy.toolInspection;
|
|
16194
16268
|
CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
@@ -18857,28 +18931,28 @@ var init_ship2 = __esm({
|
|
|
18857
18931
|
|
|
18858
18932
|
// src/machine-id.ts
|
|
18859
18933
|
function getMachineId(homeDir2 = os34.homedir()) {
|
|
18860
|
-
const file =
|
|
18934
|
+
const file = path38.join(homeDir2, ".node9", "machine-id");
|
|
18861
18935
|
try {
|
|
18862
|
-
const existing =
|
|
18936
|
+
const existing = fs39.readFileSync(file, "utf-8").trim();
|
|
18863
18937
|
if (UUID_RE.test(existing)) return existing;
|
|
18864
18938
|
} catch {
|
|
18865
18939
|
}
|
|
18866
18940
|
const id = crypto5.randomUUID();
|
|
18867
18941
|
try {
|
|
18868
|
-
|
|
18869
|
-
|
|
18942
|
+
fs39.mkdirSync(path38.dirname(file), { recursive: true });
|
|
18943
|
+
fs39.writeFileSync(file, id + "\n", { mode: 384 });
|
|
18870
18944
|
} catch {
|
|
18871
18945
|
}
|
|
18872
18946
|
return id;
|
|
18873
18947
|
}
|
|
18874
|
-
var crypto5,
|
|
18948
|
+
var crypto5, fs39, os34, path38, UUID_RE;
|
|
18875
18949
|
var init_machine_id = __esm({
|
|
18876
18950
|
"src/machine-id.ts"() {
|
|
18877
18951
|
"use strict";
|
|
18878
18952
|
crypto5 = __toESM(require("crypto"));
|
|
18879
|
-
|
|
18953
|
+
fs39 = __toESM(require("fs"));
|
|
18880
18954
|
os34 = __toESM(require("os"));
|
|
18881
|
-
|
|
18955
|
+
path38 = __toESM(require("path"));
|
|
18882
18956
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
18883
18957
|
}
|
|
18884
18958
|
});
|
|
@@ -21056,7 +21130,8 @@ data: ${JSON.stringify(item.data)}
|
|
|
21056
21130
|
totalCostUSD: 0,
|
|
21057
21131
|
firstDate: null,
|
|
21058
21132
|
lastDate: null,
|
|
21059
|
-
sessionsWithEarlySecrets: 0
|
|
21133
|
+
sessionsWithEarlySecrets: 0,
|
|
21134
|
+
perSession: []
|
|
21060
21135
|
};
|
|
21061
21136
|
let claude = EMPTY_SCAN;
|
|
21062
21137
|
let gemini = EMPTY_SCAN;
|
|
@@ -23118,14 +23193,14 @@ var require_util = __commonJS({
|
|
|
23118
23193
|
}
|
|
23119
23194
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
23120
23195
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
23121
|
-
let
|
|
23196
|
+
let path74 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
23122
23197
|
if (origin[origin.length - 1] === "/") {
|
|
23123
23198
|
origin = origin.slice(0, origin.length - 1);
|
|
23124
23199
|
}
|
|
23125
|
-
if (
|
|
23126
|
-
|
|
23200
|
+
if (path74 && path74[0] !== "/") {
|
|
23201
|
+
path74 = `/${path74}`;
|
|
23127
23202
|
}
|
|
23128
|
-
return new URL(`${origin}${
|
|
23203
|
+
return new URL(`${origin}${path74}`);
|
|
23129
23204
|
}
|
|
23130
23205
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
23131
23206
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -23946,9 +24021,9 @@ var require_diagnostics = __commonJS({
|
|
|
23946
24021
|
"undici:client:sendHeaders",
|
|
23947
24022
|
(evt) => {
|
|
23948
24023
|
const {
|
|
23949
|
-
request: { method, path:
|
|
24024
|
+
request: { method, path: path74, origin }
|
|
23950
24025
|
} = evt;
|
|
23951
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
24026
|
+
debugLog("sending request to %s %s%s", method, origin, path74);
|
|
23952
24027
|
}
|
|
23953
24028
|
);
|
|
23954
24029
|
}
|
|
@@ -23966,14 +24041,14 @@ var require_diagnostics = __commonJS({
|
|
|
23966
24041
|
"undici:request:headers",
|
|
23967
24042
|
(evt) => {
|
|
23968
24043
|
const {
|
|
23969
|
-
request: { method, path:
|
|
24044
|
+
request: { method, path: path74, origin },
|
|
23970
24045
|
response: { statusCode }
|
|
23971
24046
|
} = evt;
|
|
23972
24047
|
debugLog(
|
|
23973
24048
|
"received response to %s %s%s - HTTP %d",
|
|
23974
24049
|
method,
|
|
23975
24050
|
origin,
|
|
23976
|
-
|
|
24051
|
+
path74,
|
|
23977
24052
|
statusCode
|
|
23978
24053
|
);
|
|
23979
24054
|
}
|
|
@@ -23982,23 +24057,23 @@ var require_diagnostics = __commonJS({
|
|
|
23982
24057
|
"undici:request:trailers",
|
|
23983
24058
|
(evt) => {
|
|
23984
24059
|
const {
|
|
23985
|
-
request: { method, path:
|
|
24060
|
+
request: { method, path: path74, origin }
|
|
23986
24061
|
} = evt;
|
|
23987
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
24062
|
+
debugLog("trailers received from %s %s%s", method, origin, path74);
|
|
23988
24063
|
}
|
|
23989
24064
|
);
|
|
23990
24065
|
diagnosticsChannel.subscribe(
|
|
23991
24066
|
"undici:request:error",
|
|
23992
24067
|
(evt) => {
|
|
23993
24068
|
const {
|
|
23994
|
-
request: { method, path:
|
|
24069
|
+
request: { method, path: path74, origin },
|
|
23995
24070
|
error
|
|
23996
24071
|
} = evt;
|
|
23997
24072
|
debugLog(
|
|
23998
24073
|
"request to %s %s%s errored - %s",
|
|
23999
24074
|
method,
|
|
24000
24075
|
origin,
|
|
24001
|
-
|
|
24076
|
+
path74,
|
|
24002
24077
|
error.message
|
|
24003
24078
|
);
|
|
24004
24079
|
}
|
|
@@ -24101,7 +24176,7 @@ var require_request = __commonJS({
|
|
|
24101
24176
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
24102
24177
|
var Request = class {
|
|
24103
24178
|
constructor(origin, {
|
|
24104
|
-
path:
|
|
24179
|
+
path: path74,
|
|
24105
24180
|
method,
|
|
24106
24181
|
body,
|
|
24107
24182
|
headers,
|
|
@@ -24118,11 +24193,11 @@ var require_request = __commonJS({
|
|
|
24118
24193
|
maxRedirections,
|
|
24119
24194
|
typeOfService
|
|
24120
24195
|
}, handler) {
|
|
24121
|
-
if (typeof
|
|
24196
|
+
if (typeof path74 !== "string") {
|
|
24122
24197
|
throw new InvalidArgumentError("path must be a string");
|
|
24123
|
-
} else if (
|
|
24198
|
+
} else if (path74[0] !== "/" && !(path74.startsWith("http://") || path74.startsWith("https://")) && method !== "CONNECT") {
|
|
24124
24199
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
24125
|
-
} else if (invalidPathRegex.test(
|
|
24200
|
+
} else if (invalidPathRegex.test(path74)) {
|
|
24126
24201
|
throw new InvalidArgumentError("invalid request path");
|
|
24127
24202
|
}
|
|
24128
24203
|
if (typeof method !== "string") {
|
|
@@ -24197,7 +24272,7 @@ var require_request = __commonJS({
|
|
|
24197
24272
|
this.completed = false;
|
|
24198
24273
|
this.aborted = false;
|
|
24199
24274
|
this.upgrade = upgrade || null;
|
|
24200
|
-
this.path = query ? serializePathWithQuery(
|
|
24275
|
+
this.path = query ? serializePathWithQuery(path74, query) : path74;
|
|
24201
24276
|
this.origin = origin;
|
|
24202
24277
|
this.protocol = getProtocolFromUrlString(origin);
|
|
24203
24278
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -29236,7 +29311,7 @@ var require_client_h1 = __commonJS({
|
|
|
29236
29311
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
29237
29312
|
}
|
|
29238
29313
|
function writeH1(client, request2) {
|
|
29239
|
-
const { method, path:
|
|
29314
|
+
const { method, path: path74, host, upgrade, blocking, reset } = request2;
|
|
29240
29315
|
let { body, headers, contentLength } = request2;
|
|
29241
29316
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
29242
29317
|
if (util.isFormDataLike(body)) {
|
|
@@ -29305,7 +29380,7 @@ var require_client_h1 = __commonJS({
|
|
|
29305
29380
|
if (socket.setTypeOfService) {
|
|
29306
29381
|
socket.setTypeOfService(request2.typeOfService);
|
|
29307
29382
|
}
|
|
29308
|
-
let header = `${method} ${
|
|
29383
|
+
let header = `${method} ${path74} HTTP/1.1\r
|
|
29309
29384
|
`;
|
|
29310
29385
|
if (typeof host === "string") {
|
|
29311
29386
|
header += `host: ${host}\r
|
|
@@ -29958,7 +30033,7 @@ var require_client_h2 = __commonJS({
|
|
|
29958
30033
|
function writeH2(client, request2) {
|
|
29959
30034
|
const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
29960
30035
|
const session = client[kHTTP2Session];
|
|
29961
|
-
const { method, path:
|
|
30036
|
+
const { method, path: path74, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
29962
30037
|
let { body } = request2;
|
|
29963
30038
|
if (upgrade != null && upgrade !== "websocket") {
|
|
29964
30039
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -30026,7 +30101,7 @@ var require_client_h2 = __commonJS({
|
|
|
30026
30101
|
}
|
|
30027
30102
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
30028
30103
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
30029
|
-
headers[HTTP2_HEADER_PATH] =
|
|
30104
|
+
headers[HTTP2_HEADER_PATH] = path74;
|
|
30030
30105
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
30031
30106
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
30032
30107
|
} else {
|
|
@@ -30067,7 +30142,7 @@ var require_client_h2 = __commonJS({
|
|
|
30067
30142
|
stream.setTimeout(requestTimeout);
|
|
30068
30143
|
return true;
|
|
30069
30144
|
}
|
|
30070
|
-
headers[HTTP2_HEADER_PATH] =
|
|
30145
|
+
headers[HTTP2_HEADER_PATH] = path74;
|
|
30071
30146
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
30072
30147
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
30073
30148
|
if (body && typeof body.read === "function") {
|
|
@@ -32369,10 +32444,10 @@ var require_proxy_agent = __commonJS({
|
|
|
32369
32444
|
};
|
|
32370
32445
|
const {
|
|
32371
32446
|
origin,
|
|
32372
|
-
path:
|
|
32447
|
+
path: path74 = "/",
|
|
32373
32448
|
headers = {}
|
|
32374
32449
|
} = opts;
|
|
32375
|
-
opts.path = origin +
|
|
32450
|
+
opts.path = origin + path74;
|
|
32376
32451
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
32377
32452
|
const { host } = new URL(origin);
|
|
32378
32453
|
headers.host = host;
|
|
@@ -34435,20 +34510,20 @@ var require_mock_utils = __commonJS({
|
|
|
34435
34510
|
}
|
|
34436
34511
|
return normalizedQp;
|
|
34437
34512
|
}
|
|
34438
|
-
function safeUrl(
|
|
34439
|
-
if (typeof
|
|
34440
|
-
return
|
|
34513
|
+
function safeUrl(path74) {
|
|
34514
|
+
if (typeof path74 !== "string") {
|
|
34515
|
+
return path74;
|
|
34441
34516
|
}
|
|
34442
|
-
const pathSegments =
|
|
34517
|
+
const pathSegments = path74.split("?", 3);
|
|
34443
34518
|
if (pathSegments.length !== 2) {
|
|
34444
|
-
return
|
|
34519
|
+
return path74;
|
|
34445
34520
|
}
|
|
34446
34521
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
34447
34522
|
qp.sort();
|
|
34448
34523
|
return [...pathSegments, qp.toString()].join("?");
|
|
34449
34524
|
}
|
|
34450
|
-
function matchKey(mockDispatch2, { path:
|
|
34451
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
34525
|
+
function matchKey(mockDispatch2, { path: path74, method, body, headers }) {
|
|
34526
|
+
const pathMatch = matchValue(mockDispatch2.path, path74);
|
|
34452
34527
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
34453
34528
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
34454
34529
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -34473,8 +34548,8 @@ var require_mock_utils = __commonJS({
|
|
|
34473
34548
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
34474
34549
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
34475
34550
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
34476
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
34477
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
34551
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path74, ignoreTrailingSlash }) => {
|
|
34552
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path74)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path74), resolvedPath);
|
|
34478
34553
|
});
|
|
34479
34554
|
if (matchedMockDispatches.length === 0) {
|
|
34480
34555
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -34513,19 +34588,19 @@ var require_mock_utils = __commonJS({
|
|
|
34513
34588
|
mockDispatches.splice(index, 1);
|
|
34514
34589
|
}
|
|
34515
34590
|
}
|
|
34516
|
-
function removeTrailingSlash(
|
|
34517
|
-
while (
|
|
34518
|
-
|
|
34591
|
+
function removeTrailingSlash(path74) {
|
|
34592
|
+
while (path74.endsWith("/")) {
|
|
34593
|
+
path74 = path74.slice(0, -1);
|
|
34519
34594
|
}
|
|
34520
|
-
if (
|
|
34521
|
-
|
|
34595
|
+
if (path74.length === 0) {
|
|
34596
|
+
path74 = "/";
|
|
34522
34597
|
}
|
|
34523
|
-
return
|
|
34598
|
+
return path74;
|
|
34524
34599
|
}
|
|
34525
34600
|
function buildKey(opts) {
|
|
34526
|
-
const { path:
|
|
34601
|
+
const { path: path74, method, body, headers, query } = opts;
|
|
34527
34602
|
return {
|
|
34528
|
-
path:
|
|
34603
|
+
path: path74,
|
|
34529
34604
|
method,
|
|
34530
34605
|
body,
|
|
34531
34606
|
headers,
|
|
@@ -35215,10 +35290,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
35215
35290
|
}
|
|
35216
35291
|
format(pendingInterceptors) {
|
|
35217
35292
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
35218
|
-
({ method, path:
|
|
35293
|
+
({ method, path: path74, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
35219
35294
|
Method: method,
|
|
35220
35295
|
Origin: origin,
|
|
35221
|
-
Path:
|
|
35296
|
+
Path: path74,
|
|
35222
35297
|
"Status code": statusCode,
|
|
35223
35298
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
35224
35299
|
Invocations: timesInvoked,
|
|
@@ -35300,9 +35375,9 @@ var require_mock_agent = __commonJS({
|
|
|
35300
35375
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
35301
35376
|
const dispatchOpts = { ...opts };
|
|
35302
35377
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
35303
|
-
const [
|
|
35378
|
+
const [path74, searchParams] = dispatchOpts.path.split("?");
|
|
35304
35379
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
35305
|
-
dispatchOpts.path = `${
|
|
35380
|
+
dispatchOpts.path = `${path74}?${normalizedSearchParams}`;
|
|
35306
35381
|
}
|
|
35307
35382
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
35308
35383
|
}
|
|
@@ -35703,12 +35778,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35703
35778
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
35704
35779
|
*/
|
|
35705
35780
|
async loadSnapshots(filePath) {
|
|
35706
|
-
const
|
|
35707
|
-
if (!
|
|
35781
|
+
const path74 = filePath || this.#snapshotPath;
|
|
35782
|
+
if (!path74) {
|
|
35708
35783
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
35709
35784
|
}
|
|
35710
35785
|
try {
|
|
35711
|
-
const data = await readFile(resolve2(
|
|
35786
|
+
const data = await readFile(resolve2(path74), "utf8");
|
|
35712
35787
|
const parsed = JSON.parse(data);
|
|
35713
35788
|
if (Array.isArray(parsed)) {
|
|
35714
35789
|
this.#snapshots.clear();
|
|
@@ -35722,7 +35797,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35722
35797
|
if (error.code === "ENOENT") {
|
|
35723
35798
|
this.#snapshots.clear();
|
|
35724
35799
|
} else {
|
|
35725
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
35800
|
+
throw new UndiciError(`Failed to load snapshots from ${path74}`, { cause: error });
|
|
35726
35801
|
}
|
|
35727
35802
|
}
|
|
35728
35803
|
}
|
|
@@ -35733,11 +35808,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35733
35808
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
35734
35809
|
*/
|
|
35735
35810
|
async saveSnapshots(filePath) {
|
|
35736
|
-
const
|
|
35737
|
-
if (!
|
|
35811
|
+
const path74 = filePath || this.#snapshotPath;
|
|
35812
|
+
if (!path74) {
|
|
35738
35813
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
35739
35814
|
}
|
|
35740
|
-
const resolvedPath = resolve2(
|
|
35815
|
+
const resolvedPath = resolve2(path74);
|
|
35741
35816
|
await mkdir(dirname3(resolvedPath), { recursive: true });
|
|
35742
35817
|
const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
|
|
35743
35818
|
hash,
|
|
@@ -36362,15 +36437,15 @@ var require_redirect_handler = __commonJS({
|
|
|
36362
36437
|
return;
|
|
36363
36438
|
}
|
|
36364
36439
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
36365
|
-
const
|
|
36366
|
-
const redirectUrlString = `${origin}${
|
|
36440
|
+
const path74 = search ? `${pathname}${search}` : pathname;
|
|
36441
|
+
const redirectUrlString = `${origin}${path74}`;
|
|
36367
36442
|
for (const historyUrl of this.history) {
|
|
36368
36443
|
if (historyUrl.toString() === redirectUrlString) {
|
|
36369
36444
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
36370
36445
|
}
|
|
36371
36446
|
}
|
|
36372
36447
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
36373
|
-
this.opts.path =
|
|
36448
|
+
this.opts.path = path74;
|
|
36374
36449
|
this.opts.origin = origin;
|
|
36375
36450
|
this.opts.query = null;
|
|
36376
36451
|
}
|
|
@@ -42577,11 +42652,11 @@ var require_fetch = __commonJS({
|
|
|
42577
42652
|
function dispatch({ body }) {
|
|
42578
42653
|
const url = requestCurrentURL(request2);
|
|
42579
42654
|
const agent = fetchParams.controller.dispatcher;
|
|
42580
|
-
const
|
|
42655
|
+
const path74 = url.pathname + url.search;
|
|
42581
42656
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
42582
42657
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
42583
42658
|
{
|
|
42584
|
-
path: hasTrailingQuestionMark ? `${
|
|
42659
|
+
path: hasTrailingQuestionMark ? `${path74}?` : path74,
|
|
42585
42660
|
origin: url.origin,
|
|
42586
42661
|
method: request2.method,
|
|
42587
42662
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -43512,9 +43587,9 @@ var require_util4 = __commonJS({
|
|
|
43512
43587
|
}
|
|
43513
43588
|
}
|
|
43514
43589
|
}
|
|
43515
|
-
function validateCookiePath(
|
|
43516
|
-
for (let i = 0; i <
|
|
43517
|
-
const code =
|
|
43590
|
+
function validateCookiePath(path74) {
|
|
43591
|
+
for (let i = 0; i < path74.length; ++i) {
|
|
43592
|
+
const code = path74.charCodeAt(i);
|
|
43518
43593
|
if (code < 32 || // exclude CTLs (0-31)
|
|
43519
43594
|
code === 127 || // DEL
|
|
43520
43595
|
code === 59) {
|
|
@@ -46684,11 +46759,11 @@ var require_undici = __commonJS({
|
|
|
46684
46759
|
if (typeof opts.path !== "string") {
|
|
46685
46760
|
throw new InvalidArgumentError("invalid opts.path");
|
|
46686
46761
|
}
|
|
46687
|
-
let
|
|
46762
|
+
let path74 = opts.path;
|
|
46688
46763
|
if (!opts.path.startsWith("/")) {
|
|
46689
|
-
|
|
46764
|
+
path74 = `/${path74}`;
|
|
46690
46765
|
}
|
|
46691
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
46766
|
+
url = new URL(util.parseOrigin(url).origin + path74);
|
|
46692
46767
|
} else {
|
|
46693
46768
|
if (!opts) {
|
|
46694
46769
|
opts = typeof url === "object" ? url : {};
|
|
@@ -48676,9 +48751,9 @@ async function runDeviceLogin(opts = {}) {
|
|
|
48676
48751
|
}
|
|
48677
48752
|
|
|
48678
48753
|
// src/cli/commands/logout.ts
|
|
48679
|
-
var
|
|
48754
|
+
var fs49 = __toESM(require("fs"));
|
|
48680
48755
|
var os44 = __toESM(require("os"));
|
|
48681
|
-
var
|
|
48756
|
+
var path47 = __toESM(require("path"));
|
|
48682
48757
|
var import_chalk12 = __toESM(require("chalk"));
|
|
48683
48758
|
async function revokeSelf(creds) {
|
|
48684
48759
|
const url = creds.apiUrl.replace(/\/$/, "") + "/machines/self/disconnect";
|
|
@@ -48696,10 +48771,10 @@ function registerLogoutCommand(program2) {
|
|
|
48696
48771
|
"Disconnect this machine from the cloud (revokes its key; local enforcement keeps running)"
|
|
48697
48772
|
).action(async () => {
|
|
48698
48773
|
const profile = process.env.NODE9_PROFILE || "default";
|
|
48699
|
-
const credPath =
|
|
48774
|
+
const credPath = path47.join(os44.homedir(), ".node9", "credentials.json");
|
|
48700
48775
|
let all = {};
|
|
48701
48776
|
try {
|
|
48702
|
-
all = JSON.parse(
|
|
48777
|
+
all = JSON.parse(fs49.readFileSync(credPath, "utf-8"));
|
|
48703
48778
|
} catch {
|
|
48704
48779
|
}
|
|
48705
48780
|
const entry = all[profile];
|
|
@@ -48729,11 +48804,11 @@ function registerLogoutCommand(program2) {
|
|
|
48729
48804
|
delete all[profile];
|
|
48730
48805
|
if (Object.keys(all).length === 0) {
|
|
48731
48806
|
try {
|
|
48732
|
-
|
|
48807
|
+
fs49.unlinkSync(credPath);
|
|
48733
48808
|
} catch {
|
|
48734
48809
|
}
|
|
48735
48810
|
} else {
|
|
48736
|
-
|
|
48811
|
+
fs49.writeFileSync(credPath, JSON.stringify(all, null, 2), { mode: 384 });
|
|
48737
48812
|
}
|
|
48738
48813
|
console.log(import_chalk12.default.green("\u2713 Local: credentials removed."));
|
|
48739
48814
|
console.log(
|
|
@@ -50871,6 +50946,7 @@ init_costSync();
|
|
|
50871
50946
|
init_litellm();
|
|
50872
50947
|
init_cost_codex();
|
|
50873
50948
|
init_decision();
|
|
50949
|
+
init_session_files();
|
|
50874
50950
|
var TEST_COMMAND_RE3 = /(?:^|\s)(npm\s+(?:run\s+)?test|npx\s+(?:vitest|jest|mocha)|yarn\s+(?:run\s+)?test|pnpm\s+(?:run\s+)?test|vitest|jest|mocha|pytest|py\.test|cargo\s+test|go\s+test|bundle\s+exec\s+rspec|rspec|phpunit|dotnet\s+test)\b/i;
|
|
50875
50951
|
function buildTestTimestamps(allEntries) {
|
|
50876
50952
|
const testTs = /* @__PURE__ */ new Set();
|
|
@@ -51010,7 +51086,7 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
51010
51086
|
try {
|
|
51011
51087
|
const stat = import_fs55.default.statSync(projPath);
|
|
51012
51088
|
if (!stat.isDirectory()) return;
|
|
51013
|
-
files =
|
|
51089
|
+
files = listSessionFiles(projPath);
|
|
51014
51090
|
} catch {
|
|
51015
51091
|
return;
|
|
51016
51092
|
}
|
|
@@ -55479,7 +55555,7 @@ function severityFromScore(score) {
|
|
|
55479
55555
|
if (score >= 1) return "advisory";
|
|
55480
55556
|
return null;
|
|
55481
55557
|
}
|
|
55482
|
-
function analyzeWorkflow(
|
|
55558
|
+
function analyzeWorkflow(path74, content) {
|
|
55483
55559
|
let raw;
|
|
55484
55560
|
try {
|
|
55485
55561
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -55605,7 +55681,7 @@ function analyzeWorkflow(path73, content) {
|
|
|
55605
55681
|
dimension: "workflows",
|
|
55606
55682
|
severity,
|
|
55607
55683
|
title,
|
|
55608
|
-
file:
|
|
55684
|
+
file: path74,
|
|
55609
55685
|
signals,
|
|
55610
55686
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
55611
55687
|
fix: head === "root" && privileged ? "Do not check out the untrusted PR head into the workspace root under a privileged trigger (pull_request_target/workflow_run) \u2014 check out the base ref, or isolate the head in a subdir (--add-dir). Add an actor gate and scope the agent tools." : head === "root" ? "This runs under `pull_request` (fork PRs get a read-only token), so the head checkout is low-risk today \u2014 keep it on `pull_request` (not `pull_request_target`) and keep the actor gate + scoped tools." : "Add/verify an actor gate, scope the agent tools to read-only, and env-deny secrets. See Anthropic\u2019s claude-code-action security doc."
|
|
@@ -55681,7 +55757,7 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
55681
55757
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
55682
55758
|
return { severity, secrets, injectable, canReadEnv };
|
|
55683
55759
|
}
|
|
55684
|
-
function analyzeWorkflowSecrets(
|
|
55760
|
+
function analyzeWorkflowSecrets(path74, content) {
|
|
55685
55761
|
let raw;
|
|
55686
55762
|
try {
|
|
55687
55763
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -55701,7 +55777,7 @@ function analyzeWorkflowSecrets(path73, content) {
|
|
|
55701
55777
|
dimension: "data",
|
|
55702
55778
|
severity: worst.severity,
|
|
55703
55779
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent \u2014 hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
55704
|
-
file:
|
|
55780
|
+
file: path74,
|
|
55705
55781
|
signals: [
|
|
55706
55782
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
55707
55783
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable \u2014 latent risk only",
|
|
@@ -55728,7 +55804,7 @@ function hookCommands(hooks) {
|
|
|
55728
55804
|
}
|
|
55729
55805
|
return out;
|
|
55730
55806
|
}
|
|
55731
|
-
function analyzeAgentConfig(
|
|
55807
|
+
function analyzeAgentConfig(path74, content) {
|
|
55732
55808
|
let cfg;
|
|
55733
55809
|
try {
|
|
55734
55810
|
cfg = JSON.parse(content);
|
|
@@ -55747,7 +55823,7 @@ function analyzeAgentConfig(path73, content) {
|
|
|
55747
55823
|
dimension: "toolRules",
|
|
55748
55824
|
severity: high ? "high" : "medium",
|
|
55749
55825
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
55750
|
-
file:
|
|
55826
|
+
file: path74,
|
|
55751
55827
|
signals: [
|
|
55752
55828
|
`hook command: \`${cmd.slice(0, 120)}\``,
|
|
55753
55829
|
remoteExec ? "fetch-and-run (curl|wget / pipe-to-shell) \u2014 unpinnable remote code execution on every contributor" : unpinned ? "unpinned \u2014 a compromised/yanked package = code execution on every contributor" : "pinned, but still a standing supply-chain dependency in the agent hot path"
|
|
@@ -55767,7 +55843,7 @@ function analyzeAgentConfig(path73, content) {
|
|
|
55767
55843
|
dimension: "toolRules",
|
|
55768
55844
|
severity: hasBackstop ? "medium" : "high",
|
|
55769
55845
|
title: hasBackstop ? "Committed agent config pre-authorizes broad tools" : "Committed agent config pre-authorizes broad tools with no deny backstop",
|
|
55770
|
-
file:
|
|
55846
|
+
file: path74,
|
|
55771
55847
|
signals: [
|
|
55772
55848
|
`broad allow(s): ${broad.slice(0, 5).join(", ")}`,
|
|
55773
55849
|
hasBackstop ? "a `deny` list backstops the broad allow" : "no `deny` entry covers Bash/Write/Edit \u2014 every contributor is pre-authorized for catastrophic tools"
|
|
@@ -55780,16 +55856,16 @@ function analyzeAgentConfig(path73, content) {
|
|
|
55780
55856
|
|
|
55781
55857
|
// src/ci-check/mcp.ts
|
|
55782
55858
|
init_dist();
|
|
55783
|
-
function analyzeMcp(
|
|
55859
|
+
function analyzeMcp(path74, content) {
|
|
55784
55860
|
let cfg;
|
|
55785
55861
|
try {
|
|
55786
55862
|
cfg = JSON.parse(content);
|
|
55787
55863
|
} catch {
|
|
55788
55864
|
return [];
|
|
55789
55865
|
}
|
|
55790
|
-
return analyzeMcpServers(cfg.mcpServers ?? {},
|
|
55866
|
+
return analyzeMcpServers(cfg.mcpServers ?? {}, path74);
|
|
55791
55867
|
}
|
|
55792
|
-
function analyzeMcpServers(servers,
|
|
55868
|
+
function analyzeMcpServers(servers, path74) {
|
|
55793
55869
|
const findings = [];
|
|
55794
55870
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
55795
55871
|
if (!srv || srv.disabled) continue;
|
|
@@ -55800,7 +55876,7 @@ function analyzeMcpServers(servers, path73) {
|
|
|
55800
55876
|
dimension: "mcp",
|
|
55801
55877
|
severity: "medium",
|
|
55802
55878
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
55803
|
-
file:
|
|
55879
|
+
file: path74,
|
|
55804
55880
|
signals: [`\`${argv.slice(0, 120)}\` \u2014 unversioned/@latest npx`],
|
|
55805
55881
|
fix: "Pin the MCP server package to an exact version so a PR (or a registry compromise) can\u2019t swap the toolchain."
|
|
55806
55882
|
});
|
|
@@ -55814,7 +55890,7 @@ function analyzeMcpServers(servers, path73) {
|
|
|
55814
55890
|
dimension: "mcp",
|
|
55815
55891
|
severity: "high",
|
|
55816
55892
|
title: `MCP server "${name}" has an inline credential`,
|
|
55817
|
-
file:
|
|
55893
|
+
file: path74,
|
|
55818
55894
|
signals: [
|
|
55819
55895
|
`env.${k} matches ${hit.patternName} \u2014 agent-reachable secret committed to the repo`
|
|
55820
55896
|
],
|
|
@@ -55828,7 +55904,7 @@ function analyzeMcpServers(servers, path73) {
|
|
|
55828
55904
|
|
|
55829
55905
|
// src/ci-check/codex.ts
|
|
55830
55906
|
var import_smol_toml5 = require("smol-toml");
|
|
55831
|
-
function analyzeCodexConfig(
|
|
55907
|
+
function analyzeCodexConfig(path74, content) {
|
|
55832
55908
|
let cfg;
|
|
55833
55909
|
try {
|
|
55834
55910
|
cfg = (0, import_smol_toml5.parse)(content);
|
|
@@ -55836,7 +55912,7 @@ function analyzeCodexConfig(path73, content) {
|
|
|
55836
55912
|
return [];
|
|
55837
55913
|
}
|
|
55838
55914
|
const findings = [];
|
|
55839
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
55915
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path74));
|
|
55840
55916
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
55841
55917
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
55842
55918
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -55851,7 +55927,7 @@ function analyzeCodexConfig(path73, content) {
|
|
|
55851
55927
|
dimension: "toolRules",
|
|
55852
55928
|
severity: fullAccess ? "high" : "medium",
|
|
55853
55929
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
55854
|
-
file:
|
|
55930
|
+
file: path74,
|
|
55855
55931
|
signals,
|
|
55856
55932
|
fix: 'Commit a least-privilege Codex config: prefer `sandbox_mode = "read-only"` (or `"workspace-write"`) and `approval_policy = "on-request"`/`"on-failure"`. A repo-committed config applies to every contributor who runs Codex here.'
|
|
55857
55933
|
});
|
|
@@ -55907,10 +55983,10 @@ function decodeSuspiciousBase64(text) {
|
|
|
55907
55983
|
}
|
|
55908
55984
|
return out;
|
|
55909
55985
|
}
|
|
55910
|
-
function mk(severity, title, signals, fix,
|
|
55911
|
-
return { check: "CI-6", dimension: "instructions", severity, title, file:
|
|
55986
|
+
function mk(severity, title, signals, fix, path74) {
|
|
55987
|
+
return { check: "CI-6", dimension: "instructions", severity, title, file: path74, signals, fix };
|
|
55912
55988
|
}
|
|
55913
|
-
function analyzeInstructionFile(
|
|
55989
|
+
function analyzeInstructionFile(path74, content) {
|
|
55914
55990
|
const findings = [];
|
|
55915
55991
|
const decoded = decodeSuspiciousBase64(content);
|
|
55916
55992
|
if (TAG_CHARS.test(content))
|
|
@@ -55922,7 +55998,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55922
55998
|
"contains Unicode tag characters (U+E0000\u2013E007F) \u2014 an invisible instruction-smuggling channel with no legitimate use in text"
|
|
55923
55999
|
],
|
|
55924
56000
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
55925
|
-
|
|
56001
|
+
path74
|
|
55926
56002
|
)
|
|
55927
56003
|
);
|
|
55928
56004
|
if (BIDI_OVERRIDE.test(content))
|
|
@@ -55934,7 +56010,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55934
56010
|
"contains a bidi override (U+202D/U+202E) \u2014 a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
|
|
55935
56011
|
],
|
|
55936
56012
|
"Remove the bidi override characters.",
|
|
55937
|
-
|
|
56013
|
+
path74
|
|
55938
56014
|
)
|
|
55939
56015
|
);
|
|
55940
56016
|
else if (BIDI_EMBED_ISOLATE.test(content))
|
|
@@ -55946,7 +56022,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55946
56022
|
"contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069) \u2014 legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
|
|
55947
56023
|
],
|
|
55948
56024
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
55949
|
-
|
|
56025
|
+
path74
|
|
55950
56026
|
)
|
|
55951
56027
|
);
|
|
55952
56028
|
const zw = suspiciousZeroWidth(content);
|
|
@@ -55960,7 +56036,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55960
56036
|
revealed ? "a zero-width character conceals a prompt-override directive that only appears once the hidden characters are stripped" : "a zero-width character splits a visible Latin word \u2014 a concealment technique (hides text from human review while the agent reads it as contiguous)"
|
|
55961
56037
|
],
|
|
55962
56038
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
55963
|
-
|
|
56039
|
+
path74
|
|
55964
56040
|
)
|
|
55965
56041
|
);
|
|
55966
56042
|
}
|
|
@@ -55976,7 +56052,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55976
56052
|
`contains a prompt-override / role-impersonation directive (\`${m[0].slice(0, 60).trim()}\`)${ovEnc ? " \u2014 concealed in a base64 blob" : ""}`
|
|
55977
56053
|
],
|
|
55978
56054
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
55979
|
-
|
|
56055
|
+
path74
|
|
55980
56056
|
)
|
|
55981
56057
|
);
|
|
55982
56058
|
}
|
|
@@ -55988,7 +56064,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
55988
56064
|
"Instruction directs the agent to fetch and run remote code",
|
|
55989
56065
|
[`\`${fo[0].slice(0, 70).trim()}\` \u2014 fetch-and-obey, outside an install/setup section`],
|
|
55990
56066
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
55991
|
-
|
|
56067
|
+
path74
|
|
55992
56068
|
)
|
|
55993
56069
|
);
|
|
55994
56070
|
}
|
|
@@ -56000,7 +56076,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
56000
56076
|
"Instruction points the agent at credential material",
|
|
56001
56077
|
[`references \`${sp[0].slice(0, 50).trim()}\` \u2014 directs the agent toward secrets`],
|
|
56002
56078
|
"Do not reference credential files or paths in agent instructions.",
|
|
56003
|
-
|
|
56079
|
+
path74
|
|
56004
56080
|
)
|
|
56005
56081
|
);
|
|
56006
56082
|
}
|
|
@@ -56012,7 +56088,7 @@ function analyzeInstructionFile(path73, content) {
|
|
|
56012
56088
|
"Instruction directs the agent to send data to an external endpoint",
|
|
56013
56089
|
[`\`${ex[0].slice(0, 70).trim()}\` \u2014 possible exfiltration directive`],
|
|
56014
56090
|
"Remove external post/upload directives from agent instructions.",
|
|
56015
|
-
|
|
56091
|
+
path74
|
|
56016
56092
|
)
|
|
56017
56093
|
);
|
|
56018
56094
|
}
|