@node9/proxy 2.51.0 → 2.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-main.js +2220 -1625
- package/dist/dashboard.mjs +599 -229
- package/dist/hook.js +814 -287
- package/dist/index.js +615 -216
- package/dist/index.mjs +615 -216
- package/dist/scan-ink.mjs +42 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -423,15 +423,15 @@ function ssrfExemptMatches(entries, normalized) {
|
|
|
423
423
|
continue;
|
|
424
424
|
}
|
|
425
425
|
if (!target) continue;
|
|
426
|
-
const
|
|
426
|
+
const base3 = bitsOf(normalizeIpLiteral(entry.slice(0, slash)) ?? "");
|
|
427
427
|
const prefixText = entry.slice(slash + 1);
|
|
428
428
|
const prefix = /^\d+$/.test(prefixText) ? Number(prefixText) : NaN;
|
|
429
|
-
if (!
|
|
429
|
+
if (!base3 || !Number.isInteger(prefix) || prefix < 0 || // A v4 range never matches a v6 address, and the reverse: the widths
|
|
430
430
|
// differ, so `0.0.0.0/0` does not release `::1`.
|
|
431
|
-
|
|
431
|
+
base3.length !== target.length || prefix > base3.length) {
|
|
432
432
|
continue;
|
|
433
433
|
}
|
|
434
|
-
if (
|
|
434
|
+
if (base3.slice(0, prefix) === target.slice(0, prefix)) return true;
|
|
435
435
|
}
|
|
436
436
|
return false;
|
|
437
437
|
}
|
|
@@ -485,6 +485,10 @@ function reviewsEveryAgentFileWrite(mode) {
|
|
|
485
485
|
const level = levelOf(mode);
|
|
486
486
|
return level === "strict" || level === "block-all";
|
|
487
487
|
}
|
|
488
|
+
function holdsSendsWithoutDaemon(mode) {
|
|
489
|
+
const level = levelOf(mode);
|
|
490
|
+
return level === "strict" || level === "block-all";
|
|
491
|
+
}
|
|
488
492
|
function isBlockAll(mode) {
|
|
489
493
|
return levelOf(mode) === "block-all";
|
|
490
494
|
}
|
|
@@ -1689,6 +1693,39 @@ function protectedLiteral(code, isProtected) {
|
|
|
1689
1693
|
}
|
|
1690
1694
|
return null;
|
|
1691
1695
|
}
|
|
1696
|
+
function inlineReadPaths(language, code, preload = {}) {
|
|
1697
|
+
const out = [];
|
|
1698
|
+
const before = READ_BEFORE[language];
|
|
1699
|
+
const after = READ_AFTER[language];
|
|
1700
|
+
const assigned = /* @__PURE__ */ new Map();
|
|
1701
|
+
for (const m of code.matchAll(STRING_LITERAL)) {
|
|
1702
|
+
const raw = m[2].trim();
|
|
1703
|
+
const value = raw.replace(/^[<+]\s*/, "");
|
|
1704
|
+
if (!value) continue;
|
|
1705
|
+
const head = code.slice(Math.max(0, m.index - 160), m.index);
|
|
1706
|
+
const tail = code.slice(m.index + m[0].length, m.index + m[0].length + 40);
|
|
1707
|
+
if (/^[>|]/.test(raw) || WRITE_MODE_AFTER.test(tail) || PERL_WRITE_BEFORE.test(head)) continue;
|
|
1708
|
+
if (before.test(head) || after?.test(tail) || language === "node" && DOTENV_PATH_OPTION.test(head)) {
|
|
1709
|
+
out.push(value);
|
|
1710
|
+
continue;
|
|
1711
|
+
}
|
|
1712
|
+
const name = ASSIGNED.exec(head)?.[1];
|
|
1713
|
+
if (name) assigned.set(name, [...assigned.get(name) ?? [], value]);
|
|
1714
|
+
}
|
|
1715
|
+
if (assigned.size > 0) {
|
|
1716
|
+
const opened = /* @__PURE__ */ new Set();
|
|
1717
|
+
for (const m of code.matchAll(OPENED_NAME[language])) opened.add(m[1] ?? m[2]);
|
|
1718
|
+
for (const [name, values] of assigned) if (opened.has(name)) out.push(...values);
|
|
1719
|
+
}
|
|
1720
|
+
if (language === "python" || language === "node") {
|
|
1721
|
+
const d = DOTENV[language];
|
|
1722
|
+
const readsEnv = d.env.test(code);
|
|
1723
|
+
const loads = /dotenv/.test(code) && d.load.test(code) && !d.literalPath.test(code);
|
|
1724
|
+
if ((loads || preload.dotenv) && (readsEnv || d.values.test(code))) out.push(".env");
|
|
1725
|
+
if (readsEnv) out.push(...preload.envFiles ?? []);
|
|
1726
|
+
}
|
|
1727
|
+
return out;
|
|
1728
|
+
}
|
|
1692
1729
|
function amplifies(language, code) {
|
|
1693
1730
|
const loop = language === "python" ? /\bwhile\s+(?:True|1)\s*:/ : language === "node" ? /\bwhile\s*\(\s*(?:true|1)\s*\)|\bfor\s*\(\s*;\s*;\s*\)|\bsetInterval\s*\(/ : /\bwhile\s*\(?\s*(?:1|true)\s*\)?|\bloop\s+do\b|\bfor\s*\(\s*;\s*;\s*\)/;
|
|
1694
1731
|
const m = loop.exec(code);
|
|
@@ -2543,15 +2580,28 @@ function inlineExecCall(stmt, pipeFed) {
|
|
|
2543
2580
|
const fromStdin = () => {
|
|
2544
2581
|
if (stdinFed) {
|
|
2545
2582
|
const { code, source } = stdinCodeOf(redirs);
|
|
2546
|
-
return { interp, code: [code], source };
|
|
2583
|
+
return { interp, code: [code], source, preload };
|
|
2547
2584
|
}
|
|
2548
2585
|
return { interp, code: [null], source: "pipe" };
|
|
2549
2586
|
};
|
|
2550
2587
|
let positionals2 = 0;
|
|
2551
2588
|
let selectedProgram = false;
|
|
2552
2589
|
const codes = [];
|
|
2590
|
+
const preload = {};
|
|
2591
|
+
const nodeFamily = inlineLanguageOf(interp) === "node";
|
|
2553
2592
|
for (let i = 0; i < args.length; i++) {
|
|
2554
2593
|
const a = args[i];
|
|
2594
|
+
if (nodeFamily && !selectedProgram && codes.length === 0 && a != null) {
|
|
2595
|
+
const flag = NODE_VALUE_FLAG.exec(a);
|
|
2596
|
+
if (flag) {
|
|
2597
|
+
const value = flag[2] ?? args[++i];
|
|
2598
|
+
if (value != null) {
|
|
2599
|
+
if (/^--env-file/.test(flag[1])) (preload.envFiles ??= []).push(value);
|
|
2600
|
+
else if (/^dotenv\/config(?:\.js)?$/.test(value)) preload.dotenv = true;
|
|
2601
|
+
}
|
|
2602
|
+
continue;
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2555
2605
|
if (a == null) {
|
|
2556
2606
|
if (codes.length > 0) break;
|
|
2557
2607
|
positionals2++;
|
|
@@ -2588,7 +2638,12 @@ function inlineExecCall(stmt, pipeFed) {
|
|
|
2588
2638
|
}
|
|
2589
2639
|
}
|
|
2590
2640
|
if (codes.length > 0) {
|
|
2591
|
-
return {
|
|
2641
|
+
return {
|
|
2642
|
+
interp,
|
|
2643
|
+
code: codes,
|
|
2644
|
+
source: codes.includes(null) ? "variable" : void 0,
|
|
2645
|
+
preload
|
|
2646
|
+
};
|
|
2592
2647
|
}
|
|
2593
2648
|
if (positionals2 === 0 && (stdinFed || pipeFed)) {
|
|
2594
2649
|
if (!/^(bash|sh|zsh)$/i.test(interp)) return fromStdin();
|
|
@@ -3411,7 +3466,7 @@ function extractShellDestTokens(command) {
|
|
|
3411
3466
|
}
|
|
3412
3467
|
function analyzeFsOperation(command) {
|
|
3413
3468
|
const normalized = normalizeCommandForPolicy(command);
|
|
3414
|
-
if (!FS_OP_PRESCREEN_RE.test(normalized) && !FS_OP_PRESCREEN_RE.test(command) && !SOURCES_FILE_RE.test(command))
|
|
3469
|
+
if (!FS_OP_PRESCREEN_RE.test(normalized) && !FS_OP_PRESCREEN_RE.test(command) && !SOURCES_FILE_RE.test(command) && !runsInlineInterpreter(command, normalized))
|
|
3415
3470
|
return null;
|
|
3416
3471
|
if (fsOpCache.has(command)) {
|
|
3417
3472
|
const hit = fsOpCache.get(command) ?? null;
|
|
@@ -3419,7 +3474,8 @@ function analyzeFsOperation(command) {
|
|
|
3419
3474
|
fsOpCache.set(command, hit);
|
|
3420
3475
|
return hit;
|
|
3421
3476
|
}
|
|
3422
|
-
const
|
|
3477
|
+
const direct = analyzeFsOperationImpl(command) ?? (INDIRECT_SHAPE_RE.test(command) ? structuralJailRead(command) : null);
|
|
3478
|
+
const computed = direct?.verdict === "block" || !runsInlineInterpreter(command, normalized) ? direct : stricter(direct, inlineCodeJailRead(command));
|
|
3423
3479
|
if (fsOpCache.size >= FS_OP_CACHE_MAX) {
|
|
3424
3480
|
const oldest = fsOpCache.keys().next().value;
|
|
3425
3481
|
if (oldest !== void 0) fsOpCache.delete(oldest);
|
|
@@ -3428,8 +3484,8 @@ function analyzeFsOperation(command) {
|
|
|
3428
3484
|
return computed;
|
|
3429
3485
|
}
|
|
3430
3486
|
function isSensitiveCleanupName(p) {
|
|
3431
|
-
const
|
|
3432
|
-
return /^\.env(\.|$)/i.test(
|
|
3487
|
+
const base3 = p.replace(/^.*[\\/]/, "");
|
|
3488
|
+
return /^\.env(\.|$)/i.test(base3) || /(?:^|[\\/])\.(?:ssh|aws|gnupg|git)(?:[\\/]|$)/i.test(p) || /\.(?:pem|key|p12|pfx|crt)$/i.test(base3) || /^\.?(?:netrc|npmrc|pgpass|htpasswd)$/i.test(base3) || /^id_(?:rsa|dsa|ecdsa|ed25519)/i.test(base3) || /credential/i.test(p) || /secret/i.test(base3);
|
|
3433
3489
|
}
|
|
3434
3490
|
function isWaivableCleanupTarget(p) {
|
|
3435
3491
|
if (/^[/~]/.test(p) || /^\$/.test(p)) return false;
|
|
@@ -4158,6 +4214,24 @@ function structuralJailRead(command) {
|
|
|
4158
4214
|
}
|
|
4159
4215
|
return review;
|
|
4160
4216
|
}
|
|
4217
|
+
function inlineCodeJailRead(command) {
|
|
4218
|
+
const calls = inlineExecCalls(command);
|
|
4219
|
+
if (calls === PARSE_FAIL) return null;
|
|
4220
|
+
let review = null;
|
|
4221
|
+
for (const call of calls) {
|
|
4222
|
+
const language = inlineLanguageOf(call.interp);
|
|
4223
|
+
if (language === null) continue;
|
|
4224
|
+
for (const code of call.code) {
|
|
4225
|
+
if (code === null) continue;
|
|
4226
|
+
for (const p of inlineReadPaths(language, code, call.preload)) {
|
|
4227
|
+
const hit = matchSensitivePath(p);
|
|
4228
|
+
if (hit?.verdict === "block") return hit;
|
|
4229
|
+
review ??= hit;
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
return review;
|
|
4234
|
+
}
|
|
4161
4235
|
function baseWord(w) {
|
|
4162
4236
|
return (w ?? "").split("/").pop()?.toLowerCase() ?? "";
|
|
4163
4237
|
}
|
|
@@ -4715,6 +4789,21 @@ function hits(access, paths, directories, context) {
|
|
|
4715
4789
|
}
|
|
4716
4790
|
return false;
|
|
4717
4791
|
}
|
|
4792
|
+
function hitsNode9Dir(access, dirs, context) {
|
|
4793
|
+
const home = context.homeDirs?.[0] ?? "~";
|
|
4794
|
+
if (access.glob) {
|
|
4795
|
+
const pattern = normalizeFilePath(access.glob, access.cwd ?? context.cwd, home);
|
|
4796
|
+
const magic = pattern.search(/[*?[{]/);
|
|
4797
|
+
const literal = magic < 0 ? pattern : pattern.slice(0, pattern.lastIndexOf("/", magic));
|
|
4798
|
+
return dirs.some((d) => within(literal, d));
|
|
4799
|
+
}
|
|
4800
|
+
const candidates = access.candidates ?? [
|
|
4801
|
+
normalizeFilePath(access.path, access.cwd ?? context.cwd, home)
|
|
4802
|
+
];
|
|
4803
|
+
return candidates.some(
|
|
4804
|
+
(p) => dirs.some((d) => within(p, d)) || access.recursive === true && dirs.some((d) => within(d, p))
|
|
4805
|
+
);
|
|
4806
|
+
}
|
|
4718
4807
|
function hitsSystemDir(access, context, dirs = SYSTEM_DIRS) {
|
|
4719
4808
|
const home = context.homeDirs?.[0] ?? "~";
|
|
4720
4809
|
const candidates = access.candidates ?? [
|
|
@@ -4755,6 +4844,7 @@ function evaluateProtectedFileAccess(accesses, context, settings) {
|
|
|
4755
4844
|
const consider = (result) => {
|
|
4756
4845
|
if (!best || RANK[result.decision] > RANK[best.decision]) best = result;
|
|
4757
4846
|
};
|
|
4847
|
+
const node9Dirs = homes.map((home) => `${home.replace(/\/$/, "")}/.node9`);
|
|
4758
4848
|
for (const access of accesses) {
|
|
4759
4849
|
const mutation = access.operation !== "read";
|
|
4760
4850
|
let kind;
|
|
@@ -4783,6 +4873,10 @@ function evaluateProtectedFileAccess(accesses, context, settings) {
|
|
|
4783
4873
|
"files.system-dirs",
|
|
4784
4874
|
"review-root-home-read",
|
|
4785
4875
|
"Reading the root account's home requires approval"
|
|
4876
|
+
] : mutation && hitsNode9Dir(access, node9Dirs, context) ? [
|
|
4877
|
+
"commands.node9-disarm",
|
|
4878
|
+
"review-node9-disarm",
|
|
4879
|
+
"Changing node9's own files requires approval"
|
|
4786
4880
|
] : null;
|
|
4787
4881
|
} catch {
|
|
4788
4882
|
consider(incompleteFileVerdict(access.operation));
|
|
@@ -5388,9 +5482,9 @@ function validateBelgianNationalNumber(raw) {
|
|
|
5388
5482
|
if (!/^\d{11}$/.test(d)) return false;
|
|
5389
5483
|
const month = Number(d.slice(2, 4)) % 20;
|
|
5390
5484
|
if (month !== 0 && !plausibleDate(String(month).padStart(2, "0"), d.slice(4, 6))) return false;
|
|
5391
|
-
const
|
|
5485
|
+
const base3 = Number(d.slice(0, 9));
|
|
5392
5486
|
const check = Number(d.slice(9, 11));
|
|
5393
|
-
return 97 -
|
|
5487
|
+
return 97 - base3 % 97 === check || 97 - (2e9 + base3) % 97 === check;
|
|
5394
5488
|
}
|
|
5395
5489
|
function validateCuit(raw) {
|
|
5396
5490
|
const d = raw.replace(/-/g, "");
|
|
@@ -6492,9 +6586,9 @@ function evaluateGitHooksFileAccess(args, accesses, context, settings, shell) {
|
|
|
6492
6586
|
}
|
|
6493
6587
|
function agentFileKind(p) {
|
|
6494
6588
|
const lower2 = p.toLowerCase();
|
|
6495
|
-
const
|
|
6496
|
-
if (INSTRUCTION_NAMES.has(
|
|
6497
|
-
if (
|
|
6589
|
+
const base3 = lower2.slice(lower2.lastIndexOf("/") + 1);
|
|
6590
|
+
if (INSTRUCTION_NAMES.has(base3)) return "instructions";
|
|
6591
|
+
if (base3 === "copilot-instructions.md" && lower2.endsWith("/.github/" + base3))
|
|
6498
6592
|
return "instructions";
|
|
6499
6593
|
if (/\/\.cursor\/rules(?:\/|$)/.test(lower2)) return "instructions";
|
|
6500
6594
|
if (/\/\.claude\/projects\/[^/]+\/memory(?:\/|$)/.test(lower2)) return "memory";
|
|
@@ -6663,7 +6757,7 @@ function evaluateAgentFileWrite(args, accesses, context, settings, shell, hooks
|
|
|
6663
6757
|
skills: "agent skill",
|
|
6664
6758
|
settings: "agent settings"
|
|
6665
6759
|
};
|
|
6666
|
-
const
|
|
6760
|
+
const base3 = `${kindLabel[kind]} written: ${access.path}`;
|
|
6667
6761
|
if (!signal && !every) {
|
|
6668
6762
|
return {
|
|
6669
6763
|
decision: "allow",
|
|
@@ -6673,14 +6767,14 @@ function evaluateAgentFileWrite(args, accesses, context, settings, shell, hooks
|
|
|
6673
6767
|
path: access.path,
|
|
6674
6768
|
operation: access.operation,
|
|
6675
6769
|
kind,
|
|
6676
|
-
reason:
|
|
6770
|
+
reason: base3,
|
|
6677
6771
|
ruleDescription: "The AI writes to a file every later agent session loads as instructions.",
|
|
6678
|
-
blockedByLabel: `Node9 Files: ${
|
|
6772
|
+
blockedByLabel: `Node9 Files: ${base3}`,
|
|
6679
6773
|
tier: 2
|
|
6680
6774
|
};
|
|
6681
6775
|
}
|
|
6682
6776
|
const ruleName = signal === "content" ? "review-agent-file-content" : signal === "hooks" ? "review-agent-hooks-change" : "review-agent-file-write";
|
|
6683
|
-
const reason = signal ? `${
|
|
6777
|
+
const reason = signal ? `${base3} (${detail})` : base3;
|
|
6684
6778
|
const description = signal === "content" ? "The AI writes an instruction into a file every later agent session loads: to hide something from you, to skip approvals or the guard, or to read or send a secret. It would persist past this session; confirm it is yours." : signal === "hooks" ? "The AI changes the hooks in the agent's settings. Hooks are how node9 and your other checks run before each tool call; a change here can disarm them." : "The AI writes to a file every later agent session loads as instructions (CLAUDE.md, AGENTS.md, memory, agents, commands). Confirm the change is yours.";
|
|
6685
6779
|
return {
|
|
6686
6780
|
decision: value === "log" ? "allow" : value,
|
|
@@ -8288,6 +8382,139 @@ function scanArgumentSecrets(args) {
|
|
|
8288
8382
|
severity: "review"
|
|
8289
8383
|
} : null;
|
|
8290
8384
|
}
|
|
8385
|
+
function patternSelects(pattern, targets) {
|
|
8386
|
+
const pieces = pattern.toLowerCase().split(/[\\^$.*+?()[\]{}|]+/).filter(Boolean);
|
|
8387
|
+
if (pieces.length === 0) return false;
|
|
8388
|
+
return targets.some((t) => pieces.every((p) => t.includes(p)));
|
|
8389
|
+
}
|
|
8390
|
+
function sourceText(bytes, pos, end) {
|
|
8391
|
+
if (typeof pos !== "number" || typeof end !== "number" || pos < 0 || end < pos) return "";
|
|
8392
|
+
return new TextDecoder().decode(bytes.subarray(pos, end));
|
|
8393
|
+
}
|
|
8394
|
+
function nextOperand(words, from) {
|
|
8395
|
+
for (let i = from; i < words.length; i++) {
|
|
8396
|
+
const w = words[i];
|
|
8397
|
+
if (w !== null && w.startsWith("-")) continue;
|
|
8398
|
+
return i;
|
|
8399
|
+
}
|
|
8400
|
+
return -1;
|
|
8401
|
+
}
|
|
8402
|
+
function node9Command(words, h) {
|
|
8403
|
+
const head = base2(words[h]);
|
|
8404
|
+
if (head !== "node9" && head !== "node9.cmd" && words[h] !== "@node9/proxy") return null;
|
|
8405
|
+
const s = nextOperand(words, h + 1);
|
|
8406
|
+
const sub = s < 0 ? "" : (words[s] ?? "").toLowerCase();
|
|
8407
|
+
if (sub === "uninstall") return "node9 uninstall";
|
|
8408
|
+
if (sub !== "daemon") return null;
|
|
8409
|
+
const a = nextOperand(words, s + 1);
|
|
8410
|
+
const action = a < 0 ? "" : (words[a] ?? "").toLowerCase();
|
|
8411
|
+
return action === "stop" || action === "uninstall" ? `node9 daemon ${action}` : null;
|
|
8412
|
+
}
|
|
8413
|
+
function killsDaemon(words, texts, h, daemonPid) {
|
|
8414
|
+
const head = base2(words[h]);
|
|
8415
|
+
const args = words.slice(h + 1);
|
|
8416
|
+
if (head === "kill") {
|
|
8417
|
+
for (let i = 0; i < args.length; i++) {
|
|
8418
|
+
const w = args[i];
|
|
8419
|
+
if (w === "-s" || w === "-n") {
|
|
8420
|
+
i++;
|
|
8421
|
+
continue;
|
|
8422
|
+
}
|
|
8423
|
+
if (w !== null && w.startsWith("-")) continue;
|
|
8424
|
+
if (w === null) {
|
|
8425
|
+
if (HOME_PID_FILE_RE.test(texts[h + 1 + i] ?? "")) return "kill of the pid in daemon.pid";
|
|
8426
|
+
continue;
|
|
8427
|
+
}
|
|
8428
|
+
if (daemonPid !== null && w === String(daemonPid)) return `kill ${w} (the node9 daemon)`;
|
|
8429
|
+
}
|
|
8430
|
+
return null;
|
|
8431
|
+
}
|
|
8432
|
+
if (head === "pkill") {
|
|
8433
|
+
let full = false;
|
|
8434
|
+
let pattern = null;
|
|
8435
|
+
for (let i = 0; i < args.length; i++) {
|
|
8436
|
+
const w = args[i];
|
|
8437
|
+
if (w === null) continue;
|
|
8438
|
+
if (PKILL_VALUE_FLAGS.has(w)) {
|
|
8439
|
+
i++;
|
|
8440
|
+
continue;
|
|
8441
|
+
}
|
|
8442
|
+
if (w === "--full") full = true;
|
|
8443
|
+
else if (/^-[a-zA-Z]+$/.test(w) && w.includes("f")) full = true;
|
|
8444
|
+
if (w.startsWith("-")) continue;
|
|
8445
|
+
pattern = w;
|
|
8446
|
+
}
|
|
8447
|
+
if (pattern === null) return null;
|
|
8448
|
+
return patternSelects(pattern, full ? DAEMON_CMDLINES : DAEMON_NAMES) ? `pkill ${full ? "-f " : ""}${pattern}` : null;
|
|
8449
|
+
}
|
|
8450
|
+
if (head === "killall") {
|
|
8451
|
+
const regex = args.some((w) => w === "-r" || w === "--regexp");
|
|
8452
|
+
for (const w of args) {
|
|
8453
|
+
if (w === null || w.startsWith("-")) continue;
|
|
8454
|
+
if (regex ? patternSelects(w, DAEMON_NAMES) : KILLALL_NAMES.has(w.toLowerCase()))
|
|
8455
|
+
return `killall ${w}`;
|
|
8456
|
+
}
|
|
8457
|
+
return null;
|
|
8458
|
+
}
|
|
8459
|
+
if (head === "taskkill" || head === "taskkill.exe") {
|
|
8460
|
+
for (let i = 0; i < args.length - 1; i++) {
|
|
8461
|
+
const flag = (args[i] ?? "").toLowerCase();
|
|
8462
|
+
const value = (args[i + 1] ?? "").toLowerCase();
|
|
8463
|
+
if ((flag === "/im" || flag === "-im") && KILLALL_NAMES.has(value))
|
|
8464
|
+
return `taskkill /IM ${value}`;
|
|
8465
|
+
if ((flag === "/pid" || flag === "-pid") && daemonPid !== null && value === String(daemonPid))
|
|
8466
|
+
return `taskkill /PID ${value} (the node9 daemon)`;
|
|
8467
|
+
}
|
|
8468
|
+
}
|
|
8469
|
+
return null;
|
|
8470
|
+
}
|
|
8471
|
+
function stopsService(words, h) {
|
|
8472
|
+
const head = base2(words[h]);
|
|
8473
|
+
const args = words.slice(h + 1).map((w) => (w ?? "").toLowerCase());
|
|
8474
|
+
if (head === "systemctl") {
|
|
8475
|
+
const action = args.find((w) => STOP_SYSTEMCTL.has(w));
|
|
8476
|
+
if (action && args.some((w) => /^node9-daemon(\.service)?$/.test(w)))
|
|
8477
|
+
return `systemctl ${action} node9-daemon`;
|
|
8478
|
+
}
|
|
8479
|
+
if (head === "launchctl") {
|
|
8480
|
+
const action = args.find((w) => STOP_LAUNCHCTL.has(w));
|
|
8481
|
+
if (action && args.some((w) => w.includes("ai.node9.daemon")))
|
|
8482
|
+
return `launchctl ${action} ai.node9.daemon`;
|
|
8483
|
+
}
|
|
8484
|
+
return null;
|
|
8485
|
+
}
|
|
8486
|
+
function analyzeNode9Disarm(command, daemonPid = null, depth = 0) {
|
|
8487
|
+
if (depth > 3 || !NAME_PRESCREEN_RE.test(command.replace(/[\\'"]/g, ""))) return null;
|
|
8488
|
+
let shown = null;
|
|
8489
|
+
const bytes = new TextEncoder().encode(command);
|
|
8490
|
+
try {
|
|
8491
|
+
walkCommandScope(command, (node) => {
|
|
8492
|
+
if (shown !== null) return false;
|
|
8493
|
+
const n = node;
|
|
8494
|
+
if (!n || n.kind !== "CallExpr") return true;
|
|
8495
|
+
const words = (n.Args || []).map((a) => resolveWordLiteral(a));
|
|
8496
|
+
if (words.length === 0) return true;
|
|
8497
|
+
const texts = (n.Args || []).map((a) => sourceText(bytes, a.pos, a.end));
|
|
8498
|
+
const h = unwrapCommandHead(words);
|
|
8499
|
+
shown = node9Command(words, h) ?? killsDaemon(words, texts, h, daemonPid) ?? stopsService(words, h);
|
|
8500
|
+
if (shown === null) {
|
|
8501
|
+
const payload = literalShellPayload(words, base2(words[0]));
|
|
8502
|
+
if (payload) {
|
|
8503
|
+
const inner = analyzeNode9Disarm(payload, daemonPid, depth + 1);
|
|
8504
|
+
if (inner) shown = inner.reason.replace(/^node9 switched off by the agent: /, "");
|
|
8505
|
+
}
|
|
8506
|
+
}
|
|
8507
|
+
return true;
|
|
8508
|
+
});
|
|
8509
|
+
} catch {
|
|
8510
|
+
}
|
|
8511
|
+
if (shown === null) return null;
|
|
8512
|
+
return {
|
|
8513
|
+
ruleName: RULE_NAME2,
|
|
8514
|
+
reason: `node9 switched off by the agent: ${shown}`,
|
|
8515
|
+
description: DESCRIPTION
|
|
8516
|
+
};
|
|
8517
|
+
}
|
|
8291
8518
|
function catalogSettings(config) {
|
|
8292
8519
|
return catalogSettingsFromConfig(config.settings, config.policy);
|
|
8293
8520
|
}
|
|
@@ -8381,6 +8608,10 @@ function egressPolicyVerdict(eg) {
|
|
|
8381
8608
|
};
|
|
8382
8609
|
}
|
|
8383
8610
|
async function evaluatePolicy(config, toolName, args, context = {}, hostHooks = {}) {
|
|
8611
|
+
const v = await evaluatePolicyVerdict(config, toolName, args, context, hostHooks);
|
|
8612
|
+
return v.decision === "block" && v.checkId !== void 0 && NOT_OVERRIDABLE_CHECKS.has(v.checkId) ? { ...v, overridable: false } : v;
|
|
8613
|
+
}
|
|
8614
|
+
async function evaluatePolicyVerdict(config, toolName, args, context = {}, hostHooks = {}) {
|
|
8384
8615
|
let protectedVerdict = null;
|
|
8385
8616
|
const layers = inspectionLayers(config.policy);
|
|
8386
8617
|
if (context.agent !== "Terminal") {
|
|
@@ -8438,7 +8669,7 @@ async function evaluatePolicy(config, toolName, args, context = {}, hostHooks =
|
|
|
8438
8669
|
}
|
|
8439
8670
|
async function evaluatePolicyCore(config, toolName, args, context = {}, hooks = {}) {
|
|
8440
8671
|
const { agent, cwd, activeEnvironment } = context;
|
|
8441
|
-
const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2 } = hooks;
|
|
8672
|
+
const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2, daemonPid } = hooks;
|
|
8442
8673
|
const settingsView = catalogSettings(config);
|
|
8443
8674
|
const layers = inspectionLayers(config.policy);
|
|
8444
8675
|
const cv = (id) => checkValue(settingsView, id);
|
|
@@ -8623,6 +8854,23 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
|
|
|
8623
8854
|
else if (v && !pendingAstReview) pendingAstReview = v;
|
|
8624
8855
|
}
|
|
8625
8856
|
}
|
|
8857
|
+
if (cv("commands.node9-disarm") !== "off") {
|
|
8858
|
+
const finding = analyzeNode9Disarm(bashCommand, daemonPid?.() ?? null);
|
|
8859
|
+
if (finding) {
|
|
8860
|
+
const v = applyCheckValue(cv("commands.node9-disarm"), {
|
|
8861
|
+
decision: "review",
|
|
8862
|
+
blockedByLabel: `Node9 (AST): ${finding.ruleName}`,
|
|
8863
|
+
reason: finding.reason,
|
|
8864
|
+
tier: 2,
|
|
8865
|
+
ruleName: finding.ruleName,
|
|
8866
|
+
ruleDescription: finding.description,
|
|
8867
|
+
checkId: "commands.node9-disarm"
|
|
8868
|
+
});
|
|
8869
|
+
if (v?.logged) noteLogged(v);
|
|
8870
|
+
else if (v?.decision === "block") return v;
|
|
8871
|
+
else if (v && !pendingAstReview) pendingAstReview = v;
|
|
8872
|
+
}
|
|
8873
|
+
}
|
|
8626
8874
|
}
|
|
8627
8875
|
if (config.policy.smartRules.length > 0) {
|
|
8628
8876
|
const rmCleanupWaiver = bashCommand !== null && isRmCreatedInCommandCleanup(bashCommand);
|
|
@@ -9070,8 +9318,8 @@ function hasRoutingNumber(text) {
|
|
|
9070
9318
|
}
|
|
9071
9319
|
return false;
|
|
9072
9320
|
}
|
|
9073
|
-
function* validCardRuns(text,
|
|
9074
|
-
const re = new RegExp(
|
|
9321
|
+
function* validCardRuns(text, base3, exemptFractions = true) {
|
|
9322
|
+
const re = new RegExp(base3.source, "g");
|
|
9075
9323
|
let m;
|
|
9076
9324
|
while ((m = re.exec(text)) !== null) {
|
|
9077
9325
|
const digits = m[0].replace(/\D/g, "");
|
|
@@ -9084,17 +9332,17 @@ function* validCardRuns(text, base2, exemptFractions = true) {
|
|
|
9084
9332
|
}
|
|
9085
9333
|
}
|
|
9086
9334
|
function hasValidCard(text) {
|
|
9087
|
-
for (const
|
|
9088
|
-
if (!validCardRuns(text,
|
|
9335
|
+
for (const base3 of CARD_PATTERNS) {
|
|
9336
|
+
if (!validCardRuns(text, base3).next().done) return true;
|
|
9089
9337
|
}
|
|
9090
9338
|
return false;
|
|
9091
9339
|
}
|
|
9092
9340
|
function replaceValidCards(text, replace, { exemptFractions = true } = {}) {
|
|
9093
9341
|
let out = text;
|
|
9094
|
-
for (const
|
|
9342
|
+
for (const base3 of CARD_PATTERNS) {
|
|
9095
9343
|
let res = "";
|
|
9096
9344
|
let last = 0;
|
|
9097
|
-
for (const run of validCardRuns(out,
|
|
9345
|
+
for (const run of validCardRuns(out, base3, exemptFractions)) {
|
|
9098
9346
|
res += out.slice(last, run.index) + replace(run.digits);
|
|
9099
9347
|
last = run.index + run.length;
|
|
9100
9348
|
}
|
|
@@ -9335,9 +9583,9 @@ function maskLeaf(value, key, depth) {
|
|
|
9335
9583
|
const used = /* @__PURE__ */ new Set();
|
|
9336
9584
|
return Object.fromEntries(
|
|
9337
9585
|
Object.entries(value).map(([k, v]) => {
|
|
9338
|
-
const
|
|
9339
|
-
let name =
|
|
9340
|
-
for (let n = 2; used.has(name); n++) name = `${
|
|
9586
|
+
const base3 = maskPersonalData(k);
|
|
9587
|
+
let name = base3;
|
|
9588
|
+
for (let n = 2; used.has(name); n++) name = `${base3}#${n}`;
|
|
9341
9589
|
used.add(name);
|
|
9342
9590
|
return [name, maskLeaf(v, k, depth + 1)];
|
|
9343
9591
|
})
|
|
@@ -9831,7 +10079,7 @@ function matchCanaryArgs(args, values) {
|
|
|
9831
10079
|
return null;
|
|
9832
10080
|
}
|
|
9833
10081
|
}
|
|
9834
|
-
var getFilename, __filename2, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, finance_default, identity_default, publishing_default, settings_default, branches_default, ACTION_TEMPLATES, ACTION_CHECKS, GAP, prog, httpTo, httpWrite, HTTP_WRITE, HTTP_WRITE_ANY, NOT_STRIPE_TEST, postTo, STRIPE_OBJECTS, APP_SHIELD_SPECS, APP_SHIELDS, APP_SHIELD_NAMES, APP_SERVER_GLOB, GENERAL_ACTION_RULES, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, CHECK_TEXT, LEVELS, MODE_VALUES, SOFT, STRICT, BLOCK_ALL, LEVEL_CHECKS, ASI, ASI_IDS, PACK_SHIELD_OWASP, PACK_RULE_OWASP, VERDICTS, CHECK_VERDICT_RANK, ALL, BUILTIN_DANGEROUS_WORDS, PRODUCT_CHECKS, SHIELD_RULE_NAME, SHIELD_RULES_FOLDED_INTO_PRODUCT, CHECKS, CHECK_BY_ID, LEGACY_TO_ID, PROJECT_JAIL_BLOCK_READ, OVERRIDE_PREFIX, LABEL_WRAPPERS, LEGACY_READERS, syntax, KINDS, STRUCTS, unknownKinds, INVISIBLE_RE, INVISIBLE_ONE, HOMOGLYPHS, HOMOGLYPH_RE, MAX_BLOBS, MIN_DECODED, BASE64_RUN_RE, HEX_RUN_RE, HEX_ESCAPE_RUN_RE, SYSTEM_AUTH_FILES, SYSTEM_AUTH_DIRS, PASSWORD_HASH_FILES, STARTUP_NAMES, SYSTEM_DIRS, SYSTEM_DIRS_EXEMPT, UPLOAD_SYSTEM_DIRS, AGENT_INSTRUCTION_FILES, AGENT_INSTRUCTION_DIRS, LEGACY_SYSTEM_PATH_RE, MAX_ALTERNATIVES, MAX_CALL_DEPTH, MAX_CALL_WALKS, MAX_XARGS_PAYLOAD, POSITIONAL, MAX_DEPTH, MAX_PAYLOAD_DEPTH, unique, clone, SENDING_STDIN, DOWNLOAD_SHORT_VALUE, DOWNLOAD_LONG_VALUE, DOWNLOAD_OUTPUT_FLAGS, DOWNLOAD_DIR_FLAGS, base, quoteGlob, asWord, ops, MAX_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, codeBodiesCache, AST_CACHE_MAX, astCache, PARSE_FAIL, INTERPRETER_LINE, PROGRAM_DIR, ACCESS_VIEW_CACHE_MAX, accessViewCache, MAX_READING_PAYLOADS, STDIN_CODE_INTERPRETERS, RUNS_TEXT_ELSEWHERE, defaultExpansionOps, EMPTY_NAMES, VARIABLE_READERS, PLAIN_PROGRAM_NAME, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, CURL_SOURCE_FLAGS, CURL_VALUE_LETTERS, WGET_VALUE_LETTERS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, 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, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, INTERP_LEADING_TARGET, MAX_PAYLOAD_NESTING, payloadNesting, MAX_INLINE_CALLS, INLINE_EXEC_FALLBACK, UNREADABLE_SOURCE, SCRIPT_RUNNERS, SCRIPT_RUNNER_VALUE_FLAGS, MAX_SCRIPT_OPERANDS, NET_BINARIES, VALUE_FLAGS, HOME_VARIABLES, assignmentTable, currentStmtOffset, PAYLOAD_BUDGET, payloadBudget, seenPayloads, UNANALYSABLE_NESTING, ASSIGNMENT_HEADS, andOrOps, ARRAY_MARK, ARRAY_SEP, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, INDIRECT_SHAPE_RE, SOURCES_FILE_RE, SHELL_SET_VARS, pipeOps, callWords, JAILED_GLOB_NAMES, JAILED_DIR_NAMES, shellGlob, GLOB_META, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, exempt, RANK, SEQUENCE_OPS, BIP39_ENGLISH, BIP39_PUBLIC_VECTORS, indices, lengths, hash, MAX_MNEMONIC_HASHES, SECRET_VIEW_LIMITS, IBAN_LENGTH, IBAN_BBAN_SHAPE, B58, B58_INDEX, XPRV_VERSIONS, B62, CRC32_TABLE, GITHUB_TOKEN_RE, B64URL, B64URL_INDEX, CASK_TWO_ZERO_SUFFIX, CASK_FOUR_ZERO_SUFFIX, CF_ODD, CF_EVEN, SPANISH_LETTERS, HETU_CHARS, VERHOEFF_D, VERHOEFF_P, MAX, UNTRUSTED_TOOLS, INJECTION_SIGNALS, MENTION_QUOTE_RE, MENTION_WORD_RE, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, REFERENCE_VALUE_RE, IDENTIFIER_VALUE_RE, PATH_VALUE_RE, DOTTED_REFERENCE_RE, CONCATENATION_RE, EMAIL_VALUE_RE, FIXTURE_NAME_RE, DERIVATIVE_NAME_RE, QUERY_CREDENTIAL_VALUE_RE, OTP_SECRET_RE, OTP_DOC_SECRETS, ASSIGNED_SECRET_VALUE_RE, ASSIGNED_SECRET_NAME_RE, NAME_KEYWORD_RE, ARN_CONTEXT_RE, CIPHER_KEY_NAME_RE, CIPHER_NAME_PARTS, CIPHER_KEY_VALUE_RE, LARAVEL_KEY_VALUE_RE, SQL_PASSWORD_VALUE_RE, GRAFANA_KEY_VALUE_RE, BASIC_VALUE_RE, BASIC_PAIR_RE, BASIC_HEADER_RE, BASIC_HEADER_PAIR_RE, BASIC_PLACEHOLDER_RE, BASIC_TEMPLATE_MARKERS, DROPBOX_SECRET_RE, OTP_CAPTURE_RE, DB_URL_PASSWORD_RE, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, SENSITIVE_PATH_REGEXES, MAX_DEPTH2, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, BATCH_SEPARATOR, IMPERATIVE, SECRET_TARGET, GUARD, SIGNALS, DESTINATION_RE, REUSED_SIGNALS, NEVER_NEGATED, NEGATION_BEFORE, RDR_IN, COPY_VERBS2, LITERAL_VERBS, GIT_PRESCREEN_RE, MAX_PAYLOAD_DEPTH2, MAX_ALIAS_DEPTH, CACHE_MAX, cache, PAYLOAD_SHELLS, CONFIG_SCOPE_FLAGS, CONFIG_VALUE_FLAGS, GLOBAL_VALUE_OPTIONS, GLOBAL_FLAG_OPTIONS, MAX_LOOP_ITEMS, GitWalk, POSITIONAL2, NO_VARS, NO_APPENDS, FORCE_PUSH, DESTRUCTIVE, UNREADABLE, PUSH_LONG_VALUE, BRANCH_LONG_VALUE, TAG_LONG_VALUE, CLEAN_LONG_VALUE, RESTORE_LONG_VALUE, CHECKOUT_LONG_VALUE, HOOKS_BYPASS, NO_VERIFY_SUBS, HOOK_KILL_SWITCHES, COMMIT_LONG_VALUE, CHMOD_OPTION_RE, _appendOp, STAGE_ALL, ADD_LONG_VALUE, CHECK_ID, RULE_NAME, INERT_LINE_RE, CHECK_ID2, INSTRUCTION_NAMES, SETTINGS_RE, HOOK_WORDS_RE, SHELLS, NETCATS, NET_CLIENTS, SENDERS, NETCAT_EXEC_LONG, DECL_DUMPS, PROC_ENVIRON_RE, DEV_NET_RE, SOCAT_PROGRAM_RE, SOCAT_NET_RE, PRESCREEN_RE, MAX_PAYLOAD_DEPTH3, CACHE_MAX2, cache2, dupInOp, REVERSE_SHELL_DESCRIPTION, ENV_EXFIL_DESCRIPTION, DYNAMIC_WORD, MULTICALL, SHELL_VALUE_OPTIONS, INTERPRETERS, OutboundWalk, NPM_INSTALL_VERBS, NPM_EXEC_VERBS, PNPM_INSTALL_VERBS, YARN_INSTALL_VERBS, BUN_INSTALL_VERBS, DLX_VERBS, NON_REGISTRY_RE, NPM_NAME_RE, EXACT_SEMVER_RE, NPM_VALUE_FLAGS, PNPM_VALUE_FLAGS, YARN_VALUE_FLAGS, BUN_VALUE_FLAGS, PIP_VALUE_FLAGS, UV_VALUE_FLAGS, POETRY_VALUE_FLAGS, PIPENV_VALUE_FLAGS, PIPX_VALUE_FLAGS, PY_SPEC_RE, PY_EXACT_RE, EXACT_VERSION_RE, GEM_NAME_RE, GEM_VALUE_FLAGS, BUNDLE_VALUE_FLAGS, CRATE_NAME_RE, CARGO_ADD_VALUE_FLAGS, CARGO_INSTALL_VALUE_FLAGS, GO_VALUE_FLAGS, GO_PATH_RE, NUGET_NAME_RE, DOTNET_ADD_VALUE_FLAGS, DOTNET_TOOL_VALUE_FLAGS, NUGET_VALUE_FLAGS, MAVEN_COORD_RE, COMPOSER_NAME_RE, COMPOSER_VALUE_FLAGS, EDITOR_HEADS, EXTENSION_ID_RE, MANAGER_HEADS, SHELLS2, MAX_NESTING, SHELL_VALUE_FLAGS, NPM_FAMILY, PIP_FAMILY, NPM_FETCH_VERBS, PIP_FETCH_VERBS, NPM_FLAGS, PIP_FLAGS, NPM_VARS, PIP_VARS, PRESCREEN_RE2, PIP_ATTACHED_RE, MAX_PAYLOAD_DEPTH4, PUBLIC_REGISTRY_HOSTS, TUNING_FIELDS, MAP_GOVERNED, KNOB_GOVERNED, CONFIGURABLE_CHECK_IDS, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, MCP_DESTINATION_KEYS, ARGUMENT_SCAN_LIMITS, RUN_CHAR, runChar, VERDICT_RANK, SQL_DML_KEYWORDS, MAX_DESTINATIONS, MAX_SCAN_CHARS, EMAIL_RE, URL_RE, IBAN_RE, RECIPIENT_KEYS, DESTRUCTIVE_VERB_RE, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_CC14_RE, PII_CC13_RE, PII_CC19_RE, CARD_PATTERNS, PII_ROUTING_RE, ROUTING_LABEL_RE, ROUTING_LABEL_WINDOW, NATIONAL_ID_SHAPES, NATIONAL_ID_LABEL_RE, NATIONAL_ID_LABEL_CS_RE, idLabelIn, NATIONAL_ID_LABEL_WINDOW, NATIONAL_ID_GUARD_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, IBAN_DESTINATION_KEYS, WHOLE_IBAN_RE, JSON_ESCAPE_RE, JSON_ESCAPES, MASKED_KINDS, ENTRY_RE, IBAN_TEXT_RE, EMAIL_TEXT_RE, ACCOUNT_KEY_RE, ACCOUNT_VALUE_RE, MAX_MASK_DEPTH, EMPTY, CURL_SEND_FLAGS, WGET_SEND_FLAGS, IWR_SEND_FLAGS, WRITE_METHODS, GH_READ, GH_WRITE, GH_HOSTNAME_FLAGS, GH_REPO_VALUE_FLAGS, GH_API_VALUE_FLAGS, GIT_FETCH, PUBLISH, SHELLS3, OWN_HEADS, MAX_DEPTH3, CWD_CHANGERS, TERMINAL_ESCAPE_RE, LOOP_MAX_RECORDS, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH4, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES;
|
|
10082
|
+
var getFilename, __filename2, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, finance_default, identity_default, publishing_default, settings_default, branches_default, ACTION_TEMPLATES, ACTION_CHECKS, GAP, prog, httpTo, httpWrite, HTTP_WRITE, HTTP_WRITE_ANY, NOT_STRIPE_TEST, postTo, STRIPE_OBJECTS, APP_SHIELD_SPECS, APP_SHIELDS, APP_SHIELD_NAMES, APP_SERVER_GLOB, GENERAL_ACTION_RULES, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, CHECK_TEXT, LEVELS, MODE_VALUES, SOFT, STRICT, BLOCK_ALL, LEVEL_CHECKS, ASI, ASI_IDS, PACK_SHIELD_OWASP, PACK_RULE_OWASP, VERDICTS, CHECK_VERDICT_RANK, ALL, BUILTIN_DANGEROUS_WORDS, PRODUCT_CHECKS, SHIELD_RULE_NAME, SHIELD_RULES_FOLDED_INTO_PRODUCT, CHECKS, CHECK_BY_ID, LEGACY_TO_ID, PROJECT_JAIL_BLOCK_READ, OVERRIDE_PREFIX, LABEL_WRAPPERS, LEGACY_READERS, syntax, KINDS, STRUCTS, unknownKinds, INVISIBLE_RE, INVISIBLE_ONE, HOMOGLYPHS, HOMOGLYPH_RE, MAX_BLOBS, MIN_DECODED, BASE64_RUN_RE, HEX_RUN_RE, HEX_ESCAPE_RUN_RE, SYSTEM_AUTH_FILES, SYSTEM_AUTH_DIRS, PASSWORD_HASH_FILES, STARTUP_NAMES, SYSTEM_DIRS, SYSTEM_DIRS_EXEMPT, UPLOAD_SYSTEM_DIRS, AGENT_INSTRUCTION_FILES, AGENT_INSTRUCTION_DIRS, LEGACY_SYSTEM_PATH_RE, MAX_ALTERNATIVES, MAX_CALL_DEPTH, MAX_CALL_WALKS, MAX_XARGS_PAYLOAD, POSITIONAL, MAX_DEPTH, MAX_PAYLOAD_DEPTH, unique, clone, SENDING_STDIN, DOWNLOAD_SHORT_VALUE, DOWNLOAD_LONG_VALUE, DOWNLOAD_OUTPUT_FLAGS, DOWNLOAD_DIR_FLAGS, base, quoteGlob, asWord, ops, MAX_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, READ_CALL, ARG, WRAP, STR_PREFIX, WRITE_MODE_LITERAL, WRITE_MODE, WRITE_MODE_AFTER, PERL_WRITE_BEFORE, readCallBefore, READ_BEFORE, READ_AFTER, ASSIGNED, openedName, OPENED_NAME, DOTENV, DOTENV_PATH_OPTION, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, codeBodiesCache, AST_CACHE_MAX, astCache, PARSE_FAIL, INTERPRETER_LINE, PROGRAM_DIR, ACCESS_VIEW_CACHE_MAX, accessViewCache, MAX_READING_PAYLOADS, STDIN_CODE_INTERPRETERS, RUNS_TEXT_ELSEWHERE, defaultExpansionOps, EMPTY_NAMES, VARIABLE_READERS, PLAIN_PROGRAM_NAME, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, CURL_SOURCE_FLAGS, CURL_VALUE_LETTERS, WGET_VALUE_LETTERS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, 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, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, INTERP_LEADING_TARGET, NODE_VALUE_FLAG, MAX_PAYLOAD_NESTING, payloadNesting, MAX_INLINE_CALLS, INLINE_EXEC_FALLBACK, UNREADABLE_SOURCE, SCRIPT_RUNNERS, SCRIPT_RUNNER_VALUE_FLAGS, MAX_SCRIPT_OPERANDS, NET_BINARIES, VALUE_FLAGS, HOME_VARIABLES, assignmentTable, currentStmtOffset, PAYLOAD_BUDGET, payloadBudget, seenPayloads, UNANALYSABLE_NESTING, ASSIGNMENT_HEADS, andOrOps, ARRAY_MARK, ARRAY_SEP, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, INDIRECT_SHAPE_RE, SOURCES_FILE_RE, SHELL_SET_VARS, pipeOps, callWords, JAILED_GLOB_NAMES, JAILED_DIR_NAMES, shellGlob, GLOB_META, INLINE_INTERP_PRESCREEN_RE, runsInlineInterpreter, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, exempt, RANK, SEQUENCE_OPS, BIP39_ENGLISH, BIP39_PUBLIC_VECTORS, indices, lengths, hash, MAX_MNEMONIC_HASHES, SECRET_VIEW_LIMITS, IBAN_LENGTH, IBAN_BBAN_SHAPE, B58, B58_INDEX, XPRV_VERSIONS, B62, CRC32_TABLE, GITHUB_TOKEN_RE, B64URL, B64URL_INDEX, CASK_TWO_ZERO_SUFFIX, CASK_FOUR_ZERO_SUFFIX, CF_ODD, CF_EVEN, SPANISH_LETTERS, HETU_CHARS, VERHOEFF_D, VERHOEFF_P, MAX, UNTRUSTED_TOOLS, INJECTION_SIGNALS, MENTION_QUOTE_RE, MENTION_WORD_RE, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, REFERENCE_VALUE_RE, IDENTIFIER_VALUE_RE, PATH_VALUE_RE, DOTTED_REFERENCE_RE, CONCATENATION_RE, EMAIL_VALUE_RE, FIXTURE_NAME_RE, DERIVATIVE_NAME_RE, QUERY_CREDENTIAL_VALUE_RE, OTP_SECRET_RE, OTP_DOC_SECRETS, ASSIGNED_SECRET_VALUE_RE, ASSIGNED_SECRET_NAME_RE, NAME_KEYWORD_RE, ARN_CONTEXT_RE, CIPHER_KEY_NAME_RE, CIPHER_NAME_PARTS, CIPHER_KEY_VALUE_RE, LARAVEL_KEY_VALUE_RE, SQL_PASSWORD_VALUE_RE, GRAFANA_KEY_VALUE_RE, BASIC_VALUE_RE, BASIC_PAIR_RE, BASIC_HEADER_RE, BASIC_HEADER_PAIR_RE, BASIC_PLACEHOLDER_RE, BASIC_TEMPLATE_MARKERS, DROPBOX_SECRET_RE, OTP_CAPTURE_RE, DB_URL_PASSWORD_RE, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, SENSITIVE_PATH_REGEXES, MAX_DEPTH2, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, BATCH_SEPARATOR, IMPERATIVE, SECRET_TARGET, GUARD, SIGNALS, DESTINATION_RE, REUSED_SIGNALS, NEVER_NEGATED, NEGATION_BEFORE, RDR_IN, COPY_VERBS2, LITERAL_VERBS, GIT_PRESCREEN_RE, MAX_PAYLOAD_DEPTH2, MAX_ALIAS_DEPTH, CACHE_MAX, cache, PAYLOAD_SHELLS, CONFIG_SCOPE_FLAGS, CONFIG_VALUE_FLAGS, GLOBAL_VALUE_OPTIONS, GLOBAL_FLAG_OPTIONS, MAX_LOOP_ITEMS, GitWalk, POSITIONAL2, NO_VARS, NO_APPENDS, FORCE_PUSH, DESTRUCTIVE, UNREADABLE, PUSH_LONG_VALUE, BRANCH_LONG_VALUE, TAG_LONG_VALUE, CLEAN_LONG_VALUE, RESTORE_LONG_VALUE, CHECKOUT_LONG_VALUE, HOOKS_BYPASS, NO_VERIFY_SUBS, HOOK_KILL_SWITCHES, COMMIT_LONG_VALUE, CHMOD_OPTION_RE, _appendOp, STAGE_ALL, ADD_LONG_VALUE, CHECK_ID, RULE_NAME, INERT_LINE_RE, CHECK_ID2, INSTRUCTION_NAMES, SETTINGS_RE, HOOK_WORDS_RE, SHELLS, NETCATS, NET_CLIENTS, SENDERS, NETCAT_EXEC_LONG, DECL_DUMPS, PROC_ENVIRON_RE, DEV_NET_RE, SOCAT_PROGRAM_RE, SOCAT_NET_RE, PRESCREEN_RE, MAX_PAYLOAD_DEPTH3, CACHE_MAX2, cache2, dupInOp, REVERSE_SHELL_DESCRIPTION, ENV_EXFIL_DESCRIPTION, DYNAMIC_WORD, MULTICALL, SHELL_VALUE_OPTIONS, INTERPRETERS, OutboundWalk, NPM_INSTALL_VERBS, NPM_EXEC_VERBS, PNPM_INSTALL_VERBS, YARN_INSTALL_VERBS, BUN_INSTALL_VERBS, DLX_VERBS, NON_REGISTRY_RE, NPM_NAME_RE, EXACT_SEMVER_RE, NPM_VALUE_FLAGS, PNPM_VALUE_FLAGS, YARN_VALUE_FLAGS, BUN_VALUE_FLAGS, PIP_VALUE_FLAGS, UV_VALUE_FLAGS, POETRY_VALUE_FLAGS, PIPENV_VALUE_FLAGS, PIPX_VALUE_FLAGS, PY_SPEC_RE, PY_EXACT_RE, EXACT_VERSION_RE, GEM_NAME_RE, GEM_VALUE_FLAGS, BUNDLE_VALUE_FLAGS, CRATE_NAME_RE, CARGO_ADD_VALUE_FLAGS, CARGO_INSTALL_VALUE_FLAGS, GO_VALUE_FLAGS, GO_PATH_RE, NUGET_NAME_RE, DOTNET_ADD_VALUE_FLAGS, DOTNET_TOOL_VALUE_FLAGS, NUGET_VALUE_FLAGS, MAVEN_COORD_RE, COMPOSER_NAME_RE, COMPOSER_VALUE_FLAGS, EDITOR_HEADS, EXTENSION_ID_RE, MANAGER_HEADS, SHELLS2, MAX_NESTING, SHELL_VALUE_FLAGS, NPM_FAMILY, PIP_FAMILY, NPM_FETCH_VERBS, PIP_FETCH_VERBS, NPM_FLAGS, PIP_FLAGS, NPM_VARS, PIP_VARS, PRESCREEN_RE2, PIP_ATTACHED_RE, MAX_PAYLOAD_DEPTH4, PUBLIC_REGISTRY_HOSTS, TUNING_FIELDS, MAP_GOVERNED, KNOB_GOVERNED, CONFIGURABLE_CHECK_IDS, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, MCP_DESTINATION_KEYS, ARGUMENT_SCAN_LIMITS, RUN_CHAR, runChar, RULE_NAME2, DESCRIPTION, DAEMON_CMDLINES, DAEMON_NAMES, KILLALL_NAMES, STOP_SYSTEMCTL, STOP_LAUNCHCTL, PKILL_VALUE_FLAGS, NAME_PRESCREEN_RE, base2, HOME_PID_FILE_RE, VERDICT_RANK, SQL_DML_KEYWORDS, NOT_OVERRIDABLE_CHECKS, MAX_DESTINATIONS, MAX_SCAN_CHARS, EMAIL_RE, URL_RE, IBAN_RE, RECIPIENT_KEYS, DESTRUCTIVE_VERB_RE, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_CC14_RE, PII_CC13_RE, PII_CC19_RE, CARD_PATTERNS, PII_ROUTING_RE, ROUTING_LABEL_RE, ROUTING_LABEL_WINDOW, NATIONAL_ID_SHAPES, NATIONAL_ID_LABEL_RE, NATIONAL_ID_LABEL_CS_RE, idLabelIn, NATIONAL_ID_LABEL_WINDOW, NATIONAL_ID_GUARD_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, IBAN_DESTINATION_KEYS, WHOLE_IBAN_RE, JSON_ESCAPE_RE, JSON_ESCAPES, MASKED_KINDS, ENTRY_RE, IBAN_TEXT_RE, EMAIL_TEXT_RE, ACCOUNT_KEY_RE, ACCOUNT_VALUE_RE, MAX_MASK_DEPTH, EMPTY, CURL_SEND_FLAGS, WGET_SEND_FLAGS, IWR_SEND_FLAGS, WRITE_METHODS, GH_READ, GH_WRITE, GH_HOSTNAME_FLAGS, GH_REPO_VALUE_FLAGS, GH_API_VALUE_FLAGS, GIT_FETCH, PUBLISH, SHELLS3, OWN_HEADS, MAX_DEPTH3, CWD_CHANGERS, TERMINAL_ESCAPE_RE, LOOP_MAX_RECORDS, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH4, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES;
|
|
9835
10083
|
var init_dist = __esm({
|
|
9836
10084
|
"packages/policy-engine/dist/index.mjs"() {
|
|
9837
10085
|
"use strict";
|
|
@@ -11830,7 +12078,7 @@ var init_dist = __esm({
|
|
|
11830
12078
|
advice: "Fixed at Review for now."
|
|
11831
12079
|
},
|
|
11832
12080
|
"commands.node9-disarm": {
|
|
11833
|
-
plain: "The agent
|
|
12081
|
+
plain: "The agent switches node9 off or weakens it: stops or kills the daemon, stops its service, uninstalls node9, changes files in ~/.node9, clears a session flag, trusts an address, pauses the gate, weakens a shield.",
|
|
11834
12082
|
example: "After reading a web page, the agent runs node9 session-exposure clear --all",
|
|
11835
12083
|
advice: "Keep Review: these are your commands to run. Block if the agent should never touch node9."
|
|
11836
12084
|
},
|
|
@@ -12143,7 +12391,7 @@ var init_dist = __esm({
|
|
|
12143
12391
|
group: "commands",
|
|
12144
12392
|
owasp: "ASI10",
|
|
12145
12393
|
title: "node9 disarmed from the shell",
|
|
12146
|
-
catches: "a node9 command that clears a session flag, trusts a destination, pauses the gate or weakens a shield
|
|
12394
|
+
catches: "the agent stopping or killing the node9 daemon, stopping its service, uninstalling node9, changing files in ~/.node9, or running a node9 command that clears a session flag, trusts a destination, pauses the gate or weakens a shield",
|
|
12147
12395
|
values: ALL,
|
|
12148
12396
|
defaultValue: "review",
|
|
12149
12397
|
legacy: ["review-node9-disarm"]
|
|
@@ -13024,6 +13272,62 @@ var init_dist = __esm({
|
|
|
13024
13272
|
php: PHP
|
|
13025
13273
|
};
|
|
13026
13274
|
STRING_LITERAL = /(['"`])((?:\\.|(?!\1)[^\\\n]){1,4096})\1/g;
|
|
13275
|
+
READ_CALL = {
|
|
13276
|
+
python: String.raw`(?:\b(?:io|codecs)\.)?\bopen|\b(?:dotenv_values|load_dotenv|get_key|read_file|loadtxt|read_csv)`,
|
|
13277
|
+
node: String.raw`\b(?:readFileSync|readFile|createReadStream|readTextFile(?:Sync)?|readFileStr|openSync|file)`,
|
|
13278
|
+
perl: String.raw`\b(?:open|sysopen|read_file|slurp)`,
|
|
13279
|
+
ruby: String.raw`\b(?:File|IO)\.(?:read|binread|readlines|foreach|open)|\bDotenv\.(?:load|parse|overload)`,
|
|
13280
|
+
php: String.raw`\b(?:file_get_contents|fopen|file|readfile|parse_ini_file|highlight_file|show_source)`
|
|
13281
|
+
};
|
|
13282
|
+
ARG = String.raw`(?:(?:(?:my|our|local)\s+)?[\w.$]+(?:\s*\(\s*\))?|'[^'\n]{0,8}'|"[^"\n]{0,8}")\s*,\s*`;
|
|
13283
|
+
WRAP = String.raw`(?:(?:new\s+)?[\w.$]+\s*\(\s*(?:${ARG}){0,3}){0,3}`;
|
|
13284
|
+
STR_PREFIX = String.raw`[rRbBuUfF]{0,2}`;
|
|
13285
|
+
WRITE_MODE_LITERAL = String.raw`['"](?=[rbtU+]*w|(?![^'"]*\+)[rbtU]*[ax])[rwaxbtU+]{1,4}['"]`;
|
|
13286
|
+
WRITE_MODE = String.raw`\s*,\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL}`;
|
|
13287
|
+
WRITE_MODE_AFTER = new RegExp(`^(?:\\s*\\)){0,3}${WRITE_MODE}`);
|
|
13288
|
+
PERL_WRITE_BEFORE = /['"]\s*(?:\+?[>|]|>>)\s*['"]\s*,\s*$/;
|
|
13289
|
+
readCallBefore = (language) => new RegExp(
|
|
13290
|
+
String.raw`(?:${READ_CALL[language]})(?![\w$])\s*\(?\s*(?:${ARG}){0,3}${WRAP}${STR_PREFIX}$`
|
|
13291
|
+
);
|
|
13292
|
+
READ_BEFORE = {
|
|
13293
|
+
python: readCallBefore("python"),
|
|
13294
|
+
node: readCallBefore("node"),
|
|
13295
|
+
perl: readCallBefore("perl"),
|
|
13296
|
+
ruby: readCallBefore("ruby"),
|
|
13297
|
+
php: readCallBefore("php")
|
|
13298
|
+
};
|
|
13299
|
+
READ_AFTER = {
|
|
13300
|
+
python: new RegExp(
|
|
13301
|
+
String.raw`^\s*\)\s*\.\s*(?:read_text|read_bytes|open)\s*\((?!\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL})`
|
|
13302
|
+
)
|
|
13303
|
+
};
|
|
13304
|
+
ASSIGNED = new RegExp(String.raw`([$\w]+)\s*=\s*${WRAP}${STR_PREFIX}$`);
|
|
13305
|
+
openedName = (language) => new RegExp(
|
|
13306
|
+
String.raw`(?:${READ_CALL[language]})(?![\w$])\s*\(?\s*(?:${ARG}){0,3}${WRAP}([$\w]+)(?!${WRITE_MODE})\s*[),]` + (language === "python" ? String.raw`|\bPath\s*\(\s*([$\w]+)\s*\)\s*\.\s*(?:read_text|read_bytes|open)\s*\(` : ""),
|
|
13307
|
+
"g"
|
|
13308
|
+
);
|
|
13309
|
+
OPENED_NAME = {
|
|
13310
|
+
python: openedName("python"),
|
|
13311
|
+
node: openedName("node"),
|
|
13312
|
+
perl: openedName("perl"),
|
|
13313
|
+
ruby: openedName("ruby"),
|
|
13314
|
+
php: openedName("php")
|
|
13315
|
+
};
|
|
13316
|
+
DOTENV = {
|
|
13317
|
+
node: {
|
|
13318
|
+
load: /\brequire\s*\(\s*['"`]dotenv(?:\/config)?['"`]\s*\)|\bimport\s*(?:[\w${}\s,*]+\s+from\s*)?['"`]dotenv(?:\/config)?['"`]|\bimport\s*\(\s*['"`]dotenv(?:\/config)?['"`]\s*\)/,
|
|
13319
|
+
values: /\.parsed\b|[(,]\s*(?:require\s*\(\s*['"`]dotenv['"`]\s*\)|dotenv)\s*\.\s*config\s*\(/,
|
|
13320
|
+
env: /\b(?:process|Deno|Bun)\s*\.\s*env\b/,
|
|
13321
|
+
literalPath: /\bconfig\s*\(\s*\{[^)]*\bpath\s*:\s*['"`]/
|
|
13322
|
+
},
|
|
13323
|
+
python: {
|
|
13324
|
+
load: /\b(?:load_dotenv|dotenv_values|get_key)\s*\(/,
|
|
13325
|
+
values: /\b(?:dotenv_values|get_key)\s*\(/,
|
|
13326
|
+
env: /\b(?:environ|getenv)\b/,
|
|
13327
|
+
literalPath: /\b(?:load_dotenv|dotenv_values)\s*\(\s*(?:dotenv_path\s*=\s*)?[rRbBuU]?['"]/
|
|
13328
|
+
}
|
|
13329
|
+
};
|
|
13330
|
+
DOTENV_PATH_OPTION = /\bconfig\s*\(\s*\{[^)]*\bpath\s*:\s*$/;
|
|
13027
13331
|
sharedParser = lazy(() => getSyntax().NewParser());
|
|
13028
13332
|
MESSAGE_FLAGS = /* @__PURE__ */ new Set([
|
|
13029
13333
|
"-m",
|
|
@@ -13818,6 +14122,7 @@ var init_dist = __esm({
|
|
|
13818
14122
|
"rmdir"
|
|
13819
14123
|
]);
|
|
13820
14124
|
INTERP_LEADING_TARGET = /* @__PURE__ */ new Set(["su"]);
|
|
14125
|
+
NODE_VALUE_FLAG = /^(-r|--require|--import|--loader|--experimental-loader|--env-file|--env-file-if-exists|--input-type|-C|--conditions)(?:=(.*))?$/;
|
|
13821
14126
|
MAX_PAYLOAD_NESTING = 8;
|
|
13822
14127
|
payloadNesting = 0;
|
|
13823
14128
|
MAX_INLINE_CALLS = 16;
|
|
@@ -14066,6 +14371,8 @@ var init_dist = __esm({
|
|
|
14066
14371
|
JAILED_DIR_NAMES = [".ssh", ".aws"];
|
|
14067
14372
|
shellGlob = (p) => p.replace(/\[!/g, "[^");
|
|
14068
14373
|
GLOB_META = /(?<!\\)[*?[]/;
|
|
14374
|
+
INLINE_INTERP_PRESCREEN_RE = /(?:^|[^\w-])(?:python|node|tsx|ts-node|deno|bun|perl|ruby|irb|php)(?![A-Za-z_])/i;
|
|
14375
|
+
runsInlineInterpreter = (command, normalized) => INLINE_INTERP_PRESCREEN_RE.test(command) || INLINE_INTERP_PRESCREEN_RE.test(normalized);
|
|
14069
14376
|
isReaderWord = (w) => w !== null && FS_READ_TOOLS.has(baseWord(w));
|
|
14070
14377
|
positionalAfter = (words, from, to = words.length) => positionedArgs(words, from, to).map((a) => a.value);
|
|
14071
14378
|
NONE = { kind: "none" };
|
|
@@ -17381,9 +17688,9 @@ zoo`.split("\n");
|
|
|
17381
17688
|
const name = n.Name.Value;
|
|
17382
17689
|
if (n.Append) {
|
|
17383
17690
|
const prev = this.appended.has(name) ? this.appended.get(name) : resolveWordLiteral(n.Value) === null ? null : void 0;
|
|
17384
|
-
const
|
|
17691
|
+
const base3 = prev === void 0 ? recordedExpansion(name) : prev;
|
|
17385
17692
|
const piece = resolveWordLiteral(n.Value);
|
|
17386
|
-
this.appended.set(name, typeof
|
|
17693
|
+
this.appended.set(name, typeof base3 === "string" && piece !== null ? base3 + piece : null);
|
|
17387
17694
|
this.treeTopVars.delete(name);
|
|
17388
17695
|
return true;
|
|
17389
17696
|
}
|
|
@@ -18899,12 +19206,50 @@ ${text}` : text);
|
|
|
18899
19206
|
const char = value[index] ?? "";
|
|
18900
19207
|
return RUN_CHAR.test(char) || char !== "" && isInvisibleChar(char);
|
|
18901
19208
|
};
|
|
19209
|
+
RULE_NAME2 = "review-node9-disarm";
|
|
19210
|
+
DESCRIPTION = "The AI wants to stop node9, remove it, or change its own files. These are your commands to run, not the agent's: with the daemon stopped the outside-content and taint checks are off.";
|
|
19211
|
+
DAEMON_CMDLINES = [
|
|
19212
|
+
"node /usr/lib/node_modules/@node9/proxy/dist/cli.js daemon start",
|
|
19213
|
+
"node9 daemon start"
|
|
19214
|
+
];
|
|
19215
|
+
DAEMON_NAMES = ["node", "node9"];
|
|
19216
|
+
KILLALL_NAMES = /* @__PURE__ */ new Set(["node", "node9", "node.exe", "node9.exe"]);
|
|
19217
|
+
STOP_SYSTEMCTL = /* @__PURE__ */ new Set(["stop", "disable", "mask", "kill"]);
|
|
19218
|
+
STOP_LAUNCHCTL = /* @__PURE__ */ new Set(["unload", "bootout", "remove", "stop", "kill", "disable"]);
|
|
19219
|
+
PKILL_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
19220
|
+
"-u",
|
|
19221
|
+
"-U",
|
|
19222
|
+
"-g",
|
|
19223
|
+
"-G",
|
|
19224
|
+
"-P",
|
|
19225
|
+
"-s",
|
|
19226
|
+
"-t",
|
|
19227
|
+
"-F",
|
|
19228
|
+
"--signal",
|
|
19229
|
+
"--euid",
|
|
19230
|
+
"--uid",
|
|
19231
|
+
"--pgroup",
|
|
19232
|
+
"--group",
|
|
19233
|
+
"--parent",
|
|
19234
|
+
"--session",
|
|
19235
|
+
"--terminal",
|
|
19236
|
+
"--pidfile",
|
|
19237
|
+
"--ns",
|
|
19238
|
+
"--nslist"
|
|
19239
|
+
]);
|
|
19240
|
+
NAME_PRESCREEN_RE = /node9|kill|systemctl|launchctl|daemon/i;
|
|
19241
|
+
base2 = (w) => (w ?? "").split(/[\\/]/).pop()?.toLowerCase() ?? "";
|
|
19242
|
+
HOME_PID_FILE_RE = /(?:^|[\s"'(=`])(?:~|\$HOME|\$\{HOME\}|\/home\/[^/\s]+|\/Users\/[^/\s]+|\/root)\/\.node9\/daemon\.pid/;
|
|
18902
19243
|
VERDICT_RANK = {
|
|
18903
19244
|
allow: 0,
|
|
18904
19245
|
review: 1,
|
|
18905
19246
|
block: 2
|
|
18906
19247
|
};
|
|
18907
19248
|
SQL_DML_KEYWORDS = /* @__PURE__ */ new Set(["select", "insert", "update", "delete", "merge", "upsert"]);
|
|
19249
|
+
NOT_OVERRIDABLE_CHECKS = /* @__PURE__ */ new Set([
|
|
19250
|
+
"data.credential-files",
|
|
19251
|
+
"data.credential-files-other"
|
|
19252
|
+
]);
|
|
18908
19253
|
MAX_DESTINATIONS = 200;
|
|
18909
19254
|
MAX_SCAN_CHARS = 1e5;
|
|
18910
19255
|
EMAIL_RE = /[\p{L}\p{N}._%+-]+@[\p{L}\p{N}](?:[\p{L}\p{N}-]*[\p{L}\p{N}])?(?:\.[\p{L}\p{N}](?:[\p{L}\p{N}-]*[\p{L}\p{N}])?)*\.\p{L}{2,}/gu;
|
|
@@ -20318,8 +20663,8 @@ function safeApiUrl(raw, onReject) {
|
|
|
20318
20663
|
function sanitizeSsrfAllow(entries, source) {
|
|
20319
20664
|
const kept = [];
|
|
20320
20665
|
for (const entry of entries) {
|
|
20321
|
-
const
|
|
20322
|
-
const m = classifySsrf(
|
|
20666
|
+
const base3 = entry.includes("/") ? entry.slice(0, entry.indexOf("/")).trim() : entry;
|
|
20667
|
+
const m = classifySsrf(base3);
|
|
20323
20668
|
if (m && !m.overridable) {
|
|
20324
20669
|
const what = entry.includes("/") ? "covers only protected addresses" : "is a protected address";
|
|
20325
20670
|
process.emitWarning(
|
|
@@ -21419,12 +21764,12 @@ function getConfig(cwd) {
|
|
|
21419
21764
|
continue;
|
|
21420
21765
|
explicit[id] = v;
|
|
21421
21766
|
}
|
|
21422
|
-
const
|
|
21767
|
+
const base3 = resolveCheckMap({
|
|
21423
21768
|
...catalogSettingsFrom(mergedSettings, mergedPolicy),
|
|
21424
21769
|
checks: explicit
|
|
21425
21770
|
});
|
|
21426
21771
|
for (const [id, v] of Object.entries(v2ChecksByPath.get(projectPath)?.checks ?? {})) {
|
|
21427
|
-
if (CHECK_VERDICT_RANK[v] > CHECK_VERDICT_RANK[
|
|
21772
|
+
if (CHECK_VERDICT_RANK[v] > CHECK_VERDICT_RANK[base3[id] ?? "off"]) {
|
|
21428
21773
|
explicit[id] = v;
|
|
21429
21774
|
checkSources[id] = "project";
|
|
21430
21775
|
}
|
|
@@ -21576,7 +21921,7 @@ init_dist();
|
|
|
21576
21921
|
// src/policy/index.ts
|
|
21577
21922
|
init_esm_shims();
|
|
21578
21923
|
init_dist();
|
|
21579
|
-
import
|
|
21924
|
+
import fs15 from "fs";
|
|
21580
21925
|
|
|
21581
21926
|
// src/utils/read-capped.ts
|
|
21582
21927
|
init_esm_shims();
|
|
@@ -21620,19 +21965,51 @@ function readCappedText(file2, maxBytes, openFlags = "r") {
|
|
|
21620
21965
|
|
|
21621
21966
|
// src/policy/index.ts
|
|
21622
21967
|
import path15 from "path";
|
|
21968
|
+
import os10 from "os";
|
|
21969
|
+
|
|
21970
|
+
// src/utils/read-small-file.ts
|
|
21971
|
+
init_esm_shims();
|
|
21972
|
+
import fs7 from "fs";
|
|
21973
|
+
function readSmallFile(file2, maxBytes) {
|
|
21974
|
+
let fd;
|
|
21975
|
+
try {
|
|
21976
|
+
fd = fs7.openSync(file2, fs7.constants.O_RDONLY | (fs7.constants.O_NONBLOCK ?? 0));
|
|
21977
|
+
} catch {
|
|
21978
|
+
return null;
|
|
21979
|
+
}
|
|
21980
|
+
try {
|
|
21981
|
+
const st = fs7.fstatSync(fd);
|
|
21982
|
+
if (!st.isFile() || st.size > maxBytes) return null;
|
|
21983
|
+
const buf = Buffer.alloc(Math.min(st.size, maxBytes));
|
|
21984
|
+
let read2 = 0;
|
|
21985
|
+
while (read2 < buf.length) {
|
|
21986
|
+
const n = fs7.readSync(fd, buf, read2, buf.length - read2, read2);
|
|
21987
|
+
if (n === 0) break;
|
|
21988
|
+
read2 += n;
|
|
21989
|
+
}
|
|
21990
|
+
return buf.toString("utf8", 0, read2);
|
|
21991
|
+
} catch {
|
|
21992
|
+
return null;
|
|
21993
|
+
} finally {
|
|
21994
|
+
fs7.closeSync(fd);
|
|
21995
|
+
}
|
|
21996
|
+
}
|
|
21997
|
+
|
|
21998
|
+
// src/policy/index.ts
|
|
21999
|
+
init_forecast_context();
|
|
21623
22000
|
|
|
21624
22001
|
// src/dlp.ts
|
|
21625
22002
|
init_esm_shims();
|
|
21626
22003
|
init_dist();
|
|
21627
22004
|
init_dist();
|
|
21628
|
-
import
|
|
22005
|
+
import fs8 from "fs";
|
|
21629
22006
|
import path7 from "path";
|
|
21630
22007
|
function scanFilePath(filePath, cwd = process.cwd(), options = {}) {
|
|
21631
22008
|
if (!filePath) return null;
|
|
21632
22009
|
let resolved;
|
|
21633
22010
|
try {
|
|
21634
22011
|
const absolute2 = path7.resolve(cwd, filePath);
|
|
21635
|
-
resolved =
|
|
22012
|
+
resolved = fs8.realpathSync.native(absolute2);
|
|
21636
22013
|
} catch (err) {
|
|
21637
22014
|
const code = err.code;
|
|
21638
22015
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -21859,7 +22236,7 @@ function combineWithEngine(gates, engine, opts = { panicMode: false }) {
|
|
|
21859
22236
|
// src/policy/file-access.ts
|
|
21860
22237
|
init_esm_shims();
|
|
21861
22238
|
init_dist();
|
|
21862
|
-
import
|
|
22239
|
+
import fs9 from "fs";
|
|
21863
22240
|
import os6 from "os";
|
|
21864
22241
|
import path8 from "path";
|
|
21865
22242
|
function absoluteSpelling(p, cwd, home) {
|
|
@@ -21873,13 +22250,13 @@ function physical(p, followFinal, links = 0) {
|
|
|
21873
22250
|
return { path: `${parent.path}/${path8.basename(p)}`, missing: parent.missing };
|
|
21874
22251
|
}
|
|
21875
22252
|
try {
|
|
21876
|
-
return { path:
|
|
22253
|
+
return { path: fs9.realpathSync.native(p), missing: false };
|
|
21877
22254
|
} catch (error) {
|
|
21878
22255
|
const code = error.code;
|
|
21879
22256
|
if (!["ENOENT", "ENOTDIR"].includes(code ?? "")) throw error;
|
|
21880
22257
|
try {
|
|
21881
|
-
if (
|
|
21882
|
-
const target =
|
|
22258
|
+
if (fs9.lstatSync(p).isSymbolicLink()) {
|
|
22259
|
+
const target = fs9.readlinkSync(p);
|
|
21883
22260
|
return physical(
|
|
21884
22261
|
path8.isAbsolute(target) ? target : `${path8.dirname(p)}/${target}`,
|
|
21885
22262
|
true,
|
|
@@ -21919,14 +22296,14 @@ function prepareFileAccesses(tool, args, cwd = process.cwd(), inspection = {}, h
|
|
|
21919
22296
|
const raw = absoluteSpelling(access.path, access.cwd ?? cwd, home);
|
|
21920
22297
|
if (access.directoryTarget) {
|
|
21921
22298
|
try {
|
|
21922
|
-
if (!
|
|
22299
|
+
if (!fs9.statSync(absoluteSpelling(access.directoryTarget, access.cwd ?? cwd, home)).isDirectory())
|
|
21923
22300
|
continue;
|
|
21924
22301
|
} catch {
|
|
21925
22302
|
}
|
|
21926
22303
|
}
|
|
21927
22304
|
if (access.operation === "create") {
|
|
21928
22305
|
try {
|
|
21929
|
-
|
|
22306
|
+
fs9.statSync(raw);
|
|
21930
22307
|
continue;
|
|
21931
22308
|
} catch {
|
|
21932
22309
|
}
|
|
@@ -21983,34 +22360,34 @@ import path12 from "path";
|
|
|
21983
22360
|
// src/supply-chain/osv-index.ts
|
|
21984
22361
|
init_esm_shims();
|
|
21985
22362
|
init_dist();
|
|
21986
|
-
import
|
|
22363
|
+
import fs11 from "fs";
|
|
21987
22364
|
import os7 from "os";
|
|
21988
22365
|
import path10 from "path";
|
|
21989
22366
|
import { createHash as createHash4 } from "crypto";
|
|
21990
22367
|
|
|
21991
22368
|
// src/utils/atomic-write.ts
|
|
21992
22369
|
init_esm_shims();
|
|
21993
|
-
import
|
|
22370
|
+
import fs10 from "fs";
|
|
21994
22371
|
import path9 from "path";
|
|
21995
22372
|
import { randomUUID } from "crypto";
|
|
21996
22373
|
function atomicWriteSync(filePath, data, options) {
|
|
21997
22374
|
const dir2 = path9.dirname(filePath);
|
|
21998
|
-
if (!
|
|
22375
|
+
if (!fs10.existsSync(dir2)) fs10.mkdirSync(dir2, { recursive: true });
|
|
21999
22376
|
const tmpPath = `${filePath}.${randomUUID()}.tmp`;
|
|
22000
22377
|
try {
|
|
22001
|
-
|
|
22378
|
+
fs10.writeFileSync(tmpPath, data, options);
|
|
22002
22379
|
} catch (err) {
|
|
22003
22380
|
try {
|
|
22004
|
-
|
|
22381
|
+
fs10.unlinkSync(tmpPath);
|
|
22005
22382
|
} catch {
|
|
22006
22383
|
}
|
|
22007
22384
|
throw err;
|
|
22008
22385
|
}
|
|
22009
22386
|
try {
|
|
22010
|
-
|
|
22387
|
+
fs10.renameSync(tmpPath, filePath);
|
|
22011
22388
|
} catch (err) {
|
|
22012
22389
|
try {
|
|
22013
|
-
|
|
22390
|
+
fs10.unlinkSync(tmpPath);
|
|
22014
22391
|
} catch {
|
|
22015
22392
|
}
|
|
22016
22393
|
throw err;
|
|
@@ -22046,7 +22423,7 @@ function shardPath(eco, shard) {
|
|
|
22046
22423
|
}
|
|
22047
22424
|
function readMeta(eco) {
|
|
22048
22425
|
try {
|
|
22049
|
-
const m = JSON.parse(
|
|
22426
|
+
const m = JSON.parse(fs11.readFileSync(path10.join(ecoDir(eco), "meta.json"), "utf8"));
|
|
22050
22427
|
if (typeof m?.syncedAt !== "string" || typeof m?.lastModifiedMs !== "number") return null;
|
|
22051
22428
|
return m;
|
|
22052
22429
|
} catch {
|
|
@@ -22055,7 +22432,7 @@ function readMeta(eco) {
|
|
|
22055
22432
|
}
|
|
22056
22433
|
function readShard(eco, shard) {
|
|
22057
22434
|
try {
|
|
22058
|
-
const s = JSON.parse(
|
|
22435
|
+
const s = JSON.parse(fs11.readFileSync(shardPath(eco, shard), "utf8"));
|
|
22059
22436
|
return s && typeof s === "object" && !Array.isArray(s) ? s : {};
|
|
22060
22437
|
} catch {
|
|
22061
22438
|
return {};
|
|
@@ -22165,15 +22542,15 @@ async function fetchJson(url, opts) {
|
|
|
22165
22542
|
// src/supply-chain/osv-online.ts
|
|
22166
22543
|
var TIMEOUT_MS = 2500;
|
|
22167
22544
|
async function queryOsvMalicious(queries) {
|
|
22168
|
-
const
|
|
22169
|
-
if (!
|
|
22545
|
+
const base3 = endpoints().osvApi;
|
|
22546
|
+
if (!base3 || queries.length === 0) return null;
|
|
22170
22547
|
const body = JSON.stringify({
|
|
22171
22548
|
queries: queries.map((q) => ({
|
|
22172
22549
|
package: { name: q.name, ecosystem: q.ecosystem },
|
|
22173
22550
|
...q.version ? { version: q.version } : {}
|
|
22174
22551
|
}))
|
|
22175
22552
|
});
|
|
22176
|
-
const res = await fetchJson(`${
|
|
22553
|
+
const res = await fetchJson(`${base3}/v1/querybatch`, {
|
|
22177
22554
|
timeoutMs: TIMEOUT_MS,
|
|
22178
22555
|
maxBytes: 1024 * 1024,
|
|
22179
22556
|
body
|
|
@@ -22234,9 +22611,9 @@ function pypiRepoOf(doc) {
|
|
|
22234
22611
|
return null;
|
|
22235
22612
|
}
|
|
22236
22613
|
async function npmSourceRepo(name, version) {
|
|
22237
|
-
const
|
|
22238
|
-
if (!
|
|
22239
|
-
const url = `${
|
|
22614
|
+
const base3 = endpoints().npmRegistry;
|
|
22615
|
+
if (!base3) return "unknown";
|
|
22616
|
+
const url = `${base3}/-/npm/v1/attestations/${name.replaceAll("/", "%2F")}@${encodeURIComponent(version)}`;
|
|
22240
22617
|
return read(url, npmRepoOf);
|
|
22241
22618
|
}
|
|
22242
22619
|
async function read(url, repoOf) {
|
|
@@ -22249,9 +22626,9 @@ async function read(url, repoOf) {
|
|
|
22249
22626
|
}
|
|
22250
22627
|
}
|
|
22251
22628
|
async function pypiSourceRepo(name, version, filename) {
|
|
22252
|
-
const
|
|
22253
|
-
if (!
|
|
22254
|
-
const url = `${
|
|
22629
|
+
const base3 = endpoints().pypi;
|
|
22630
|
+
if (!base3) return "unknown";
|
|
22631
|
+
const url = `${base3}/integrity/${encodeURIComponent(name)}/${encodeURIComponent(version)}/${encodeURIComponent(filename)}/provenance`;
|
|
22255
22632
|
return read(url, pypiRepoOf);
|
|
22256
22633
|
}
|
|
22257
22634
|
var PYPI_FINAL = /^\d+(?:\.\d+)*$/;
|
|
@@ -22296,9 +22673,9 @@ async function npmVersionDocument(url, selector) {
|
|
|
22296
22673
|
};
|
|
22297
22674
|
}
|
|
22298
22675
|
async function npmInfo(name, version, freshWindowMs, raw) {
|
|
22299
|
-
const
|
|
22300
|
-
if (!
|
|
22301
|
-
const url = `${
|
|
22676
|
+
const base3 = endpoints().npmRegistry;
|
|
22677
|
+
if (!base3) return null;
|
|
22678
|
+
const url = `${base3}/${name.replaceAll("/", "%2F")}`;
|
|
22302
22679
|
const aliasStart = raw?.indexOf("@npm:") ?? -1;
|
|
22303
22680
|
const target = aliasStart > 0 ? raw.slice(aliasStart + 5) : raw?.replace(/^npm:/, "");
|
|
22304
22681
|
const specStart = target?.indexOf("@", 1) ?? -1;
|
|
@@ -22366,9 +22743,9 @@ async function npmInfo(name, version, freshWindowMs, raw) {
|
|
|
22366
22743
|
return info;
|
|
22367
22744
|
}
|
|
22368
22745
|
async function pypiInfo(name, version) {
|
|
22369
|
-
const
|
|
22370
|
-
if (!
|
|
22371
|
-
const url = version ? `${
|
|
22746
|
+
const base3 = endpoints().pypi;
|
|
22747
|
+
if (!base3) return null;
|
|
22748
|
+
const url = version ? `${base3}/pypi/${encodeURIComponent(name)}/${encodeURIComponent(version)}/json` : `${base3}/pypi/${encodeURIComponent(name)}/json`;
|
|
22372
22749
|
const doc = await fetchJson(url, { timeoutMs: TIMEOUT_MS3, maxBytes: MAX_BYTES2 });
|
|
22373
22750
|
if (!doc?.info?.version) return null;
|
|
22374
22751
|
const times = (doc.urls ?? []).map((u) => u.upload_time_iso_8601 ? Date.parse(u.upload_time_iso_8601) : NaN).filter((t) => Number.isFinite(t));
|
|
@@ -22392,9 +22769,9 @@ function pypiHistoryOf(releases, version) {
|
|
|
22392
22769
|
};
|
|
22393
22770
|
}
|
|
22394
22771
|
async function pypiHistory(name, version) {
|
|
22395
|
-
const
|
|
22396
|
-
if (!
|
|
22397
|
-
const doc = await fetchJson(`${
|
|
22772
|
+
const base3 = endpoints().pypi;
|
|
22773
|
+
if (!base3) return null;
|
|
22774
|
+
const doc = await fetchJson(`${base3}/pypi/${encodeURIComponent(name)}/json`, {
|
|
22398
22775
|
timeoutMs: TIMEOUT_MS3,
|
|
22399
22776
|
maxBytes: MAX_BYTES2
|
|
22400
22777
|
});
|
|
@@ -22409,7 +22786,7 @@ async function registryInfo(eco, name, version, freshWindowMs, raw) {
|
|
|
22409
22786
|
|
|
22410
22787
|
// src/supply-chain/local-resolve.ts
|
|
22411
22788
|
init_esm_shims();
|
|
22412
|
-
import
|
|
22789
|
+
import fs12 from "fs";
|
|
22413
22790
|
import path11 from "path";
|
|
22414
22791
|
var MAX_LEVELS = 32;
|
|
22415
22792
|
var LOCAL_FIRST_MANAGERS = /* @__PURE__ */ new Set(["npx", "bunx", "npm exec"]);
|
|
@@ -22421,7 +22798,7 @@ function resolveInstalled(name, cwd) {
|
|
|
22421
22798
|
const pkgDir = path11.join(dir2, "node_modules", ...name.split("/"));
|
|
22422
22799
|
const manifest = path11.join(pkgDir, "package.json");
|
|
22423
22800
|
try {
|
|
22424
|
-
const raw =
|
|
22801
|
+
const raw = fs12.readFileSync(manifest, "utf8");
|
|
22425
22802
|
const parsed = JSON.parse(raw);
|
|
22426
22803
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
22427
22804
|
return { version: parsed.version, dir: pkgDir };
|
|
@@ -22699,7 +23076,7 @@ init_esm_shims();
|
|
|
22699
23076
|
init_dist();
|
|
22700
23077
|
import os8 from "os";
|
|
22701
23078
|
import path13 from "path";
|
|
22702
|
-
import
|
|
23079
|
+
import fs13 from "fs";
|
|
22703
23080
|
var MAX_CONFIG_BYTES = 256 * 1024;
|
|
22704
23081
|
var MAX_PARENT_DIRS = 12;
|
|
22705
23082
|
var TTL_MS = 5e3;
|
|
@@ -22824,7 +23201,7 @@ function configuredRegistryHosts(cwd, env = process.env, home = os8.homedir()) {
|
|
|
22824
23201
|
const r = readCappedText(
|
|
22825
23202
|
file2,
|
|
22826
23203
|
MAX_CONFIG_BYTES,
|
|
22827
|
-
|
|
23204
|
+
fs13.constants.O_RDONLY | (fs13.constants.O_NONBLOCK ?? 0)
|
|
22828
23205
|
);
|
|
22829
23206
|
if (r) hostsInText(r.text, hosts);
|
|
22830
23207
|
}
|
|
@@ -22834,7 +23211,7 @@ function configuredRegistryHosts(cwd, env = process.env, home = os8.homedir()) {
|
|
|
22834
23211
|
|
|
22835
23212
|
// src/utils/provenance.ts
|
|
22836
23213
|
init_esm_shims();
|
|
22837
|
-
import
|
|
23214
|
+
import fs14 from "fs";
|
|
22838
23215
|
import path14 from "path";
|
|
22839
23216
|
import os9 from "os";
|
|
22840
23217
|
var SYSTEM_PREFIXES = ["/usr/bin", "/usr/sbin", "/bin", "/sbin"];
|
|
@@ -22854,7 +23231,7 @@ function findInPath(cmd) {
|
|
|
22854
23231
|
if (!dir2) continue;
|
|
22855
23232
|
const full = path14.join(dir2, cmd);
|
|
22856
23233
|
try {
|
|
22857
|
-
|
|
23234
|
+
fs14.accessSync(full, fs14.constants.X_OK);
|
|
22858
23235
|
return full;
|
|
22859
23236
|
} catch {
|
|
22860
23237
|
}
|
|
@@ -22899,7 +23276,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
22899
23276
|
reason: "binary not found in PATH"
|
|
22900
23277
|
};
|
|
22901
23278
|
}
|
|
22902
|
-
resolved =
|
|
23279
|
+
resolved = fs14.realpathSync(found);
|
|
22903
23280
|
} catch {
|
|
22904
23281
|
return {
|
|
22905
23282
|
resolvedPath: cmd,
|
|
@@ -22908,7 +23285,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
22908
23285
|
};
|
|
22909
23286
|
}
|
|
22910
23287
|
try {
|
|
22911
|
-
const stat =
|
|
23288
|
+
const stat = fs14.statSync(resolved);
|
|
22912
23289
|
if (stat.mode & 2) {
|
|
22913
23290
|
return {
|
|
22914
23291
|
resolvedPath: resolved,
|
|
@@ -22957,14 +23334,26 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
|
|
|
22957
23334
|
isTrustedHost: config.policy.trustedHostsManaged ? (host2) => matchesTrustedHost(host2, config.policy.trustedHosts) : isTrustedHost,
|
|
22958
23335
|
readAgentSettings,
|
|
22959
23336
|
isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2),
|
|
22960
|
-
isGitWorkTreeTop
|
|
23337
|
+
isGitWorkTreeTop,
|
|
23338
|
+
daemonPid: daemonPidFromFile
|
|
22961
23339
|
}
|
|
22962
23340
|
);
|
|
22963
23341
|
}
|
|
23342
|
+
function daemonPidFromFile() {
|
|
23343
|
+
if (forecastRun()) return null;
|
|
23344
|
+
const text = readSmallFile(path15.join(os10.homedir(), ".node9", "daemon.pid"), 4096);
|
|
23345
|
+
if (text === null) return null;
|
|
23346
|
+
try {
|
|
23347
|
+
const pid = JSON.parse(text).pid;
|
|
23348
|
+
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= 4194304 ? pid : null;
|
|
23349
|
+
} catch {
|
|
23350
|
+
return null;
|
|
23351
|
+
}
|
|
23352
|
+
}
|
|
22964
23353
|
function isGitWorkTreeTop(dir2, cwd) {
|
|
22965
23354
|
if (!path15.isAbsolute(cwd)) return true;
|
|
22966
23355
|
try {
|
|
22967
|
-
return
|
|
23356
|
+
return fs15.existsSync(path15.join(path15.resolve(cwd, dir2), ".git"));
|
|
22968
23357
|
} catch {
|
|
22969
23358
|
return true;
|
|
22970
23359
|
}
|
|
@@ -22974,7 +23363,7 @@ function readAgentSettings(absPath) {
|
|
|
22974
23363
|
const r = readCappedText(
|
|
22975
23364
|
absPath,
|
|
22976
23365
|
MAX_AGENT_SETTINGS_BYTES,
|
|
22977
|
-
|
|
23366
|
+
fs15.constants.O_RDONLY | (fs15.constants.O_NONBLOCK ?? 0)
|
|
22978
23367
|
);
|
|
22979
23368
|
return r && !r.truncated ? r.text : null;
|
|
22980
23369
|
}
|
|
@@ -22984,12 +23373,12 @@ function isIgnoredTool2(toolName) {
|
|
|
22984
23373
|
|
|
22985
23374
|
// src/auth/state.ts
|
|
22986
23375
|
init_esm_shims();
|
|
22987
|
-
import
|
|
23376
|
+
import fs16 from "fs";
|
|
22988
23377
|
import path16 from "path";
|
|
22989
|
-
import
|
|
23378
|
+
import os11 from "os";
|
|
22990
23379
|
init_forecast_context();
|
|
22991
|
-
var PAUSED_FILE = path16.join(
|
|
22992
|
-
var TRUST_FILE = path16.join(
|
|
23380
|
+
var PAUSED_FILE = path16.join(os11.homedir(), ".node9", "PAUSED");
|
|
23381
|
+
var TRUST_FILE = path16.join(os11.homedir(), ".node9", "trust.json");
|
|
22993
23382
|
function extractCommandPattern(toolName, args) {
|
|
22994
23383
|
const lower2 = toolName.toLowerCase();
|
|
22995
23384
|
if (lower2 !== "bash" && lower2 !== "execute_bash" && lower2 !== "shell") return void 0;
|
|
@@ -23002,11 +23391,11 @@ function extractCommandPattern(toolName, args) {
|
|
|
23002
23391
|
function checkPause() {
|
|
23003
23392
|
if (forecastRun()) return { paused: false };
|
|
23004
23393
|
try {
|
|
23005
|
-
if (!
|
|
23006
|
-
const state = JSON.parse(
|
|
23394
|
+
if (!fs16.existsSync(PAUSED_FILE)) return { paused: false };
|
|
23395
|
+
const state = JSON.parse(fs16.readFileSync(PAUSED_FILE, "utf-8"));
|
|
23007
23396
|
if (state.expiry > 0 && Date.now() >= state.expiry) {
|
|
23008
23397
|
try {
|
|
23009
|
-
|
|
23398
|
+
fs16.unlinkSync(PAUSED_FILE);
|
|
23010
23399
|
} catch {
|
|
23011
23400
|
}
|
|
23012
23401
|
return { paused: false };
|
|
@@ -23019,8 +23408,8 @@ function checkPause() {
|
|
|
23019
23408
|
function getActiveTrustSession(toolName, args) {
|
|
23020
23409
|
if (forecastRun()) return false;
|
|
23021
23410
|
try {
|
|
23022
|
-
if (!
|
|
23023
|
-
const trust = JSON.parse(
|
|
23411
|
+
if (!fs16.existsSync(TRUST_FILE)) return false;
|
|
23412
|
+
const trust = JSON.parse(fs16.readFileSync(TRUST_FILE, "utf-8"));
|
|
23024
23413
|
const now = Date.now();
|
|
23025
23414
|
const active = trust.entries.filter((e) => e.expiry > now);
|
|
23026
23415
|
if (active.length !== trust.entries.length) {
|
|
@@ -23043,8 +23432,8 @@ function writeTrustSession(toolName, durationMs, args) {
|
|
|
23043
23432
|
try {
|
|
23044
23433
|
let trust = { entries: [] };
|
|
23045
23434
|
try {
|
|
23046
|
-
if (
|
|
23047
|
-
trust = JSON.parse(
|
|
23435
|
+
if (fs16.existsSync(TRUST_FILE)) {
|
|
23436
|
+
trust = JSON.parse(fs16.readFileSync(TRUST_FILE, "utf-8"));
|
|
23048
23437
|
}
|
|
23049
23438
|
} catch {
|
|
23050
23439
|
}
|
|
@@ -23066,9 +23455,9 @@ function writeTrustSession(toolName, durationMs, args) {
|
|
|
23066
23455
|
}
|
|
23067
23456
|
function getPersistentDecision(toolName) {
|
|
23068
23457
|
try {
|
|
23069
|
-
const file2 = path16.join(
|
|
23070
|
-
if (!
|
|
23071
|
-
const decisions = JSON.parse(
|
|
23458
|
+
const file2 = path16.join(os11.homedir(), ".node9", "decisions.json");
|
|
23459
|
+
if (!fs16.existsSync(file2)) return null;
|
|
23460
|
+
const decisions = JSON.parse(fs16.readFileSync(file2, "utf-8"));
|
|
23072
23461
|
const d = decisions[toolName];
|
|
23073
23462
|
if (d === "allow" || d === "deny") return d;
|
|
23074
23463
|
} catch {
|
|
@@ -23079,15 +23468,15 @@ function getPersistentDecision(toolName) {
|
|
|
23079
23468
|
// src/auth/daemon.ts
|
|
23080
23469
|
init_esm_shims();
|
|
23081
23470
|
init_forecast_context();
|
|
23082
|
-
import
|
|
23471
|
+
import fs18 from "fs";
|
|
23083
23472
|
import http from "http";
|
|
23084
23473
|
import net from "net";
|
|
23085
23474
|
import path18 from "path";
|
|
23086
|
-
import
|
|
23475
|
+
import os12 from "os";
|
|
23087
23476
|
|
|
23088
23477
|
// src/utils/activity-socket.ts
|
|
23089
23478
|
init_esm_shims();
|
|
23090
|
-
import
|
|
23479
|
+
import fs17 from "fs";
|
|
23091
23480
|
import path17 from "path";
|
|
23092
23481
|
|
|
23093
23482
|
// src/utils/own-dir.ts
|
|
@@ -23097,7 +23486,7 @@ init_esm_shims();
|
|
|
23097
23486
|
var currentUid = () => typeof process.getuid === "function" ? process.getuid() : void 0;
|
|
23098
23487
|
function isPrivateDir(dir2, uid = currentUid()) {
|
|
23099
23488
|
try {
|
|
23100
|
-
const st =
|
|
23489
|
+
const st = fs17.lstatSync(dir2);
|
|
23101
23490
|
if (st.isSymbolicLink() || !st.isDirectory()) return false;
|
|
23102
23491
|
if (uid !== void 0 && st.uid !== uid) return false;
|
|
23103
23492
|
return (st.mode & 18) === 0;
|
|
@@ -23109,7 +23498,7 @@ var WINDOWS_PIPE = /^\\\\\.\\pipe\\node9-activity-[0-9a-f]{32}$/;
|
|
|
23109
23498
|
function isTrustedActivitySocket(socketPath, uid = currentUid()) {
|
|
23110
23499
|
if (process.platform === "win32") return WINDOWS_PIPE.test(socketPath);
|
|
23111
23500
|
try {
|
|
23112
|
-
const st =
|
|
23501
|
+
const st = fs17.lstatSync(socketPath);
|
|
23113
23502
|
if (!st.isSocket()) return false;
|
|
23114
23503
|
if (uid !== void 0 && st.uid !== uid) return false;
|
|
23115
23504
|
} catch {
|
|
@@ -23267,9 +23656,9 @@ function recordFromLegacyWait(body, now = Date.now()) {
|
|
|
23267
23656
|
}
|
|
23268
23657
|
|
|
23269
23658
|
// src/auth/daemon.ts
|
|
23270
|
-
function daemonActivitySocket(home =
|
|
23659
|
+
function daemonActivitySocket(home = os12.homedir()) {
|
|
23271
23660
|
try {
|
|
23272
|
-
const raw =
|
|
23661
|
+
const raw = fs18.readFileSync(path18.join(home, ".node9", "daemon.pid"), "utf-8");
|
|
23273
23662
|
const p = JSON.parse(raw).activitySocket;
|
|
23274
23663
|
return typeof p === "string" && isTrustedActivitySocket(p) ? p : null;
|
|
23275
23664
|
} catch {
|
|
@@ -23333,9 +23722,9 @@ var DAEMON_HOST = "127.0.0.1";
|
|
|
23333
23722
|
function getInternalToken() {
|
|
23334
23723
|
if (forecastRun()) return null;
|
|
23335
23724
|
try {
|
|
23336
|
-
const pidFile = path18.join(
|
|
23337
|
-
if (!
|
|
23338
|
-
const data = JSON.parse(
|
|
23725
|
+
const pidFile = path18.join(os12.homedir(), ".node9", "daemon.pid");
|
|
23726
|
+
if (!fs18.existsSync(pidFile)) return null;
|
|
23727
|
+
const data = JSON.parse(fs18.readFileSync(pidFile, "utf-8"));
|
|
23339
23728
|
process.kill(data.pid, 0);
|
|
23340
23729
|
return data.internalToken ?? null;
|
|
23341
23730
|
} catch {
|
|
@@ -23344,12 +23733,12 @@ function getInternalToken() {
|
|
|
23344
23733
|
}
|
|
23345
23734
|
function isDaemonRunning() {
|
|
23346
23735
|
if (forecastRun()) return false;
|
|
23347
|
-
const pidFile = path18.join(
|
|
23348
|
-
if (
|
|
23736
|
+
const pidFile = path18.join(os12.homedir(), ".node9", "daemon.pid");
|
|
23737
|
+
if (fs18.existsSync(pidFile)) {
|
|
23349
23738
|
let pid;
|
|
23350
23739
|
let port;
|
|
23351
23740
|
try {
|
|
23352
|
-
const data = JSON.parse(
|
|
23741
|
+
const data = JSON.parse(fs18.readFileSync(pidFile, "utf-8"));
|
|
23353
23742
|
pid = data.pid;
|
|
23354
23743
|
port = data.port;
|
|
23355
23744
|
} catch {
|
|
@@ -23367,7 +23756,7 @@ function isDaemonRunning() {
|
|
|
23367
23756
|
} catch (err) {
|
|
23368
23757
|
if (err instanceof Error && "code" in err && err.code === "ESRCH") {
|
|
23369
23758
|
try {
|
|
23370
|
-
|
|
23759
|
+
fs18.unlinkSync(pidFile);
|
|
23371
23760
|
} catch {
|
|
23372
23761
|
}
|
|
23373
23762
|
}
|
|
@@ -23391,11 +23780,11 @@ async function daemonHasInteractiveApprover(timeoutMs = 400) {
|
|
|
23391
23780
|
}
|
|
23392
23781
|
}
|
|
23393
23782
|
async function registerDaemonEntry(toolName, args, meta, riskMetadata, activityId, cwd, recoveryCommand, skipBackgroundAuth, viewOnly, localSmartRuleMatched, socketActivitySent, sessionId, card) {
|
|
23394
|
-
const
|
|
23783
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23395
23784
|
const ctrl = new AbortController();
|
|
23396
23785
|
const timer = setTimeout(() => ctrl.abort(), 5e3);
|
|
23397
23786
|
try {
|
|
23398
|
-
const res = await fetch(`${
|
|
23787
|
+
const res = await fetch(`${base3}/check`, {
|
|
23399
23788
|
method: "POST",
|
|
23400
23789
|
headers: { "Content-Type": "application/json" },
|
|
23401
23790
|
body: JSON.stringify({
|
|
@@ -23505,8 +23894,8 @@ function daemonGet(urlPath, signal, token = getInternalToken()) {
|
|
|
23505
23894
|
});
|
|
23506
23895
|
}
|
|
23507
23896
|
async function notifyDaemonViewer(toolName, args, meta, riskMetadata, activityId, socketActivitySent, extra) {
|
|
23508
|
-
const
|
|
23509
|
-
const res = await fetch(`${
|
|
23897
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23898
|
+
const res = await fetch(`${base3}/check`, {
|
|
23510
23899
|
method: "POST",
|
|
23511
23900
|
headers: { "Content-Type": "application/json" },
|
|
23512
23901
|
body: JSON.stringify({
|
|
@@ -23538,9 +23927,9 @@ async function notifyTaint(filePath, source, fromEid) {
|
|
|
23538
23927
|
return;
|
|
23539
23928
|
}
|
|
23540
23929
|
if (!isDaemonRunning()) return;
|
|
23541
|
-
const
|
|
23930
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23542
23931
|
try {
|
|
23543
|
-
await fetch(`${
|
|
23932
|
+
await fetch(`${base3}/taint`, {
|
|
23544
23933
|
method: "POST",
|
|
23545
23934
|
headers: { "Content-Type": "application/json" },
|
|
23546
23935
|
// Phase D2 — fromEid is the audit eid that created this taint (edge source).
|
|
@@ -23558,9 +23947,9 @@ async function checkTaint(paths) {
|
|
|
23558
23947
|
return record ? { tainted: true, record } : { tainted: false };
|
|
23559
23948
|
}
|
|
23560
23949
|
if (!isDaemonRunning()) return { tainted: false, daemonUnavailable: true };
|
|
23561
|
-
const
|
|
23950
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23562
23951
|
try {
|
|
23563
|
-
const res = await fetch(`${
|
|
23952
|
+
const res = await fetch(`${base3}/taint/check`, {
|
|
23564
23953
|
method: "POST",
|
|
23565
23954
|
headers: { "Content-Type": "application/json" },
|
|
23566
23955
|
body: JSON.stringify({ paths }),
|
|
@@ -23588,9 +23977,9 @@ async function notifyWritten(paths) {
|
|
|
23588
23977
|
return;
|
|
23589
23978
|
}
|
|
23590
23979
|
if (paths.length === 0 || !isDaemonRunning()) return;
|
|
23591
|
-
const
|
|
23980
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23592
23981
|
try {
|
|
23593
|
-
await fetch(`${
|
|
23982
|
+
await fetch(`${base3}/written`, {
|
|
23594
23983
|
method: "POST",
|
|
23595
23984
|
headers: exposureHeaders(),
|
|
23596
23985
|
body: JSON.stringify({ paths: paths.slice(0, 64) }),
|
|
@@ -23604,9 +23993,9 @@ async function checkWritten(paths) {
|
|
|
23604
23993
|
const forecast = forecastRun();
|
|
23605
23994
|
if (forecast) return { written: forecast.session.written(paths) };
|
|
23606
23995
|
if (!isDaemonRunning()) return { written: [], daemonUnavailable: true };
|
|
23607
|
-
const
|
|
23996
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23608
23997
|
try {
|
|
23609
|
-
const res = await fetch(`${
|
|
23998
|
+
const res = await fetch(`${base3}/written/check`, {
|
|
23610
23999
|
method: "POST",
|
|
23611
24000
|
headers: exposureHeaders(),
|
|
23612
24001
|
body: JSON.stringify({ paths: paths.slice(0, 64) }),
|
|
@@ -23628,9 +24017,9 @@ async function checkSessionTaint(sessionId) {
|
|
|
23628
24017
|
return record ? { tainted: true, record, exposed } : { tainted: false, exposed };
|
|
23629
24018
|
}
|
|
23630
24019
|
if (!sessionId || !isDaemonRunning()) return { tainted: false };
|
|
23631
|
-
const
|
|
24020
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23632
24021
|
try {
|
|
23633
|
-
const res = await fetch(`${
|
|
24022
|
+
const res = await fetch(`${base3}/session-taint/check`, {
|
|
23634
24023
|
method: "POST",
|
|
23635
24024
|
headers: exposureHeaders(),
|
|
23636
24025
|
body: JSON.stringify({ sessionId }),
|
|
@@ -23648,8 +24037,8 @@ function exposureHeaders() {
|
|
|
23648
24037
|
};
|
|
23649
24038
|
}
|
|
23650
24039
|
async function exposurePost(route, body, timeoutMs) {
|
|
23651
|
-
const
|
|
23652
|
-
const res = await fetch(`${
|
|
24040
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
24041
|
+
const res = await fetch(`${base3}${route}`, {
|
|
23653
24042
|
method: "POST",
|
|
23654
24043
|
headers: exposureHeaders(),
|
|
23655
24044
|
body: JSON.stringify(body),
|
|
@@ -23664,7 +24053,8 @@ async function checkSessionExposure(sessionId) {
|
|
|
23664
24053
|
const record = forecast.session.checkExposure(forecast.now);
|
|
23665
24054
|
return record ? { exposed: true, record } : { exposed: false };
|
|
23666
24055
|
}
|
|
23667
|
-
if (!sessionId
|
|
24056
|
+
if (!sessionId) return { exposed: false };
|
|
24057
|
+
if (!isDaemonRunning()) return { exposed: false, daemonUnavailable: true };
|
|
23668
24058
|
try {
|
|
23669
24059
|
return await exposurePost(
|
|
23670
24060
|
"/session-exposure/check",
|
|
@@ -23688,8 +24078,8 @@ async function approveSessionExposure(sessionId, keys) {
|
|
|
23688
24078
|
}
|
|
23689
24079
|
}
|
|
23690
24080
|
async function resolveViaDaemon(id, decision, internalToken, source, record) {
|
|
23691
|
-
const
|
|
23692
|
-
const res = await fetch(`${
|
|
24081
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
24082
|
+
const res = await fetch(`${base3}/resolve/${id}`, {
|
|
23693
24083
|
method: "POST",
|
|
23694
24084
|
headers: { "Content-Type": "application/json", "X-Node9-Internal": internalToken },
|
|
23695
24085
|
body: JSON.stringify({ decision, ...source && { source }, ...record && { record } }),
|
|
@@ -23707,8 +24097,8 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
23707
24097
|
|
|
23708
24098
|
// src/apps/state.ts
|
|
23709
24099
|
init_esm_shims();
|
|
23710
|
-
import
|
|
23711
|
-
import
|
|
24100
|
+
import fs20 from "fs";
|
|
24101
|
+
import os14 from "os";
|
|
23712
24102
|
import path20 from "path";
|
|
23713
24103
|
|
|
23714
24104
|
// src/apps/catalog.ts
|
|
@@ -23843,22 +24233,22 @@ init_audit();
|
|
|
23843
24233
|
|
|
23844
24234
|
// src/daemon/mcp-tools.ts
|
|
23845
24235
|
init_esm_shims();
|
|
23846
|
-
import
|
|
24236
|
+
import fs19 from "fs";
|
|
23847
24237
|
import path19 from "path";
|
|
23848
|
-
import
|
|
24238
|
+
import os13 from "os";
|
|
23849
24239
|
|
|
23850
24240
|
// src/mcp-cmd.ts
|
|
23851
24241
|
init_esm_shims();
|
|
23852
24242
|
|
|
23853
24243
|
// src/daemon/mcp-tools.ts
|
|
23854
24244
|
function getMcpToolsFile() {
|
|
23855
|
-
return path19.join(
|
|
24245
|
+
return path19.join(os13.homedir(), ".node9", "mcp-tools.json");
|
|
23856
24246
|
}
|
|
23857
24247
|
function readMcpToolsConfig() {
|
|
23858
24248
|
try {
|
|
23859
24249
|
const file2 = getMcpToolsFile();
|
|
23860
|
-
if (!
|
|
23861
|
-
const raw =
|
|
24250
|
+
if (!fs19.existsSync(file2)) return {};
|
|
24251
|
+
const raw = fs19.readFileSync(file2, "utf-8");
|
|
23862
24252
|
return JSON.parse(raw);
|
|
23863
24253
|
} catch {
|
|
23864
24254
|
return {};
|
|
@@ -23866,7 +24256,7 @@ function readMcpToolsConfig() {
|
|
|
23866
24256
|
}
|
|
23867
24257
|
|
|
23868
24258
|
// src/apps/state.ts
|
|
23869
|
-
function appsFilePath(home =
|
|
24259
|
+
function appsFilePath(home = os14.homedir()) {
|
|
23870
24260
|
return path20.join(home, ".node9", "apps.json");
|
|
23871
24261
|
}
|
|
23872
24262
|
var SIGNAL_KINDS = /* @__PURE__ */ new Set(["mcp-server", "command", "package", "env-name"]);
|
|
@@ -23915,7 +24305,7 @@ function readAppsFile(home) {
|
|
|
23915
24305
|
function readAppsFileStrict(home) {
|
|
23916
24306
|
let text;
|
|
23917
24307
|
try {
|
|
23918
|
-
text =
|
|
24308
|
+
text = fs20.readFileSync(appsFilePath(home), "utf8");
|
|
23919
24309
|
} catch (e) {
|
|
23920
24310
|
return e.code === "ENOENT" ? emptyFile() : null;
|
|
23921
24311
|
}
|
|
@@ -23930,7 +24320,7 @@ var NO_LINKS = /* @__PURE__ */ Object.create(null);
|
|
|
23930
24320
|
function localLinks() {
|
|
23931
24321
|
const file2 = appsFilePath();
|
|
23932
24322
|
try {
|
|
23933
|
-
const mtimeMs =
|
|
24323
|
+
const mtimeMs = fs20.statSync(file2).mtimeMs;
|
|
23934
24324
|
if (!linkCache || linkCache.file !== file2 || linkCache.mtimeMs !== mtimeMs) {
|
|
23935
24325
|
linkCache = { mtimeMs, file: file2, links: readAppsFile().links };
|
|
23936
24326
|
}
|
|
@@ -23970,7 +24360,7 @@ function resolveLinkedServer(label2, opts = {}) {
|
|
|
23970
24360
|
}
|
|
23971
24361
|
|
|
23972
24362
|
// src/auth/orchestrator.ts
|
|
23973
|
-
import
|
|
24363
|
+
import os22 from "os";
|
|
23974
24364
|
import path32 from "path";
|
|
23975
24365
|
|
|
23976
24366
|
// src/ui/native.ts
|
|
@@ -24321,12 +24711,12 @@ end run`;
|
|
|
24321
24711
|
|
|
24322
24712
|
// src/canary/registry.ts
|
|
24323
24713
|
init_esm_shims();
|
|
24324
|
-
import
|
|
24325
|
-
import
|
|
24714
|
+
import fs21 from "fs";
|
|
24715
|
+
import os15 from "os";
|
|
24326
24716
|
import path23 from "path";
|
|
24327
24717
|
init_dist();
|
|
24328
24718
|
function canaryStorePath() {
|
|
24329
|
-
return path23.join(
|
|
24719
|
+
return path23.join(os15.homedir(), ".node9", "canaries.json");
|
|
24330
24720
|
}
|
|
24331
24721
|
function isRecord(x) {
|
|
24332
24722
|
if (!x || typeof x !== "object") return false;
|
|
@@ -24337,7 +24727,7 @@ function loadCanaries(opts) {
|
|
|
24337
24727
|
const p = canaryStorePath();
|
|
24338
24728
|
let raw;
|
|
24339
24729
|
try {
|
|
24340
|
-
raw =
|
|
24730
|
+
raw = fs21.readFileSync(p, "utf-8");
|
|
24341
24731
|
} catch (e) {
|
|
24342
24732
|
if (e.code === "ENOENT") return [];
|
|
24343
24733
|
throw e;
|
|
@@ -24365,21 +24755,21 @@ init_dist();
|
|
|
24365
24755
|
// src/auth/session-script.ts
|
|
24366
24756
|
init_esm_shims();
|
|
24367
24757
|
init_dist();
|
|
24368
|
-
import
|
|
24369
|
-
import
|
|
24758
|
+
import fs22 from "fs";
|
|
24759
|
+
import os16 from "os";
|
|
24370
24760
|
import path24 from "path";
|
|
24371
24761
|
var MAX_SCRIPT_BYTES = 64 * 1024;
|
|
24372
24762
|
var MAX_RECORDED_WRITES = 32;
|
|
24373
24763
|
function readScriptFile(resolved) {
|
|
24374
24764
|
let fd;
|
|
24375
24765
|
try {
|
|
24376
|
-
fd =
|
|
24377
|
-
const st =
|
|
24766
|
+
fd = fs22.openSync(resolved, fs22.constants.O_RDONLY | (fs22.constants.O_NONBLOCK ?? 0));
|
|
24767
|
+
const st = fs22.fstatSync(fd);
|
|
24378
24768
|
if (!st.isFile() || st.size > MAX_SCRIPT_BYTES) return null;
|
|
24379
24769
|
const buf = Buffer.alloc(MAX_SCRIPT_BYTES + 1);
|
|
24380
24770
|
let n = 0;
|
|
24381
24771
|
while (n < buf.length) {
|
|
24382
|
-
const got =
|
|
24772
|
+
const got = fs22.readSync(fd, buf, n, buf.length - n, n);
|
|
24383
24773
|
if (got === 0) break;
|
|
24384
24774
|
n += got;
|
|
24385
24775
|
}
|
|
@@ -24390,7 +24780,7 @@ function readScriptFile(resolved) {
|
|
|
24390
24780
|
} finally {
|
|
24391
24781
|
if (fd !== void 0) {
|
|
24392
24782
|
try {
|
|
24393
|
-
|
|
24783
|
+
fs22.closeSync(fd);
|
|
24394
24784
|
} catch {
|
|
24395
24785
|
}
|
|
24396
24786
|
}
|
|
@@ -24400,16 +24790,16 @@ function absolute(p, cwd, home) {
|
|
|
24400
24790
|
const spelled = p === "~" || p.startsWith("~/") ? home + p.slice(1) : p;
|
|
24401
24791
|
return path24.resolve(cwd, spelled);
|
|
24402
24792
|
}
|
|
24403
|
-
async function resolveSessionScript(toolName, args, cwd, layers, deps, home =
|
|
24793
|
+
async function resolveSessionScript(toolName, args, cwd, layers, deps, home = os16.homedir()) {
|
|
24404
24794
|
try {
|
|
24405
24795
|
const d = deps ?? { checkWritten, readScript: readScriptFile };
|
|
24406
24796
|
const shell = resolveShellInput(toolName, args, layers);
|
|
24407
24797
|
if (shell.kind !== "shell") return null;
|
|
24408
24798
|
const operands2 = shellScriptOperands(shell.command);
|
|
24409
24799
|
if (operands2.length === 0) return null;
|
|
24410
|
-
const
|
|
24800
|
+
const base3 = cwd ?? process.cwd();
|
|
24411
24801
|
const byResolved = /* @__PURE__ */ new Map();
|
|
24412
|
-
for (const op of operands2) byResolved.set(absolute(op,
|
|
24802
|
+
for (const op of operands2) byResolved.set(absolute(op, base3, home), op);
|
|
24413
24803
|
const { written } = await d.checkWritten([...byResolved.keys()]);
|
|
24414
24804
|
for (const resolved of written) {
|
|
24415
24805
|
const spelled = byResolved.get(resolved);
|
|
@@ -24421,7 +24811,7 @@ async function resolveSessionScript(toolName, args, cwd, layers, deps, home = os
|
|
|
24421
24811
|
path: spelled,
|
|
24422
24812
|
resolved,
|
|
24423
24813
|
args: scriptArgs,
|
|
24424
|
-
fileAccess: prepareFileAccesses("Bash", scriptArgs,
|
|
24814
|
+
fileAccess: prepareFileAccesses("Bash", scriptArgs, base3, layers, home)
|
|
24425
24815
|
};
|
|
24426
24816
|
}
|
|
24427
24817
|
return null;
|
|
@@ -24429,17 +24819,17 @@ async function resolveSessionScript(toolName, args, cwd, layers, deps, home = os
|
|
|
24429
24819
|
return null;
|
|
24430
24820
|
}
|
|
24431
24821
|
}
|
|
24432
|
-
function sessionWriteTargets(toolName, args, fileAccess, cwd, home =
|
|
24433
|
-
const
|
|
24822
|
+
function sessionWriteTargets(toolName, args, fileAccess, cwd, home = os16.homedir()) {
|
|
24823
|
+
const base3 = cwd ?? process.cwd();
|
|
24434
24824
|
const out = /* @__PURE__ */ new Set();
|
|
24435
24825
|
const argsObj = args && typeof args === "object" ? args : {};
|
|
24436
24826
|
const named = argsObj.file_path ?? argsObj.path ?? argsObj.filename;
|
|
24437
24827
|
if (typeof named === "string" && named && /write|edit|create|save|append/i.test(toolName))
|
|
24438
|
-
out.add(absolute(named,
|
|
24828
|
+
out.add(absolute(named, base3, home));
|
|
24439
24829
|
for (const a of fileAccess?.accesses ?? []) {
|
|
24440
24830
|
if (a.operation !== "write" && a.operation !== "create") continue;
|
|
24441
24831
|
if (a.glob || a.recursive) continue;
|
|
24442
|
-
out.add(absolute(a.path, a.cwd ??
|
|
24832
|
+
out.add(absolute(a.path, a.cwd ?? base3, home));
|
|
24443
24833
|
if (out.size >= MAX_RECORDED_WRITES) break;
|
|
24444
24834
|
}
|
|
24445
24835
|
return [...out];
|
|
@@ -24460,27 +24850,27 @@ init_dist();
|
|
|
24460
24850
|
|
|
24461
24851
|
// src/exposure/known-hosts.ts
|
|
24462
24852
|
init_esm_shims();
|
|
24463
|
-
import
|
|
24853
|
+
import fs24 from "fs";
|
|
24464
24854
|
import path26 from "path";
|
|
24465
24855
|
|
|
24466
24856
|
// src/utils/git-remotes.ts
|
|
24467
24857
|
init_esm_shims();
|
|
24468
24858
|
init_dist();
|
|
24469
|
-
import
|
|
24859
|
+
import fs23 from "fs";
|
|
24470
24860
|
import path25 from "path";
|
|
24471
|
-
function
|
|
24861
|
+
function readSmallFile2(p, max) {
|
|
24472
24862
|
let fd;
|
|
24473
24863
|
try {
|
|
24474
|
-
fd =
|
|
24475
|
-
const st =
|
|
24864
|
+
fd = fs23.openSync(p, fs23.constants.O_RDONLY | (fs23.constants.O_NOFOLLOW ?? 0));
|
|
24865
|
+
const st = fs23.fstatSync(fd);
|
|
24476
24866
|
if (!st.isFile() || st.size > max) return null;
|
|
24477
24867
|
const buf = Buffer.alloc(st.size);
|
|
24478
|
-
const n =
|
|
24868
|
+
const n = fs23.readSync(fd, buf, 0, st.size, 0);
|
|
24479
24869
|
return buf.subarray(0, n).toString("utf8");
|
|
24480
24870
|
} catch {
|
|
24481
24871
|
return null;
|
|
24482
24872
|
} finally {
|
|
24483
|
-
if (fd !== void 0)
|
|
24873
|
+
if (fd !== void 0) fs23.closeSync(fd);
|
|
24484
24874
|
}
|
|
24485
24875
|
}
|
|
24486
24876
|
function gitRemoteHost(url) {
|
|
@@ -24502,15 +24892,15 @@ function findGitConfig(dir2, walkUp = true) {
|
|
|
24502
24892
|
let cur = path25.resolve(dir2);
|
|
24503
24893
|
for (let i = 0; i < (walkUp ? 64 : 1); i++) {
|
|
24504
24894
|
const dotGit = path25.join(cur, ".git");
|
|
24505
|
-
const direct =
|
|
24895
|
+
const direct = readSmallFile2(path25.join(dotGit, "config"), 1e6);
|
|
24506
24896
|
if (direct !== null) return direct;
|
|
24507
|
-
const pointer =
|
|
24897
|
+
const pointer = readSmallFile2(dotGit, 4096);
|
|
24508
24898
|
const m = pointer && /^gitdir:\s*(.+?)\s*$/m.exec(pointer);
|
|
24509
24899
|
if (m) {
|
|
24510
24900
|
let gitDir = path25.resolve(cur, m[1]);
|
|
24511
|
-
const common =
|
|
24901
|
+
const common = readSmallFile2(path25.join(gitDir, "commondir"), 4096);
|
|
24512
24902
|
if (common !== null) gitDir = path25.resolve(gitDir, common.trim());
|
|
24513
|
-
return
|
|
24903
|
+
return readSmallFile2(path25.join(gitDir, "config"), 1e6);
|
|
24514
24904
|
}
|
|
24515
24905
|
const parent = path25.dirname(cur);
|
|
24516
24906
|
if (parent === cur) return null;
|
|
@@ -24567,7 +24957,7 @@ function manifestRoot(dir2) {
|
|
|
24567
24957
|
for (let i = 0; i < 64; i++) {
|
|
24568
24958
|
for (const [m] of ECOSYSTEMS) {
|
|
24569
24959
|
try {
|
|
24570
|
-
if (
|
|
24960
|
+
if (fs24.existsSync(path26.join(cur, m))) return cur;
|
|
24571
24961
|
} catch {
|
|
24572
24962
|
}
|
|
24573
24963
|
}
|
|
@@ -24593,10 +24983,10 @@ function knownProjectHosts(dir2) {
|
|
|
24593
24983
|
const root = manifestRoot(key);
|
|
24594
24984
|
if (root !== null) {
|
|
24595
24985
|
for (const [m, registry] of ECOSYSTEMS) {
|
|
24596
|
-
if (
|
|
24986
|
+
if (fs24.existsSync(path26.join(root, m))) out.hosts.add(registry);
|
|
24597
24987
|
}
|
|
24598
24988
|
try {
|
|
24599
|
-
if (
|
|
24989
|
+
if (fs24.readdirSync(root).some((f) => f.endsWith(".gemspec")))
|
|
24600
24990
|
out.hosts.add("host:rubygems.org");
|
|
24601
24991
|
} catch {
|
|
24602
24992
|
}
|
|
@@ -24610,8 +25000,8 @@ function knownProjectHosts(dir2) {
|
|
|
24610
25000
|
// src/exposure/writes.ts
|
|
24611
25001
|
init_esm_shims();
|
|
24612
25002
|
init_dist();
|
|
24613
|
-
import
|
|
24614
|
-
import
|
|
25003
|
+
import fs25 from "fs";
|
|
25004
|
+
import os17 from "os";
|
|
24615
25005
|
import path27 from "path";
|
|
24616
25006
|
var WRITE_OPS = /* @__PURE__ */ new Set(["write", "create", "remove"]);
|
|
24617
25007
|
var LIFECYCLE_RE = /"(scripts|preinstall|install|postinstall|prepare|prepublish|prepublishOnly|prepack|postpack|publish|postpublish)"\s*:/;
|
|
@@ -24641,7 +25031,7 @@ function packageScriptsTouched(args, absPath, shellCommand) {
|
|
|
24641
25031
|
if (typeof a.content === "string") {
|
|
24642
25032
|
try {
|
|
24643
25033
|
const next = JSON.parse(a.content);
|
|
24644
|
-
const prev = JSON.parse(
|
|
25034
|
+
const prev = JSON.parse(fs25.readFileSync(absPath, "utf8"));
|
|
24645
25035
|
return JSON.stringify(next.scripts ?? null) !== JSON.stringify(prev.scripts ?? null);
|
|
24646
25036
|
} catch {
|
|
24647
25037
|
return LIFECYCLE_RE.test(a.content);
|
|
@@ -24651,8 +25041,8 @@ function packageScriptsTouched(args, absPath, shellCommand) {
|
|
|
24651
25041
|
}
|
|
24652
25042
|
function judgeWritesAfterExposure(opts) {
|
|
24653
25043
|
const holds = [];
|
|
24654
|
-
const home = opts.home ??
|
|
24655
|
-
const tmp = normalizeFilePath(
|
|
25044
|
+
const home = opts.home ?? os17.homedir();
|
|
25045
|
+
const tmp = normalizeFilePath(os17.tmpdir());
|
|
24656
25046
|
const root = opts.cwd ? normalizeFilePath(opts.cwd, "", home) : null;
|
|
24657
25047
|
const seen = /* @__PURE__ */ new Set();
|
|
24658
25048
|
for (const access of opts.accesses) {
|
|
@@ -24685,8 +25075,8 @@ function judgeWritesAfterExposure(opts) {
|
|
|
24685
25075
|
// src/exposure/marker.ts
|
|
24686
25076
|
init_esm_shims();
|
|
24687
25077
|
import crypto3 from "crypto";
|
|
24688
|
-
import
|
|
24689
|
-
import
|
|
25078
|
+
import fs26 from "fs";
|
|
25079
|
+
import os18 from "os";
|
|
24690
25080
|
import path28 from "path";
|
|
24691
25081
|
|
|
24692
25082
|
// src/daemon/exposure-store.ts
|
|
@@ -24696,7 +25086,7 @@ var SESSION_EXPOSURE_TTL_MS = 4 * 60 * 60 * 1e3;
|
|
|
24696
25086
|
// src/exposure/marker.ts
|
|
24697
25087
|
init_forecast_context();
|
|
24698
25088
|
function dir() {
|
|
24699
|
-
return path28.join(
|
|
25089
|
+
return path28.join(os18.homedir(), ".node9", "exposure-sessions");
|
|
24700
25090
|
}
|
|
24701
25091
|
function file(sessionId) {
|
|
24702
25092
|
const id = crypto3.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
|
|
@@ -24707,7 +25097,7 @@ function maybeSessionExposed(sessionId) {
|
|
|
24707
25097
|
const forecast = forecastRun();
|
|
24708
25098
|
if (forecast) return forecast.session.checkExposure(forecast.now) !== null;
|
|
24709
25099
|
try {
|
|
24710
|
-
const st =
|
|
25100
|
+
const st = fs26.statSync(file(sessionId));
|
|
24711
25101
|
return Date.now() - st.mtimeMs < SESSION_EXPOSURE_TTL_MS;
|
|
24712
25102
|
} catch (e) {
|
|
24713
25103
|
return e.code !== "ENOENT";
|
|
@@ -24716,7 +25106,7 @@ function maybeSessionExposed(sessionId) {
|
|
|
24716
25106
|
|
|
24717
25107
|
// src/exposure/roles.ts
|
|
24718
25108
|
init_esm_shims();
|
|
24719
|
-
import
|
|
25109
|
+
import fs27 from "fs";
|
|
24720
25110
|
var EXPOSURE_LABEL = "\u{1F6E1}\uFE0F Node9 Exposure";
|
|
24721
25111
|
var AGENT_INTERNAL_PREFIXES = ["ccd_", "visualize"];
|
|
24722
25112
|
function foldServerName(name) {
|
|
@@ -24726,7 +25116,7 @@ var inventoryCache = null;
|
|
|
24726
25116
|
var inventoryStamp = null;
|
|
24727
25117
|
function inventoryFileStamp() {
|
|
24728
25118
|
try {
|
|
24729
|
-
const st =
|
|
25119
|
+
const st = fs27.statSync(getMcpToolsFile());
|
|
24730
25120
|
return `${st.mtimeMs}:${st.size}`;
|
|
24731
25121
|
} catch {
|
|
24732
25122
|
return "";
|
|
@@ -24812,15 +25202,15 @@ function sourceWord(toolName) {
|
|
|
24812
25202
|
// src/auth/trusted-recipients.ts
|
|
24813
25203
|
init_esm_shims();
|
|
24814
25204
|
init_dist();
|
|
24815
|
-
import
|
|
25205
|
+
import fs28 from "fs";
|
|
24816
25206
|
import path29 from "path";
|
|
24817
|
-
import
|
|
25207
|
+
import os19 from "os";
|
|
24818
25208
|
function getTrustedRecipientsPath() {
|
|
24819
|
-
return path29.join(
|
|
25209
|
+
return path29.join(os19.homedir(), ".node9", "trusted-recipients.json");
|
|
24820
25210
|
}
|
|
24821
25211
|
function readTrustedRecipients() {
|
|
24822
25212
|
try {
|
|
24823
|
-
const raw =
|
|
25213
|
+
const raw = fs28.readFileSync(getTrustedRecipientsPath(), "utf8");
|
|
24824
25214
|
const parsed = JSON.parse(raw);
|
|
24825
25215
|
return Array.isArray(parsed.entries) ? parsed.entries.filter((e) => e && typeof e.value === "string") : [];
|
|
24826
25216
|
} catch {
|
|
@@ -24829,10 +25219,10 @@ function readTrustedRecipients() {
|
|
|
24829
25219
|
}
|
|
24830
25220
|
function writeTrustedRecipients(entries) {
|
|
24831
25221
|
const filePath = getTrustedRecipientsPath();
|
|
24832
|
-
|
|
25222
|
+
fs28.mkdirSync(path29.dirname(filePath), { recursive: true });
|
|
24833
25223
|
const tmp = filePath + ".node9-tmp";
|
|
24834
|
-
|
|
24835
|
-
|
|
25224
|
+
fs28.writeFileSync(tmp, JSON.stringify({ entries }, null, 2), { mode: 384 });
|
|
25225
|
+
fs28.renameSync(tmp, filePath);
|
|
24836
25226
|
}
|
|
24837
25227
|
function addTrustedRecipient(raw, addedBy = "user") {
|
|
24838
25228
|
const value = normalizeRecipient(raw);
|
|
@@ -24847,7 +25237,7 @@ function addTrustedRecipient(raw, addedBy = "user") {
|
|
|
24847
25237
|
var cache6 = null;
|
|
24848
25238
|
function mtimeOf() {
|
|
24849
25239
|
try {
|
|
24850
|
-
return
|
|
25240
|
+
return fs28.statSync(getTrustedRecipientsPath()).mtimeMs;
|
|
24851
25241
|
} catch {
|
|
24852
25242
|
return 0;
|
|
24853
25243
|
}
|
|
@@ -24866,8 +25256,8 @@ init_forecast_context();
|
|
|
24866
25256
|
// src/auth/cloud.ts
|
|
24867
25257
|
init_esm_shims();
|
|
24868
25258
|
init_audit();
|
|
24869
|
-
import
|
|
24870
|
-
import
|
|
25259
|
+
import fs29 from "fs";
|
|
25260
|
+
import os20 from "os";
|
|
24871
25261
|
import path30 from "path";
|
|
24872
25262
|
init_dist();
|
|
24873
25263
|
var CLOUD_ARRAY_KEYS = /* @__PURE__ */ new Set(["exposureDestinations", "exposureDestinationHashes"]);
|
|
@@ -24903,7 +25293,7 @@ async function initNode9SaaS(toolName, args, creds, meta, riskMetadata, agentPol
|
|
|
24903
25293
|
let ciContext;
|
|
24904
25294
|
if (process.env.CI) {
|
|
24905
25295
|
try {
|
|
24906
|
-
const ciContextPath = path30.join(
|
|
25296
|
+
const ciContextPath = path30.join(os20.homedir(), ".node9", "ci-context.json");
|
|
24907
25297
|
const ci = readCappedText(ciContextPath, 1e4);
|
|
24908
25298
|
if (!ci) throw new Error("ci-context.json unreadable");
|
|
24909
25299
|
if (ci.truncated) throw new Error("ci-context.json exceeds 10 KB");
|
|
@@ -24945,9 +25335,9 @@ async function initNode9SaaS(toolName, args, creds, meta, riskMetadata, agentPol
|
|
|
24945
25335
|
context: {
|
|
24946
25336
|
agent: meta?.agent,
|
|
24947
25337
|
mcpServer: meta?.mcpServer,
|
|
24948
|
-
hostname:
|
|
25338
|
+
hostname: os20.hostname(),
|
|
24949
25339
|
cwd: process.cwd(),
|
|
24950
|
-
platform:
|
|
25340
|
+
platform: os20.platform()
|
|
24951
25341
|
},
|
|
24952
25342
|
// The SaaS validates riskMetadata strictly and would drop it whole on
|
|
24953
25343
|
// an unknown key, so only fields its schema declares go on the wire.
|
|
@@ -25021,14 +25411,14 @@ async function resolveNode9SaaS(requestId, creds, approved, decidedBy) {
|
|
|
25021
25411
|
});
|
|
25022
25412
|
clearTimeout(timer);
|
|
25023
25413
|
if (!res.ok) {
|
|
25024
|
-
|
|
25414
|
+
fs29.appendFileSync(
|
|
25025
25415
|
HOOK_DEBUG_LOG,
|
|
25026
25416
|
`[resolve-cloud] PATCH ${safeMessage(resolveUrl, 200)} \u2192 HTTP ${res.status}
|
|
25027
25417
|
`
|
|
25028
25418
|
);
|
|
25029
25419
|
}
|
|
25030
25420
|
} catch (err) {
|
|
25031
|
-
|
|
25421
|
+
fs29.appendFileSync(
|
|
25032
25422
|
HOOK_DEBUG_LOG,
|
|
25033
25423
|
`[resolve-cloud] PATCH failed for ${safeMessage(requestId, 64)}: ${safeMessage(err)}
|
|
25034
25424
|
`
|
|
@@ -25041,16 +25431,16 @@ init_esm_shims();
|
|
|
25041
25431
|
init_dist();
|
|
25042
25432
|
init_forecast_context();
|
|
25043
25433
|
init_dist();
|
|
25044
|
-
import
|
|
25434
|
+
import fs30 from "fs";
|
|
25045
25435
|
import path31 from "path";
|
|
25046
|
-
import
|
|
25436
|
+
import os21 from "os";
|
|
25047
25437
|
function loopStateFile() {
|
|
25048
|
-
return path31.join(
|
|
25438
|
+
return path31.join(os21.homedir(), ".node9", "loop-state.json");
|
|
25049
25439
|
}
|
|
25050
25440
|
function readState() {
|
|
25051
25441
|
try {
|
|
25052
|
-
if (!
|
|
25053
|
-
const raw =
|
|
25442
|
+
if (!fs30.existsSync(loopStateFile())) return [];
|
|
25443
|
+
const raw = fs30.readFileSync(loopStateFile(), "utf-8");
|
|
25054
25444
|
const parsed = JSON.parse(raw);
|
|
25055
25445
|
if (!Array.isArray(parsed)) return [];
|
|
25056
25446
|
return parsed;
|
|
@@ -25060,10 +25450,10 @@ function readState() {
|
|
|
25060
25450
|
}
|
|
25061
25451
|
function writeState(records) {
|
|
25062
25452
|
const dir2 = path31.dirname(loopStateFile());
|
|
25063
|
-
if (!
|
|
25064
|
-
const tmpPath = `${loopStateFile()}.${
|
|
25065
|
-
|
|
25066
|
-
|
|
25453
|
+
if (!fs30.existsSync(dir2)) fs30.mkdirSync(dir2, { recursive: true });
|
|
25454
|
+
const tmpPath = `${loopStateFile()}.${os21.hostname()}.${process.pid}.tmp`;
|
|
25455
|
+
fs30.writeFileSync(tmpPath, JSON.stringify(records));
|
|
25456
|
+
fs30.renameSync(tmpPath, loopStateFile());
|
|
25067
25457
|
}
|
|
25068
25458
|
function recordAndCheck(tool, args, threshold = 3, windowMs = 12e4) {
|
|
25069
25459
|
try {
|
|
@@ -25262,7 +25652,7 @@ function isMcpToolName(toolName) {
|
|
|
25262
25652
|
return /^mcp__[^_](?:[^_]|_(?!_))*?__/i.test(toolName);
|
|
25263
25653
|
}
|
|
25264
25654
|
function absoluteUploadPath(spelled, cwd) {
|
|
25265
|
-
const expanded = spelled === "~" || spelled.startsWith("~/") ? path32.join(
|
|
25655
|
+
const expanded = spelled === "~" || spelled.startsWith("~/") ? path32.join(os22.homedir(), spelled.slice(1)) : spelled;
|
|
25266
25656
|
if (path32.isAbsolute(expanded)) return expanded;
|
|
25267
25657
|
return cwd && path32.isAbsolute(cwd) ? path32.resolve(cwd, expanded) : expanded;
|
|
25268
25658
|
}
|
|
@@ -25588,8 +25978,17 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25588
25978
|
const judged = sendsSomething || (!!shellExp?.fetches || writes.length > 0) && mayBeExposed;
|
|
25589
25979
|
if (judged) {
|
|
25590
25980
|
const exposure = await checkSessionExposure(meta.sessionId);
|
|
25591
|
-
|
|
25592
|
-
|
|
25981
|
+
const unknownRead = exposure.daemonUnavailable === true && holdsSendsWithoutDaemon(config.settings.mode);
|
|
25982
|
+
const rec = exposure.exposed && exposure.record ? exposure.record : unknownRead ? {
|
|
25983
|
+
sessionId: meta.sessionId,
|
|
25984
|
+
sources: [],
|
|
25985
|
+
destinations: [],
|
|
25986
|
+
userMentioned: [],
|
|
25987
|
+
approved: [],
|
|
25988
|
+
createdAt: 0,
|
|
25989
|
+
expiresAt: 0
|
|
25990
|
+
} : null;
|
|
25991
|
+
if (rec) {
|
|
25593
25992
|
const dests = new Set(
|
|
25594
25993
|
acts && !shellExp && !mcpFileWrite ? extractArgDestinations(args) : []
|
|
25595
25994
|
);
|
|
@@ -25648,7 +26047,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25648
26047
|
if (dests.size === 0 && acts && !mcpFileWrite && (role.destructive === true || isDestructiveToolName(bare))) {
|
|
25649
26048
|
held.push({ dest: "", why: "destructive" });
|
|
25650
26049
|
}
|
|
25651
|
-
const writeHolds = writes.length > 0 ? judgeWritesAfterExposure({
|
|
26050
|
+
const writeHolds = writes.length > 0 && !(unknownRead && !exposure.exposed) ? judgeWritesAfterExposure({
|
|
25652
26051
|
accesses: writes,
|
|
25653
26052
|
args,
|
|
25654
26053
|
shellCommand: shellInput.kind === "shell" ? shellInput.command : null,
|
|
@@ -25675,14 +26074,14 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25675
26074
|
const parts = held.map(
|
|
25676
26075
|
(h) => h.dest ? `sends to ${destinationValue(h.dest)}, ${h.why === "appeared in what was read" ? `${noun(h.dest)} that appeared in that ${last ? readWord : "content"}` : `${noun(h.dest)} this session did not know`}` : h.why === "repository" ? h.repo.endsWith("/*") ? `sends to a repository on ${h.repo.slice(0, -2)} it does not name (a gist, a new repository or an API call)` : `sends to ${h.repo}, a repository that is not one of this project's remotes` : h.why === "unresolved" ? "sends to a destination this session cannot see (built at run time, or a remote of another repository)" : `is ${bare}, a destructive call, with no known destination`
|
|
25677
26076
|
);
|
|
25678
|
-
const home =
|
|
26077
|
+
const home = os22.homedir();
|
|
25679
26078
|
const short = (p) => p.startsWith(home + "/") ? "~" + p.slice(home.length) : p;
|
|
25680
26079
|
for (const w of writeHolds) {
|
|
25681
26080
|
parts.push(
|
|
25682
26081
|
w.why === "outside-project" ? `writes outside the project, to ${short(w.path)}` : w.why === "agent-instruction" ? `writes to ${short(w.path)}, a file that runs code or instructs the agent` : `writes content carrying ${destinationValue(w.destination ?? "")}, ${noun(w.destination ?? "host:x")} that appeared in that ${readWord}`
|
|
25683
26082
|
);
|
|
25684
26083
|
}
|
|
25685
|
-
exposureReview = `\u{1F6E1}\uFE0F Node9: this session read ${read2}. This call ${parts.join("; and ")}.`;
|
|
26084
|
+
exposureReview = unknownRead && !exposure.exposed ? `\u{1F6E1}\uFE0F Node9: the node9 daemon is not running, so node9 cannot tell what this session read. This call ${parts.join("; and ")}. Start it with: node9 daemon start.` : `\u{1F6E1}\uFE0F Node9: this session read ${read2}. This call ${parts.join("; and ")}.`;
|
|
25686
26085
|
exposureFromEid = last?.eid;
|
|
25687
26086
|
if (exposureFromEid) exposureMeta = { exposureFromEid };
|
|
25688
26087
|
exposureKeys = [
|