@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.js
CHANGED
|
@@ -436,15 +436,15 @@ function ssrfExemptMatches(entries, normalized) {
|
|
|
436
436
|
continue;
|
|
437
437
|
}
|
|
438
438
|
if (!target) continue;
|
|
439
|
-
const
|
|
439
|
+
const base3 = bitsOf(normalizeIpLiteral(entry.slice(0, slash)) ?? "");
|
|
440
440
|
const prefixText = entry.slice(slash + 1);
|
|
441
441
|
const prefix = /^\d+$/.test(prefixText) ? Number(prefixText) : NaN;
|
|
442
|
-
if (!
|
|
442
|
+
if (!base3 || !Number.isInteger(prefix) || prefix < 0 || // A v4 range never matches a v6 address, and the reverse: the widths
|
|
443
443
|
// differ, so `0.0.0.0/0` does not release `::1`.
|
|
444
|
-
|
|
444
|
+
base3.length !== target.length || prefix > base3.length) {
|
|
445
445
|
continue;
|
|
446
446
|
}
|
|
447
|
-
if (
|
|
447
|
+
if (base3.slice(0, prefix) === target.slice(0, prefix)) return true;
|
|
448
448
|
}
|
|
449
449
|
return false;
|
|
450
450
|
}
|
|
@@ -498,6 +498,10 @@ function reviewsEveryAgentFileWrite(mode) {
|
|
|
498
498
|
const level = levelOf(mode);
|
|
499
499
|
return level === "strict" || level === "block-all";
|
|
500
500
|
}
|
|
501
|
+
function holdsSendsWithoutDaemon(mode) {
|
|
502
|
+
const level = levelOf(mode);
|
|
503
|
+
return level === "strict" || level === "block-all";
|
|
504
|
+
}
|
|
501
505
|
function isBlockAll(mode) {
|
|
502
506
|
return levelOf(mode) === "block-all";
|
|
503
507
|
}
|
|
@@ -1702,6 +1706,39 @@ function protectedLiteral(code, isProtected) {
|
|
|
1702
1706
|
}
|
|
1703
1707
|
return null;
|
|
1704
1708
|
}
|
|
1709
|
+
function inlineReadPaths(language, code, preload = {}) {
|
|
1710
|
+
const out = [];
|
|
1711
|
+
const before = READ_BEFORE[language];
|
|
1712
|
+
const after = READ_AFTER[language];
|
|
1713
|
+
const assigned = /* @__PURE__ */ new Map();
|
|
1714
|
+
for (const m of code.matchAll(STRING_LITERAL)) {
|
|
1715
|
+
const raw = m[2].trim();
|
|
1716
|
+
const value = raw.replace(/^[<+]\s*/, "");
|
|
1717
|
+
if (!value) continue;
|
|
1718
|
+
const head = code.slice(Math.max(0, m.index - 160), m.index);
|
|
1719
|
+
const tail = code.slice(m.index + m[0].length, m.index + m[0].length + 40);
|
|
1720
|
+
if (/^[>|]/.test(raw) || WRITE_MODE_AFTER.test(tail) || PERL_WRITE_BEFORE.test(head)) continue;
|
|
1721
|
+
if (before.test(head) || after?.test(tail) || language === "node" && DOTENV_PATH_OPTION.test(head)) {
|
|
1722
|
+
out.push(value);
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
const name = ASSIGNED.exec(head)?.[1];
|
|
1726
|
+
if (name) assigned.set(name, [...assigned.get(name) ?? [], value]);
|
|
1727
|
+
}
|
|
1728
|
+
if (assigned.size > 0) {
|
|
1729
|
+
const opened = /* @__PURE__ */ new Set();
|
|
1730
|
+
for (const m of code.matchAll(OPENED_NAME[language])) opened.add(m[1] ?? m[2]);
|
|
1731
|
+
for (const [name, values] of assigned) if (opened.has(name)) out.push(...values);
|
|
1732
|
+
}
|
|
1733
|
+
if (language === "python" || language === "node") {
|
|
1734
|
+
const d = DOTENV[language];
|
|
1735
|
+
const readsEnv = d.env.test(code);
|
|
1736
|
+
const loads = /dotenv/.test(code) && d.load.test(code) && !d.literalPath.test(code);
|
|
1737
|
+
if ((loads || preload.dotenv) && (readsEnv || d.values.test(code))) out.push(".env");
|
|
1738
|
+
if (readsEnv) out.push(...preload.envFiles ?? []);
|
|
1739
|
+
}
|
|
1740
|
+
return out;
|
|
1741
|
+
}
|
|
1705
1742
|
function amplifies(language, code) {
|
|
1706
1743
|
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*\)/;
|
|
1707
1744
|
const m = loop.exec(code);
|
|
@@ -2556,15 +2593,28 @@ function inlineExecCall(stmt, pipeFed) {
|
|
|
2556
2593
|
const fromStdin = () => {
|
|
2557
2594
|
if (stdinFed) {
|
|
2558
2595
|
const { code, source } = stdinCodeOf(redirs);
|
|
2559
|
-
return { interp, code: [code], source };
|
|
2596
|
+
return { interp, code: [code], source, preload };
|
|
2560
2597
|
}
|
|
2561
2598
|
return { interp, code: [null], source: "pipe" };
|
|
2562
2599
|
};
|
|
2563
2600
|
let positionals2 = 0;
|
|
2564
2601
|
let selectedProgram = false;
|
|
2565
2602
|
const codes = [];
|
|
2603
|
+
const preload = {};
|
|
2604
|
+
const nodeFamily = inlineLanguageOf(interp) === "node";
|
|
2566
2605
|
for (let i = 0; i < args.length; i++) {
|
|
2567
2606
|
const a = args[i];
|
|
2607
|
+
if (nodeFamily && !selectedProgram && codes.length === 0 && a != null) {
|
|
2608
|
+
const flag = NODE_VALUE_FLAG.exec(a);
|
|
2609
|
+
if (flag) {
|
|
2610
|
+
const value = flag[2] ?? args[++i];
|
|
2611
|
+
if (value != null) {
|
|
2612
|
+
if (/^--env-file/.test(flag[1])) (preload.envFiles ??= []).push(value);
|
|
2613
|
+
else if (/^dotenv\/config(?:\.js)?$/.test(value)) preload.dotenv = true;
|
|
2614
|
+
}
|
|
2615
|
+
continue;
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2568
2618
|
if (a == null) {
|
|
2569
2619
|
if (codes.length > 0) break;
|
|
2570
2620
|
positionals2++;
|
|
@@ -2601,7 +2651,12 @@ function inlineExecCall(stmt, pipeFed) {
|
|
|
2601
2651
|
}
|
|
2602
2652
|
}
|
|
2603
2653
|
if (codes.length > 0) {
|
|
2604
|
-
return {
|
|
2654
|
+
return {
|
|
2655
|
+
interp,
|
|
2656
|
+
code: codes,
|
|
2657
|
+
source: codes.includes(null) ? "variable" : void 0,
|
|
2658
|
+
preload
|
|
2659
|
+
};
|
|
2605
2660
|
}
|
|
2606
2661
|
if (positionals2 === 0 && (stdinFed || pipeFed)) {
|
|
2607
2662
|
if (!/^(bash|sh|zsh)$/i.test(interp)) return fromStdin();
|
|
@@ -3424,7 +3479,7 @@ function extractShellDestTokens(command) {
|
|
|
3424
3479
|
}
|
|
3425
3480
|
function analyzeFsOperation(command) {
|
|
3426
3481
|
const normalized = normalizeCommandForPolicy(command);
|
|
3427
|
-
if (!FS_OP_PRESCREEN_RE.test(normalized) && !FS_OP_PRESCREEN_RE.test(command) && !SOURCES_FILE_RE.test(command))
|
|
3482
|
+
if (!FS_OP_PRESCREEN_RE.test(normalized) && !FS_OP_PRESCREEN_RE.test(command) && !SOURCES_FILE_RE.test(command) && !runsInlineInterpreter(command, normalized))
|
|
3428
3483
|
return null;
|
|
3429
3484
|
if (fsOpCache.has(command)) {
|
|
3430
3485
|
const hit = fsOpCache.get(command) ?? null;
|
|
@@ -3432,7 +3487,8 @@ function analyzeFsOperation(command) {
|
|
|
3432
3487
|
fsOpCache.set(command, hit);
|
|
3433
3488
|
return hit;
|
|
3434
3489
|
}
|
|
3435
|
-
const
|
|
3490
|
+
const direct = analyzeFsOperationImpl(command) ?? (INDIRECT_SHAPE_RE.test(command) ? structuralJailRead(command) : null);
|
|
3491
|
+
const computed = direct?.verdict === "block" || !runsInlineInterpreter(command, normalized) ? direct : stricter(direct, inlineCodeJailRead(command));
|
|
3436
3492
|
if (fsOpCache.size >= FS_OP_CACHE_MAX) {
|
|
3437
3493
|
const oldest = fsOpCache.keys().next().value;
|
|
3438
3494
|
if (oldest !== void 0) fsOpCache.delete(oldest);
|
|
@@ -3441,8 +3497,8 @@ function analyzeFsOperation(command) {
|
|
|
3441
3497
|
return computed;
|
|
3442
3498
|
}
|
|
3443
3499
|
function isSensitiveCleanupName(p) {
|
|
3444
|
-
const
|
|
3445
|
-
return /^\.env(\.|$)/i.test(
|
|
3500
|
+
const base3 = p.replace(/^.*[\\/]/, "");
|
|
3501
|
+
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);
|
|
3446
3502
|
}
|
|
3447
3503
|
function isWaivableCleanupTarget(p) {
|
|
3448
3504
|
if (/^[/~]/.test(p) || /^\$/.test(p)) return false;
|
|
@@ -4171,6 +4227,24 @@ function structuralJailRead(command) {
|
|
|
4171
4227
|
}
|
|
4172
4228
|
return review;
|
|
4173
4229
|
}
|
|
4230
|
+
function inlineCodeJailRead(command) {
|
|
4231
|
+
const calls = inlineExecCalls(command);
|
|
4232
|
+
if (calls === PARSE_FAIL) return null;
|
|
4233
|
+
let review = null;
|
|
4234
|
+
for (const call of calls) {
|
|
4235
|
+
const language = inlineLanguageOf(call.interp);
|
|
4236
|
+
if (language === null) continue;
|
|
4237
|
+
for (const code of call.code) {
|
|
4238
|
+
if (code === null) continue;
|
|
4239
|
+
for (const p of inlineReadPaths(language, code, call.preload)) {
|
|
4240
|
+
const hit = matchSensitivePath(p);
|
|
4241
|
+
if (hit?.verdict === "block") return hit;
|
|
4242
|
+
review ??= hit;
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
return review;
|
|
4247
|
+
}
|
|
4174
4248
|
function baseWord(w) {
|
|
4175
4249
|
return (w ?? "").split("/").pop()?.toLowerCase() ?? "";
|
|
4176
4250
|
}
|
|
@@ -4728,6 +4802,21 @@ function hits(access, paths, directories, context) {
|
|
|
4728
4802
|
}
|
|
4729
4803
|
return false;
|
|
4730
4804
|
}
|
|
4805
|
+
function hitsNode9Dir(access, dirs, context) {
|
|
4806
|
+
const home = context.homeDirs?.[0] ?? "~";
|
|
4807
|
+
if (access.glob) {
|
|
4808
|
+
const pattern = normalizeFilePath(access.glob, access.cwd ?? context.cwd, home);
|
|
4809
|
+
const magic = pattern.search(/[*?[{]/);
|
|
4810
|
+
const literal = magic < 0 ? pattern : pattern.slice(0, pattern.lastIndexOf("/", magic));
|
|
4811
|
+
return dirs.some((d) => within(literal, d));
|
|
4812
|
+
}
|
|
4813
|
+
const candidates = access.candidates ?? [
|
|
4814
|
+
normalizeFilePath(access.path, access.cwd ?? context.cwd, home)
|
|
4815
|
+
];
|
|
4816
|
+
return candidates.some(
|
|
4817
|
+
(p) => dirs.some((d) => within(p, d)) || access.recursive === true && dirs.some((d) => within(d, p))
|
|
4818
|
+
);
|
|
4819
|
+
}
|
|
4731
4820
|
function hitsSystemDir(access, context, dirs = SYSTEM_DIRS) {
|
|
4732
4821
|
const home = context.homeDirs?.[0] ?? "~";
|
|
4733
4822
|
const candidates = access.candidates ?? [
|
|
@@ -4768,6 +4857,7 @@ function evaluateProtectedFileAccess(accesses, context, settings) {
|
|
|
4768
4857
|
const consider = (result) => {
|
|
4769
4858
|
if (!best || RANK[result.decision] > RANK[best.decision]) best = result;
|
|
4770
4859
|
};
|
|
4860
|
+
const node9Dirs = homes.map((home) => `${home.replace(/\/$/, "")}/.node9`);
|
|
4771
4861
|
for (const access of accesses) {
|
|
4772
4862
|
const mutation = access.operation !== "read";
|
|
4773
4863
|
let kind;
|
|
@@ -4796,6 +4886,10 @@ function evaluateProtectedFileAccess(accesses, context, settings) {
|
|
|
4796
4886
|
"files.system-dirs",
|
|
4797
4887
|
"review-root-home-read",
|
|
4798
4888
|
"Reading the root account's home requires approval"
|
|
4889
|
+
] : mutation && hitsNode9Dir(access, node9Dirs, context) ? [
|
|
4890
|
+
"commands.node9-disarm",
|
|
4891
|
+
"review-node9-disarm",
|
|
4892
|
+
"Changing node9's own files requires approval"
|
|
4799
4893
|
] : null;
|
|
4800
4894
|
} catch {
|
|
4801
4895
|
consider(incompleteFileVerdict(access.operation));
|
|
@@ -5401,9 +5495,9 @@ function validateBelgianNationalNumber(raw) {
|
|
|
5401
5495
|
if (!/^\d{11}$/.test(d)) return false;
|
|
5402
5496
|
const month = Number(d.slice(2, 4)) % 20;
|
|
5403
5497
|
if (month !== 0 && !plausibleDate(String(month).padStart(2, "0"), d.slice(4, 6))) return false;
|
|
5404
|
-
const
|
|
5498
|
+
const base3 = Number(d.slice(0, 9));
|
|
5405
5499
|
const check = Number(d.slice(9, 11));
|
|
5406
|
-
return 97 -
|
|
5500
|
+
return 97 - base3 % 97 === check || 97 - (2e9 + base3) % 97 === check;
|
|
5407
5501
|
}
|
|
5408
5502
|
function validateCuit(raw) {
|
|
5409
5503
|
const d = raw.replace(/-/g, "");
|
|
@@ -6505,9 +6599,9 @@ function evaluateGitHooksFileAccess(args, accesses, context, settings, shell) {
|
|
|
6505
6599
|
}
|
|
6506
6600
|
function agentFileKind(p) {
|
|
6507
6601
|
const lower2 = p.toLowerCase();
|
|
6508
|
-
const
|
|
6509
|
-
if (INSTRUCTION_NAMES.has(
|
|
6510
|
-
if (
|
|
6602
|
+
const base3 = lower2.slice(lower2.lastIndexOf("/") + 1);
|
|
6603
|
+
if (INSTRUCTION_NAMES.has(base3)) return "instructions";
|
|
6604
|
+
if (base3 === "copilot-instructions.md" && lower2.endsWith("/.github/" + base3))
|
|
6511
6605
|
return "instructions";
|
|
6512
6606
|
if (/\/\.cursor\/rules(?:\/|$)/.test(lower2)) return "instructions";
|
|
6513
6607
|
if (/\/\.claude\/projects\/[^/]+\/memory(?:\/|$)/.test(lower2)) return "memory";
|
|
@@ -6676,7 +6770,7 @@ function evaluateAgentFileWrite(args, accesses, context, settings, shell, hooks
|
|
|
6676
6770
|
skills: "agent skill",
|
|
6677
6771
|
settings: "agent settings"
|
|
6678
6772
|
};
|
|
6679
|
-
const
|
|
6773
|
+
const base3 = `${kindLabel[kind]} written: ${access.path}`;
|
|
6680
6774
|
if (!signal && !every) {
|
|
6681
6775
|
return {
|
|
6682
6776
|
decision: "allow",
|
|
@@ -6686,14 +6780,14 @@ function evaluateAgentFileWrite(args, accesses, context, settings, shell, hooks
|
|
|
6686
6780
|
path: access.path,
|
|
6687
6781
|
operation: access.operation,
|
|
6688
6782
|
kind,
|
|
6689
|
-
reason:
|
|
6783
|
+
reason: base3,
|
|
6690
6784
|
ruleDescription: "The AI writes to a file every later agent session loads as instructions.",
|
|
6691
|
-
blockedByLabel: `Node9 Files: ${
|
|
6785
|
+
blockedByLabel: `Node9 Files: ${base3}`,
|
|
6692
6786
|
tier: 2
|
|
6693
6787
|
};
|
|
6694
6788
|
}
|
|
6695
6789
|
const ruleName = signal === "content" ? "review-agent-file-content" : signal === "hooks" ? "review-agent-hooks-change" : "review-agent-file-write";
|
|
6696
|
-
const reason = signal ? `${
|
|
6790
|
+
const reason = signal ? `${base3} (${detail})` : base3;
|
|
6697
6791
|
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.";
|
|
6698
6792
|
return {
|
|
6699
6793
|
decision: value === "log" ? "allow" : value,
|
|
@@ -8301,6 +8395,139 @@ function scanArgumentSecrets(args) {
|
|
|
8301
8395
|
severity: "review"
|
|
8302
8396
|
} : null;
|
|
8303
8397
|
}
|
|
8398
|
+
function patternSelects(pattern, targets) {
|
|
8399
|
+
const pieces = pattern.toLowerCase().split(/[\\^$.*+?()[\]{}|]+/).filter(Boolean);
|
|
8400
|
+
if (pieces.length === 0) return false;
|
|
8401
|
+
return targets.some((t) => pieces.every((p) => t.includes(p)));
|
|
8402
|
+
}
|
|
8403
|
+
function sourceText(bytes, pos, end) {
|
|
8404
|
+
if (typeof pos !== "number" || typeof end !== "number" || pos < 0 || end < pos) return "";
|
|
8405
|
+
return new TextDecoder().decode(bytes.subarray(pos, end));
|
|
8406
|
+
}
|
|
8407
|
+
function nextOperand(words, from) {
|
|
8408
|
+
for (let i = from; i < words.length; i++) {
|
|
8409
|
+
const w = words[i];
|
|
8410
|
+
if (w !== null && w.startsWith("-")) continue;
|
|
8411
|
+
return i;
|
|
8412
|
+
}
|
|
8413
|
+
return -1;
|
|
8414
|
+
}
|
|
8415
|
+
function node9Command(words, h) {
|
|
8416
|
+
const head = base2(words[h]);
|
|
8417
|
+
if (head !== "node9" && head !== "node9.cmd" && words[h] !== "@node9/proxy") return null;
|
|
8418
|
+
const s = nextOperand(words, h + 1);
|
|
8419
|
+
const sub = s < 0 ? "" : (words[s] ?? "").toLowerCase();
|
|
8420
|
+
if (sub === "uninstall") return "node9 uninstall";
|
|
8421
|
+
if (sub !== "daemon") return null;
|
|
8422
|
+
const a = nextOperand(words, s + 1);
|
|
8423
|
+
const action = a < 0 ? "" : (words[a] ?? "").toLowerCase();
|
|
8424
|
+
return action === "stop" || action === "uninstall" ? `node9 daemon ${action}` : null;
|
|
8425
|
+
}
|
|
8426
|
+
function killsDaemon(words, texts, h, daemonPid) {
|
|
8427
|
+
const head = base2(words[h]);
|
|
8428
|
+
const args = words.slice(h + 1);
|
|
8429
|
+
if (head === "kill") {
|
|
8430
|
+
for (let i = 0; i < args.length; i++) {
|
|
8431
|
+
const w = args[i];
|
|
8432
|
+
if (w === "-s" || w === "-n") {
|
|
8433
|
+
i++;
|
|
8434
|
+
continue;
|
|
8435
|
+
}
|
|
8436
|
+
if (w !== null && w.startsWith("-")) continue;
|
|
8437
|
+
if (w === null) {
|
|
8438
|
+
if (HOME_PID_FILE_RE.test(texts[h + 1 + i] ?? "")) return "kill of the pid in daemon.pid";
|
|
8439
|
+
continue;
|
|
8440
|
+
}
|
|
8441
|
+
if (daemonPid !== null && w === String(daemonPid)) return `kill ${w} (the node9 daemon)`;
|
|
8442
|
+
}
|
|
8443
|
+
return null;
|
|
8444
|
+
}
|
|
8445
|
+
if (head === "pkill") {
|
|
8446
|
+
let full = false;
|
|
8447
|
+
let pattern = null;
|
|
8448
|
+
for (let i = 0; i < args.length; i++) {
|
|
8449
|
+
const w = args[i];
|
|
8450
|
+
if (w === null) continue;
|
|
8451
|
+
if (PKILL_VALUE_FLAGS.has(w)) {
|
|
8452
|
+
i++;
|
|
8453
|
+
continue;
|
|
8454
|
+
}
|
|
8455
|
+
if (w === "--full") full = true;
|
|
8456
|
+
else if (/^-[a-zA-Z]+$/.test(w) && w.includes("f")) full = true;
|
|
8457
|
+
if (w.startsWith("-")) continue;
|
|
8458
|
+
pattern = w;
|
|
8459
|
+
}
|
|
8460
|
+
if (pattern === null) return null;
|
|
8461
|
+
return patternSelects(pattern, full ? DAEMON_CMDLINES : DAEMON_NAMES) ? `pkill ${full ? "-f " : ""}${pattern}` : null;
|
|
8462
|
+
}
|
|
8463
|
+
if (head === "killall") {
|
|
8464
|
+
const regex = args.some((w) => w === "-r" || w === "--regexp");
|
|
8465
|
+
for (const w of args) {
|
|
8466
|
+
if (w === null || w.startsWith("-")) continue;
|
|
8467
|
+
if (regex ? patternSelects(w, DAEMON_NAMES) : KILLALL_NAMES.has(w.toLowerCase()))
|
|
8468
|
+
return `killall ${w}`;
|
|
8469
|
+
}
|
|
8470
|
+
return null;
|
|
8471
|
+
}
|
|
8472
|
+
if (head === "taskkill" || head === "taskkill.exe") {
|
|
8473
|
+
for (let i = 0; i < args.length - 1; i++) {
|
|
8474
|
+
const flag = (args[i] ?? "").toLowerCase();
|
|
8475
|
+
const value = (args[i + 1] ?? "").toLowerCase();
|
|
8476
|
+
if ((flag === "/im" || flag === "-im") && KILLALL_NAMES.has(value))
|
|
8477
|
+
return `taskkill /IM ${value}`;
|
|
8478
|
+
if ((flag === "/pid" || flag === "-pid") && daemonPid !== null && value === String(daemonPid))
|
|
8479
|
+
return `taskkill /PID ${value} (the node9 daemon)`;
|
|
8480
|
+
}
|
|
8481
|
+
}
|
|
8482
|
+
return null;
|
|
8483
|
+
}
|
|
8484
|
+
function stopsService(words, h) {
|
|
8485
|
+
const head = base2(words[h]);
|
|
8486
|
+
const args = words.slice(h + 1).map((w) => (w ?? "").toLowerCase());
|
|
8487
|
+
if (head === "systemctl") {
|
|
8488
|
+
const action = args.find((w) => STOP_SYSTEMCTL.has(w));
|
|
8489
|
+
if (action && args.some((w) => /^node9-daemon(\.service)?$/.test(w)))
|
|
8490
|
+
return `systemctl ${action} node9-daemon`;
|
|
8491
|
+
}
|
|
8492
|
+
if (head === "launchctl") {
|
|
8493
|
+
const action = args.find((w) => STOP_LAUNCHCTL.has(w));
|
|
8494
|
+
if (action && args.some((w) => w.includes("ai.node9.daemon")))
|
|
8495
|
+
return `launchctl ${action} ai.node9.daemon`;
|
|
8496
|
+
}
|
|
8497
|
+
return null;
|
|
8498
|
+
}
|
|
8499
|
+
function analyzeNode9Disarm(command, daemonPid = null, depth = 0) {
|
|
8500
|
+
if (depth > 3 || !NAME_PRESCREEN_RE.test(command.replace(/[\\'"]/g, ""))) return null;
|
|
8501
|
+
let shown = null;
|
|
8502
|
+
const bytes = new TextEncoder().encode(command);
|
|
8503
|
+
try {
|
|
8504
|
+
walkCommandScope(command, (node) => {
|
|
8505
|
+
if (shown !== null) return false;
|
|
8506
|
+
const n = node;
|
|
8507
|
+
if (!n || n.kind !== "CallExpr") return true;
|
|
8508
|
+
const words = (n.Args || []).map((a) => resolveWordLiteral(a));
|
|
8509
|
+
if (words.length === 0) return true;
|
|
8510
|
+
const texts = (n.Args || []).map((a) => sourceText(bytes, a.pos, a.end));
|
|
8511
|
+
const h = unwrapCommandHead(words);
|
|
8512
|
+
shown = node9Command(words, h) ?? killsDaemon(words, texts, h, daemonPid) ?? stopsService(words, h);
|
|
8513
|
+
if (shown === null) {
|
|
8514
|
+
const payload = literalShellPayload(words, base2(words[0]));
|
|
8515
|
+
if (payload) {
|
|
8516
|
+
const inner = analyzeNode9Disarm(payload, daemonPid, depth + 1);
|
|
8517
|
+
if (inner) shown = inner.reason.replace(/^node9 switched off by the agent: /, "");
|
|
8518
|
+
}
|
|
8519
|
+
}
|
|
8520
|
+
return true;
|
|
8521
|
+
});
|
|
8522
|
+
} catch {
|
|
8523
|
+
}
|
|
8524
|
+
if (shown === null) return null;
|
|
8525
|
+
return {
|
|
8526
|
+
ruleName: RULE_NAME2,
|
|
8527
|
+
reason: `node9 switched off by the agent: ${shown}`,
|
|
8528
|
+
description: DESCRIPTION
|
|
8529
|
+
};
|
|
8530
|
+
}
|
|
8304
8531
|
function catalogSettings(config) {
|
|
8305
8532
|
return catalogSettingsFromConfig(config.settings, config.policy);
|
|
8306
8533
|
}
|
|
@@ -8394,6 +8621,10 @@ function egressPolicyVerdict(eg) {
|
|
|
8394
8621
|
};
|
|
8395
8622
|
}
|
|
8396
8623
|
async function evaluatePolicy(config, toolName, args, context = {}, hostHooks = {}) {
|
|
8624
|
+
const v = await evaluatePolicyVerdict(config, toolName, args, context, hostHooks);
|
|
8625
|
+
return v.decision === "block" && v.checkId !== void 0 && NOT_OVERRIDABLE_CHECKS.has(v.checkId) ? { ...v, overridable: false } : v;
|
|
8626
|
+
}
|
|
8627
|
+
async function evaluatePolicyVerdict(config, toolName, args, context = {}, hostHooks = {}) {
|
|
8397
8628
|
let protectedVerdict = null;
|
|
8398
8629
|
const layers = inspectionLayers(config.policy);
|
|
8399
8630
|
if (context.agent !== "Terminal") {
|
|
@@ -8451,7 +8682,7 @@ async function evaluatePolicy(config, toolName, args, context = {}, hostHooks =
|
|
|
8451
8682
|
}
|
|
8452
8683
|
async function evaluatePolicyCore(config, toolName, args, context = {}, hooks = {}) {
|
|
8453
8684
|
const { agent, cwd, activeEnvironment } = context;
|
|
8454
|
-
const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2 } = hooks;
|
|
8685
|
+
const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2, daemonPid } = hooks;
|
|
8455
8686
|
const settingsView = catalogSettings(config);
|
|
8456
8687
|
const layers = inspectionLayers(config.policy);
|
|
8457
8688
|
const cv = (id) => checkValue(settingsView, id);
|
|
@@ -8636,6 +8867,23 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
|
|
|
8636
8867
|
else if (v && !pendingAstReview) pendingAstReview = v;
|
|
8637
8868
|
}
|
|
8638
8869
|
}
|
|
8870
|
+
if (cv("commands.node9-disarm") !== "off") {
|
|
8871
|
+
const finding = analyzeNode9Disarm(bashCommand, daemonPid?.() ?? null);
|
|
8872
|
+
if (finding) {
|
|
8873
|
+
const v = applyCheckValue(cv("commands.node9-disarm"), {
|
|
8874
|
+
decision: "review",
|
|
8875
|
+
blockedByLabel: `Node9 (AST): ${finding.ruleName}`,
|
|
8876
|
+
reason: finding.reason,
|
|
8877
|
+
tier: 2,
|
|
8878
|
+
ruleName: finding.ruleName,
|
|
8879
|
+
ruleDescription: finding.description,
|
|
8880
|
+
checkId: "commands.node9-disarm"
|
|
8881
|
+
});
|
|
8882
|
+
if (v?.logged) noteLogged(v);
|
|
8883
|
+
else if (v?.decision === "block") return v;
|
|
8884
|
+
else if (v && !pendingAstReview) pendingAstReview = v;
|
|
8885
|
+
}
|
|
8886
|
+
}
|
|
8639
8887
|
}
|
|
8640
8888
|
if (config.policy.smartRules.length > 0) {
|
|
8641
8889
|
const rmCleanupWaiver = bashCommand !== null && isRmCreatedInCommandCleanup(bashCommand);
|
|
@@ -9083,8 +9331,8 @@ function hasRoutingNumber(text) {
|
|
|
9083
9331
|
}
|
|
9084
9332
|
return false;
|
|
9085
9333
|
}
|
|
9086
|
-
function* validCardRuns(text,
|
|
9087
|
-
const re = new RegExp(
|
|
9334
|
+
function* validCardRuns(text, base3, exemptFractions = true) {
|
|
9335
|
+
const re = new RegExp(base3.source, "g");
|
|
9088
9336
|
let m;
|
|
9089
9337
|
while ((m = re.exec(text)) !== null) {
|
|
9090
9338
|
const digits = m[0].replace(/\D/g, "");
|
|
@@ -9097,17 +9345,17 @@ function* validCardRuns(text, base2, exemptFractions = true) {
|
|
|
9097
9345
|
}
|
|
9098
9346
|
}
|
|
9099
9347
|
function hasValidCard(text) {
|
|
9100
|
-
for (const
|
|
9101
|
-
if (!validCardRuns(text,
|
|
9348
|
+
for (const base3 of CARD_PATTERNS) {
|
|
9349
|
+
if (!validCardRuns(text, base3).next().done) return true;
|
|
9102
9350
|
}
|
|
9103
9351
|
return false;
|
|
9104
9352
|
}
|
|
9105
9353
|
function replaceValidCards(text, replace, { exemptFractions = true } = {}) {
|
|
9106
9354
|
let out = text;
|
|
9107
|
-
for (const
|
|
9355
|
+
for (const base3 of CARD_PATTERNS) {
|
|
9108
9356
|
let res = "";
|
|
9109
9357
|
let last = 0;
|
|
9110
|
-
for (const run of validCardRuns(out,
|
|
9358
|
+
for (const run of validCardRuns(out, base3, exemptFractions)) {
|
|
9111
9359
|
res += out.slice(last, run.index) + replace(run.digits);
|
|
9112
9360
|
last = run.index + run.length;
|
|
9113
9361
|
}
|
|
@@ -9348,9 +9596,9 @@ function maskLeaf(value, key, depth) {
|
|
|
9348
9596
|
const used = /* @__PURE__ */ new Set();
|
|
9349
9597
|
return Object.fromEntries(
|
|
9350
9598
|
Object.entries(value).map(([k, v]) => {
|
|
9351
|
-
const
|
|
9352
|
-
let name =
|
|
9353
|
-
for (let n = 2; used.has(name); n++) name = `${
|
|
9599
|
+
const base3 = maskPersonalData(k);
|
|
9600
|
+
let name = base3;
|
|
9601
|
+
for (let n = 2; used.has(name); n++) name = `${base3}#${n}`;
|
|
9354
9602
|
used.add(name);
|
|
9355
9603
|
return [name, maskLeaf(v, k, depth + 1)];
|
|
9356
9604
|
})
|
|
@@ -9844,7 +10092,7 @@ function matchCanaryArgs(args, values) {
|
|
|
9844
10092
|
return null;
|
|
9845
10093
|
}
|
|
9846
10094
|
}
|
|
9847
|
-
var import_url, import_picomatch, import_safe_regex2, import_picomatch2, import_module, import_picomatch3, import_safe_regex22, import_crypto2, import_crypto3, import_crypto4, import_crypto5, 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;
|
|
10095
|
+
var import_url, import_picomatch, import_safe_regex2, import_picomatch2, import_module, import_picomatch3, import_safe_regex22, import_crypto2, import_crypto3, import_crypto4, import_crypto5, 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;
|
|
9848
10096
|
var init_dist = __esm({
|
|
9849
10097
|
"packages/policy-engine/dist/index.mjs"() {
|
|
9850
10098
|
"use strict";
|
|
@@ -11854,7 +12102,7 @@ var init_dist = __esm({
|
|
|
11854
12102
|
advice: "Fixed at Review for now."
|
|
11855
12103
|
},
|
|
11856
12104
|
"commands.node9-disarm": {
|
|
11857
|
-
plain: "The agent
|
|
12105
|
+
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.",
|
|
11858
12106
|
example: "After reading a web page, the agent runs node9 session-exposure clear --all",
|
|
11859
12107
|
advice: "Keep Review: these are your commands to run. Block if the agent should never touch node9."
|
|
11860
12108
|
},
|
|
@@ -12167,7 +12415,7 @@ var init_dist = __esm({
|
|
|
12167
12415
|
group: "commands",
|
|
12168
12416
|
owasp: "ASI10",
|
|
12169
12417
|
title: "node9 disarmed from the shell",
|
|
12170
|
-
catches: "a node9 command that clears a session flag, trusts a destination, pauses the gate or weakens a shield
|
|
12418
|
+
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",
|
|
12171
12419
|
values: ALL,
|
|
12172
12420
|
defaultValue: "review",
|
|
12173
12421
|
legacy: ["review-node9-disarm"]
|
|
@@ -13048,6 +13296,62 @@ var init_dist = __esm({
|
|
|
13048
13296
|
php: PHP
|
|
13049
13297
|
};
|
|
13050
13298
|
STRING_LITERAL = /(['"`])((?:\\.|(?!\1)[^\\\n]){1,4096})\1/g;
|
|
13299
|
+
READ_CALL = {
|
|
13300
|
+
python: String.raw`(?:\b(?:io|codecs)\.)?\bopen|\b(?:dotenv_values|load_dotenv|get_key|read_file|loadtxt|read_csv)`,
|
|
13301
|
+
node: String.raw`\b(?:readFileSync|readFile|createReadStream|readTextFile(?:Sync)?|readFileStr|openSync|file)`,
|
|
13302
|
+
perl: String.raw`\b(?:open|sysopen|read_file|slurp)`,
|
|
13303
|
+
ruby: String.raw`\b(?:File|IO)\.(?:read|binread|readlines|foreach|open)|\bDotenv\.(?:load|parse|overload)`,
|
|
13304
|
+
php: String.raw`\b(?:file_get_contents|fopen|file|readfile|parse_ini_file|highlight_file|show_source)`
|
|
13305
|
+
};
|
|
13306
|
+
ARG = String.raw`(?:(?:(?:my|our|local)\s+)?[\w.$]+(?:\s*\(\s*\))?|'[^'\n]{0,8}'|"[^"\n]{0,8}")\s*,\s*`;
|
|
13307
|
+
WRAP = String.raw`(?:(?:new\s+)?[\w.$]+\s*\(\s*(?:${ARG}){0,3}){0,3}`;
|
|
13308
|
+
STR_PREFIX = String.raw`[rRbBuUfF]{0,2}`;
|
|
13309
|
+
WRITE_MODE_LITERAL = String.raw`['"](?=[rbtU+]*w|(?![^'"]*\+)[rbtU]*[ax])[rwaxbtU+]{1,4}['"]`;
|
|
13310
|
+
WRITE_MODE = String.raw`\s*,\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL}`;
|
|
13311
|
+
WRITE_MODE_AFTER = new RegExp(`^(?:\\s*\\)){0,3}${WRITE_MODE}`);
|
|
13312
|
+
PERL_WRITE_BEFORE = /['"]\s*(?:\+?[>|]|>>)\s*['"]\s*,\s*$/;
|
|
13313
|
+
readCallBefore = (language) => new RegExp(
|
|
13314
|
+
String.raw`(?:${READ_CALL[language]})(?![\w$])\s*\(?\s*(?:${ARG}){0,3}${WRAP}${STR_PREFIX}$`
|
|
13315
|
+
);
|
|
13316
|
+
READ_BEFORE = {
|
|
13317
|
+
python: readCallBefore("python"),
|
|
13318
|
+
node: readCallBefore("node"),
|
|
13319
|
+
perl: readCallBefore("perl"),
|
|
13320
|
+
ruby: readCallBefore("ruby"),
|
|
13321
|
+
php: readCallBefore("php")
|
|
13322
|
+
};
|
|
13323
|
+
READ_AFTER = {
|
|
13324
|
+
python: new RegExp(
|
|
13325
|
+
String.raw`^\s*\)\s*\.\s*(?:read_text|read_bytes|open)\s*\((?!\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL})`
|
|
13326
|
+
)
|
|
13327
|
+
};
|
|
13328
|
+
ASSIGNED = new RegExp(String.raw`([$\w]+)\s*=\s*${WRAP}${STR_PREFIX}$`);
|
|
13329
|
+
openedName = (language) => new RegExp(
|
|
13330
|
+
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*\(` : ""),
|
|
13331
|
+
"g"
|
|
13332
|
+
);
|
|
13333
|
+
OPENED_NAME = {
|
|
13334
|
+
python: openedName("python"),
|
|
13335
|
+
node: openedName("node"),
|
|
13336
|
+
perl: openedName("perl"),
|
|
13337
|
+
ruby: openedName("ruby"),
|
|
13338
|
+
php: openedName("php")
|
|
13339
|
+
};
|
|
13340
|
+
DOTENV = {
|
|
13341
|
+
node: {
|
|
13342
|
+
load: /\brequire\s*\(\s*['"`]dotenv(?:\/config)?['"`]\s*\)|\bimport\s*(?:[\w${}\s,*]+\s+from\s*)?['"`]dotenv(?:\/config)?['"`]|\bimport\s*\(\s*['"`]dotenv(?:\/config)?['"`]\s*\)/,
|
|
13343
|
+
values: /\.parsed\b|[(,]\s*(?:require\s*\(\s*['"`]dotenv['"`]\s*\)|dotenv)\s*\.\s*config\s*\(/,
|
|
13344
|
+
env: /\b(?:process|Deno|Bun)\s*\.\s*env\b/,
|
|
13345
|
+
literalPath: /\bconfig\s*\(\s*\{[^)]*\bpath\s*:\s*['"`]/
|
|
13346
|
+
},
|
|
13347
|
+
python: {
|
|
13348
|
+
load: /\b(?:load_dotenv|dotenv_values|get_key)\s*\(/,
|
|
13349
|
+
values: /\b(?:dotenv_values|get_key)\s*\(/,
|
|
13350
|
+
env: /\b(?:environ|getenv)\b/,
|
|
13351
|
+
literalPath: /\b(?:load_dotenv|dotenv_values)\s*\(\s*(?:dotenv_path\s*=\s*)?[rRbBuU]?['"]/
|
|
13352
|
+
}
|
|
13353
|
+
};
|
|
13354
|
+
DOTENV_PATH_OPTION = /\bconfig\s*\(\s*\{[^)]*\bpath\s*:\s*$/;
|
|
13051
13355
|
sharedParser = lazy(() => getSyntax().NewParser());
|
|
13052
13356
|
MESSAGE_FLAGS = /* @__PURE__ */ new Set([
|
|
13053
13357
|
"-m",
|
|
@@ -13842,6 +14146,7 @@ var init_dist = __esm({
|
|
|
13842
14146
|
"rmdir"
|
|
13843
14147
|
]);
|
|
13844
14148
|
INTERP_LEADING_TARGET = /* @__PURE__ */ new Set(["su"]);
|
|
14149
|
+
NODE_VALUE_FLAG = /^(-r|--require|--import|--loader|--experimental-loader|--env-file|--env-file-if-exists|--input-type|-C|--conditions)(?:=(.*))?$/;
|
|
13845
14150
|
MAX_PAYLOAD_NESTING = 8;
|
|
13846
14151
|
payloadNesting = 0;
|
|
13847
14152
|
MAX_INLINE_CALLS = 16;
|
|
@@ -14090,6 +14395,8 @@ var init_dist = __esm({
|
|
|
14090
14395
|
JAILED_DIR_NAMES = [".ssh", ".aws"];
|
|
14091
14396
|
shellGlob = (p) => p.replace(/\[!/g, "[^");
|
|
14092
14397
|
GLOB_META = /(?<!\\)[*?[]/;
|
|
14398
|
+
INLINE_INTERP_PRESCREEN_RE = /(?:^|[^\w-])(?:python|node|tsx|ts-node|deno|bun|perl|ruby|irb|php)(?![A-Za-z_])/i;
|
|
14399
|
+
runsInlineInterpreter = (command, normalized) => INLINE_INTERP_PRESCREEN_RE.test(command) || INLINE_INTERP_PRESCREEN_RE.test(normalized);
|
|
14093
14400
|
isReaderWord = (w) => w !== null && FS_READ_TOOLS.has(baseWord(w));
|
|
14094
14401
|
positionalAfter = (words, from, to = words.length) => positionedArgs(words, from, to).map((a) => a.value);
|
|
14095
14402
|
NONE = { kind: "none" };
|
|
@@ -17405,9 +17712,9 @@ zoo`.split("\n");
|
|
|
17405
17712
|
const name = n.Name.Value;
|
|
17406
17713
|
if (n.Append) {
|
|
17407
17714
|
const prev = this.appended.has(name) ? this.appended.get(name) : resolveWordLiteral(n.Value) === null ? null : void 0;
|
|
17408
|
-
const
|
|
17715
|
+
const base3 = prev === void 0 ? recordedExpansion(name) : prev;
|
|
17409
17716
|
const piece = resolveWordLiteral(n.Value);
|
|
17410
|
-
this.appended.set(name, typeof
|
|
17717
|
+
this.appended.set(name, typeof base3 === "string" && piece !== null ? base3 + piece : null);
|
|
17411
17718
|
this.treeTopVars.delete(name);
|
|
17412
17719
|
return true;
|
|
17413
17720
|
}
|
|
@@ -18923,12 +19230,50 @@ ${text}` : text);
|
|
|
18923
19230
|
const char = value[index] ?? "";
|
|
18924
19231
|
return RUN_CHAR.test(char) || char !== "" && isInvisibleChar(char);
|
|
18925
19232
|
};
|
|
19233
|
+
RULE_NAME2 = "review-node9-disarm";
|
|
19234
|
+
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.";
|
|
19235
|
+
DAEMON_CMDLINES = [
|
|
19236
|
+
"node /usr/lib/node_modules/@node9/proxy/dist/cli.js daemon start",
|
|
19237
|
+
"node9 daemon start"
|
|
19238
|
+
];
|
|
19239
|
+
DAEMON_NAMES = ["node", "node9"];
|
|
19240
|
+
KILLALL_NAMES = /* @__PURE__ */ new Set(["node", "node9", "node.exe", "node9.exe"]);
|
|
19241
|
+
STOP_SYSTEMCTL = /* @__PURE__ */ new Set(["stop", "disable", "mask", "kill"]);
|
|
19242
|
+
STOP_LAUNCHCTL = /* @__PURE__ */ new Set(["unload", "bootout", "remove", "stop", "kill", "disable"]);
|
|
19243
|
+
PKILL_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
19244
|
+
"-u",
|
|
19245
|
+
"-U",
|
|
19246
|
+
"-g",
|
|
19247
|
+
"-G",
|
|
19248
|
+
"-P",
|
|
19249
|
+
"-s",
|
|
19250
|
+
"-t",
|
|
19251
|
+
"-F",
|
|
19252
|
+
"--signal",
|
|
19253
|
+
"--euid",
|
|
19254
|
+
"--uid",
|
|
19255
|
+
"--pgroup",
|
|
19256
|
+
"--group",
|
|
19257
|
+
"--parent",
|
|
19258
|
+
"--session",
|
|
19259
|
+
"--terminal",
|
|
19260
|
+
"--pidfile",
|
|
19261
|
+
"--ns",
|
|
19262
|
+
"--nslist"
|
|
19263
|
+
]);
|
|
19264
|
+
NAME_PRESCREEN_RE = /node9|kill|systemctl|launchctl|daemon/i;
|
|
19265
|
+
base2 = (w) => (w ?? "").split(/[\\/]/).pop()?.toLowerCase() ?? "";
|
|
19266
|
+
HOME_PID_FILE_RE = /(?:^|[\s"'(=`])(?:~|\$HOME|\$\{HOME\}|\/home\/[^/\s]+|\/Users\/[^/\s]+|\/root)\/\.node9\/daemon\.pid/;
|
|
18926
19267
|
VERDICT_RANK = {
|
|
18927
19268
|
allow: 0,
|
|
18928
19269
|
review: 1,
|
|
18929
19270
|
block: 2
|
|
18930
19271
|
};
|
|
18931
19272
|
SQL_DML_KEYWORDS = /* @__PURE__ */ new Set(["select", "insert", "update", "delete", "merge", "upsert"]);
|
|
19273
|
+
NOT_OVERRIDABLE_CHECKS = /* @__PURE__ */ new Set([
|
|
19274
|
+
"data.credential-files",
|
|
19275
|
+
"data.credential-files-other"
|
|
19276
|
+
]);
|
|
18932
19277
|
MAX_DESTINATIONS = 200;
|
|
18933
19278
|
MAX_SCAN_CHARS = 1e5;
|
|
18934
19279
|
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;
|
|
@@ -20347,8 +20692,8 @@ function safeApiUrl(raw, onReject) {
|
|
|
20347
20692
|
function sanitizeSsrfAllow(entries, source) {
|
|
20348
20693
|
const kept = [];
|
|
20349
20694
|
for (const entry of entries) {
|
|
20350
|
-
const
|
|
20351
|
-
const m = classifySsrf(
|
|
20695
|
+
const base3 = entry.includes("/") ? entry.slice(0, entry.indexOf("/")).trim() : entry;
|
|
20696
|
+
const m = classifySsrf(base3);
|
|
20352
20697
|
if (m && !m.overridable) {
|
|
20353
20698
|
const what = entry.includes("/") ? "covers only protected addresses" : "is a protected address";
|
|
20354
20699
|
process.emitWarning(
|
|
@@ -21448,12 +21793,12 @@ function getConfig(cwd) {
|
|
|
21448
21793
|
continue;
|
|
21449
21794
|
explicit[id] = v;
|
|
21450
21795
|
}
|
|
21451
|
-
const
|
|
21796
|
+
const base3 = resolveCheckMap({
|
|
21452
21797
|
...catalogSettingsFrom(mergedSettings, mergedPolicy),
|
|
21453
21798
|
checks: explicit
|
|
21454
21799
|
});
|
|
21455
21800
|
for (const [id, v] of Object.entries(v2ChecksByPath.get(projectPath)?.checks ?? {})) {
|
|
21456
|
-
if (CHECK_VERDICT_RANK[v] > CHECK_VERDICT_RANK[
|
|
21801
|
+
if (CHECK_VERDICT_RANK[v] > CHECK_VERDICT_RANK[base3[id] ?? "off"]) {
|
|
21457
21802
|
explicit[id] = v;
|
|
21458
21803
|
checkSources[id] = "project";
|
|
21459
21804
|
}
|
|
@@ -21605,7 +21950,7 @@ init_dist();
|
|
|
21605
21950
|
// src/policy/index.ts
|
|
21606
21951
|
init_cjs_shims();
|
|
21607
21952
|
init_dist();
|
|
21608
|
-
var
|
|
21953
|
+
var import_fs15 = __toESM(require("fs"));
|
|
21609
21954
|
|
|
21610
21955
|
// src/utils/read-capped.ts
|
|
21611
21956
|
init_cjs_shims();
|
|
@@ -21649,10 +21994,42 @@ function readCappedText(file2, maxBytes, openFlags = "r") {
|
|
|
21649
21994
|
|
|
21650
21995
|
// src/policy/index.ts
|
|
21651
21996
|
var import_path14 = __toESM(require("path"));
|
|
21997
|
+
var import_os10 = __toESM(require("os"));
|
|
21652
21998
|
|
|
21653
|
-
// src/
|
|
21999
|
+
// src/utils/read-small-file.ts
|
|
21654
22000
|
init_cjs_shims();
|
|
21655
22001
|
var import_fs7 = __toESM(require("fs"));
|
|
22002
|
+
function readSmallFile(file2, maxBytes) {
|
|
22003
|
+
let fd;
|
|
22004
|
+
try {
|
|
22005
|
+
fd = import_fs7.default.openSync(file2, import_fs7.default.constants.O_RDONLY | (import_fs7.default.constants.O_NONBLOCK ?? 0));
|
|
22006
|
+
} catch {
|
|
22007
|
+
return null;
|
|
22008
|
+
}
|
|
22009
|
+
try {
|
|
22010
|
+
const st = import_fs7.default.fstatSync(fd);
|
|
22011
|
+
if (!st.isFile() || st.size > maxBytes) return null;
|
|
22012
|
+
const buf = Buffer.alloc(Math.min(st.size, maxBytes));
|
|
22013
|
+
let read2 = 0;
|
|
22014
|
+
while (read2 < buf.length) {
|
|
22015
|
+
const n = import_fs7.default.readSync(fd, buf, read2, buf.length - read2, read2);
|
|
22016
|
+
if (n === 0) break;
|
|
22017
|
+
read2 += n;
|
|
22018
|
+
}
|
|
22019
|
+
return buf.toString("utf8", 0, read2);
|
|
22020
|
+
} catch {
|
|
22021
|
+
return null;
|
|
22022
|
+
} finally {
|
|
22023
|
+
import_fs7.default.closeSync(fd);
|
|
22024
|
+
}
|
|
22025
|
+
}
|
|
22026
|
+
|
|
22027
|
+
// src/policy/index.ts
|
|
22028
|
+
init_forecast_context();
|
|
22029
|
+
|
|
22030
|
+
// src/dlp.ts
|
|
22031
|
+
init_cjs_shims();
|
|
22032
|
+
var import_fs8 = __toESM(require("fs"));
|
|
21656
22033
|
var import_path6 = __toESM(require("path"));
|
|
21657
22034
|
init_dist();
|
|
21658
22035
|
init_dist();
|
|
@@ -21661,7 +22038,7 @@ function scanFilePath(filePath, cwd = process.cwd(), options = {}) {
|
|
|
21661
22038
|
let resolved;
|
|
21662
22039
|
try {
|
|
21663
22040
|
const absolute2 = import_path6.default.resolve(cwd, filePath);
|
|
21664
|
-
resolved =
|
|
22041
|
+
resolved = import_fs8.default.realpathSync.native(absolute2);
|
|
21665
22042
|
} catch (err) {
|
|
21666
22043
|
const code = err.code;
|
|
21667
22044
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -21887,7 +22264,7 @@ function combineWithEngine(gates, engine, opts = { panicMode: false }) {
|
|
|
21887
22264
|
|
|
21888
22265
|
// src/policy/file-access.ts
|
|
21889
22266
|
init_cjs_shims();
|
|
21890
|
-
var
|
|
22267
|
+
var import_fs9 = __toESM(require("fs"));
|
|
21891
22268
|
var import_os6 = __toESM(require("os"));
|
|
21892
22269
|
var import_path7 = __toESM(require("path"));
|
|
21893
22270
|
init_dist();
|
|
@@ -21902,13 +22279,13 @@ function physical(p, followFinal, links = 0) {
|
|
|
21902
22279
|
return { path: `${parent.path}/${import_path7.default.basename(p)}`, missing: parent.missing };
|
|
21903
22280
|
}
|
|
21904
22281
|
try {
|
|
21905
|
-
return { path:
|
|
22282
|
+
return { path: import_fs9.default.realpathSync.native(p), missing: false };
|
|
21906
22283
|
} catch (error) {
|
|
21907
22284
|
const code = error.code;
|
|
21908
22285
|
if (!["ENOENT", "ENOTDIR"].includes(code ?? "")) throw error;
|
|
21909
22286
|
try {
|
|
21910
|
-
if (
|
|
21911
|
-
const target =
|
|
22287
|
+
if (import_fs9.default.lstatSync(p).isSymbolicLink()) {
|
|
22288
|
+
const target = import_fs9.default.readlinkSync(p);
|
|
21912
22289
|
return physical(
|
|
21913
22290
|
import_path7.default.isAbsolute(target) ? target : `${import_path7.default.dirname(p)}/${target}`,
|
|
21914
22291
|
true,
|
|
@@ -21948,14 +22325,14 @@ function prepareFileAccesses(tool, args, cwd = process.cwd(), inspection = {}, h
|
|
|
21948
22325
|
const raw = absoluteSpelling(access.path, access.cwd ?? cwd, home);
|
|
21949
22326
|
if (access.directoryTarget) {
|
|
21950
22327
|
try {
|
|
21951
|
-
if (!
|
|
22328
|
+
if (!import_fs9.default.statSync(absoluteSpelling(access.directoryTarget, access.cwd ?? cwd, home)).isDirectory())
|
|
21952
22329
|
continue;
|
|
21953
22330
|
} catch {
|
|
21954
22331
|
}
|
|
21955
22332
|
}
|
|
21956
22333
|
if (access.operation === "create") {
|
|
21957
22334
|
try {
|
|
21958
|
-
|
|
22335
|
+
import_fs9.default.statSync(raw);
|
|
21959
22336
|
continue;
|
|
21960
22337
|
} catch {
|
|
21961
22338
|
}
|
|
@@ -22011,7 +22388,7 @@ init_dist();
|
|
|
22011
22388
|
|
|
22012
22389
|
// src/supply-chain/osv-index.ts
|
|
22013
22390
|
init_cjs_shims();
|
|
22014
|
-
var
|
|
22391
|
+
var import_fs11 = __toESM(require("fs"));
|
|
22015
22392
|
var import_os7 = __toESM(require("os"));
|
|
22016
22393
|
var import_path9 = __toESM(require("path"));
|
|
22017
22394
|
var import_crypto8 = require("crypto");
|
|
@@ -22019,27 +22396,27 @@ init_dist();
|
|
|
22019
22396
|
|
|
22020
22397
|
// src/utils/atomic-write.ts
|
|
22021
22398
|
init_cjs_shims();
|
|
22022
|
-
var
|
|
22399
|
+
var import_fs10 = __toESM(require("fs"));
|
|
22023
22400
|
var import_path8 = __toESM(require("path"));
|
|
22024
22401
|
var import_crypto7 = require("crypto");
|
|
22025
22402
|
function atomicWriteSync(filePath, data, options) {
|
|
22026
22403
|
const dir2 = import_path8.default.dirname(filePath);
|
|
22027
|
-
if (!
|
|
22404
|
+
if (!import_fs10.default.existsSync(dir2)) import_fs10.default.mkdirSync(dir2, { recursive: true });
|
|
22028
22405
|
const tmpPath = `${filePath}.${(0, import_crypto7.randomUUID)()}.tmp`;
|
|
22029
22406
|
try {
|
|
22030
|
-
|
|
22407
|
+
import_fs10.default.writeFileSync(tmpPath, data, options);
|
|
22031
22408
|
} catch (err) {
|
|
22032
22409
|
try {
|
|
22033
|
-
|
|
22410
|
+
import_fs10.default.unlinkSync(tmpPath);
|
|
22034
22411
|
} catch {
|
|
22035
22412
|
}
|
|
22036
22413
|
throw err;
|
|
22037
22414
|
}
|
|
22038
22415
|
try {
|
|
22039
|
-
|
|
22416
|
+
import_fs10.default.renameSync(tmpPath, filePath);
|
|
22040
22417
|
} catch (err) {
|
|
22041
22418
|
try {
|
|
22042
|
-
|
|
22419
|
+
import_fs10.default.unlinkSync(tmpPath);
|
|
22043
22420
|
} catch {
|
|
22044
22421
|
}
|
|
22045
22422
|
throw err;
|
|
@@ -22075,7 +22452,7 @@ function shardPath(eco, shard) {
|
|
|
22075
22452
|
}
|
|
22076
22453
|
function readMeta(eco) {
|
|
22077
22454
|
try {
|
|
22078
|
-
const m = JSON.parse(
|
|
22455
|
+
const m = JSON.parse(import_fs11.default.readFileSync(import_path9.default.join(ecoDir(eco), "meta.json"), "utf8"));
|
|
22079
22456
|
if (typeof m?.syncedAt !== "string" || typeof m?.lastModifiedMs !== "number") return null;
|
|
22080
22457
|
return m;
|
|
22081
22458
|
} catch {
|
|
@@ -22084,7 +22461,7 @@ function readMeta(eco) {
|
|
|
22084
22461
|
}
|
|
22085
22462
|
function readShard(eco, shard) {
|
|
22086
22463
|
try {
|
|
22087
|
-
const s = JSON.parse(
|
|
22464
|
+
const s = JSON.parse(import_fs11.default.readFileSync(shardPath(eco, shard), "utf8"));
|
|
22088
22465
|
return s && typeof s === "object" && !Array.isArray(s) ? s : {};
|
|
22089
22466
|
} catch {
|
|
22090
22467
|
return {};
|
|
@@ -22194,15 +22571,15 @@ async function fetchJson(url, opts) {
|
|
|
22194
22571
|
// src/supply-chain/osv-online.ts
|
|
22195
22572
|
var TIMEOUT_MS = 2500;
|
|
22196
22573
|
async function queryOsvMalicious(queries) {
|
|
22197
|
-
const
|
|
22198
|
-
if (!
|
|
22574
|
+
const base3 = endpoints().osvApi;
|
|
22575
|
+
if (!base3 || queries.length === 0) return null;
|
|
22199
22576
|
const body = JSON.stringify({
|
|
22200
22577
|
queries: queries.map((q) => ({
|
|
22201
22578
|
package: { name: q.name, ecosystem: q.ecosystem },
|
|
22202
22579
|
...q.version ? { version: q.version } : {}
|
|
22203
22580
|
}))
|
|
22204
22581
|
});
|
|
22205
|
-
const res = await fetchJson(`${
|
|
22582
|
+
const res = await fetchJson(`${base3}/v1/querybatch`, {
|
|
22206
22583
|
timeoutMs: TIMEOUT_MS,
|
|
22207
22584
|
maxBytes: 1024 * 1024,
|
|
22208
22585
|
body
|
|
@@ -22263,9 +22640,9 @@ function pypiRepoOf(doc) {
|
|
|
22263
22640
|
return null;
|
|
22264
22641
|
}
|
|
22265
22642
|
async function npmSourceRepo(name, version) {
|
|
22266
|
-
const
|
|
22267
|
-
if (!
|
|
22268
|
-
const url = `${
|
|
22643
|
+
const base3 = endpoints().npmRegistry;
|
|
22644
|
+
if (!base3) return "unknown";
|
|
22645
|
+
const url = `${base3}/-/npm/v1/attestations/${name.replaceAll("/", "%2F")}@${encodeURIComponent(version)}`;
|
|
22269
22646
|
return read(url, npmRepoOf);
|
|
22270
22647
|
}
|
|
22271
22648
|
async function read(url, repoOf) {
|
|
@@ -22278,9 +22655,9 @@ async function read(url, repoOf) {
|
|
|
22278
22655
|
}
|
|
22279
22656
|
}
|
|
22280
22657
|
async function pypiSourceRepo(name, version, filename) {
|
|
22281
|
-
const
|
|
22282
|
-
if (!
|
|
22283
|
-
const url = `${
|
|
22658
|
+
const base3 = endpoints().pypi;
|
|
22659
|
+
if (!base3) return "unknown";
|
|
22660
|
+
const url = `${base3}/integrity/${encodeURIComponent(name)}/${encodeURIComponent(version)}/${encodeURIComponent(filename)}/provenance`;
|
|
22284
22661
|
return read(url, pypiRepoOf);
|
|
22285
22662
|
}
|
|
22286
22663
|
var PYPI_FINAL = /^\d+(?:\.\d+)*$/;
|
|
@@ -22325,9 +22702,9 @@ async function npmVersionDocument(url, selector) {
|
|
|
22325
22702
|
};
|
|
22326
22703
|
}
|
|
22327
22704
|
async function npmInfo(name, version, freshWindowMs, raw) {
|
|
22328
|
-
const
|
|
22329
|
-
if (!
|
|
22330
|
-
const url = `${
|
|
22705
|
+
const base3 = endpoints().npmRegistry;
|
|
22706
|
+
if (!base3) return null;
|
|
22707
|
+
const url = `${base3}/${name.replaceAll("/", "%2F")}`;
|
|
22331
22708
|
const aliasStart = raw?.indexOf("@npm:") ?? -1;
|
|
22332
22709
|
const target = aliasStart > 0 ? raw.slice(aliasStart + 5) : raw?.replace(/^npm:/, "");
|
|
22333
22710
|
const specStart = target?.indexOf("@", 1) ?? -1;
|
|
@@ -22395,9 +22772,9 @@ async function npmInfo(name, version, freshWindowMs, raw) {
|
|
|
22395
22772
|
return info;
|
|
22396
22773
|
}
|
|
22397
22774
|
async function pypiInfo(name, version) {
|
|
22398
|
-
const
|
|
22399
|
-
if (!
|
|
22400
|
-
const url = version ? `${
|
|
22775
|
+
const base3 = endpoints().pypi;
|
|
22776
|
+
if (!base3) return null;
|
|
22777
|
+
const url = version ? `${base3}/pypi/${encodeURIComponent(name)}/${encodeURIComponent(version)}/json` : `${base3}/pypi/${encodeURIComponent(name)}/json`;
|
|
22401
22778
|
const doc = await fetchJson(url, { timeoutMs: TIMEOUT_MS3, maxBytes: MAX_BYTES2 });
|
|
22402
22779
|
if (!doc?.info?.version) return null;
|
|
22403
22780
|
const times = (doc.urls ?? []).map((u) => u.upload_time_iso_8601 ? Date.parse(u.upload_time_iso_8601) : NaN).filter((t) => Number.isFinite(t));
|
|
@@ -22421,9 +22798,9 @@ function pypiHistoryOf(releases, version) {
|
|
|
22421
22798
|
};
|
|
22422
22799
|
}
|
|
22423
22800
|
async function pypiHistory(name, version) {
|
|
22424
|
-
const
|
|
22425
|
-
if (!
|
|
22426
|
-
const doc = await fetchJson(`${
|
|
22801
|
+
const base3 = endpoints().pypi;
|
|
22802
|
+
if (!base3) return null;
|
|
22803
|
+
const doc = await fetchJson(`${base3}/pypi/${encodeURIComponent(name)}/json`, {
|
|
22427
22804
|
timeoutMs: TIMEOUT_MS3,
|
|
22428
22805
|
maxBytes: MAX_BYTES2
|
|
22429
22806
|
});
|
|
@@ -22438,7 +22815,7 @@ async function registryInfo(eco, name, version, freshWindowMs, raw) {
|
|
|
22438
22815
|
|
|
22439
22816
|
// src/supply-chain/local-resolve.ts
|
|
22440
22817
|
init_cjs_shims();
|
|
22441
|
-
var
|
|
22818
|
+
var import_fs12 = __toESM(require("fs"));
|
|
22442
22819
|
var import_path10 = __toESM(require("path"));
|
|
22443
22820
|
var MAX_LEVELS = 32;
|
|
22444
22821
|
var LOCAL_FIRST_MANAGERS = /* @__PURE__ */ new Set(["npx", "bunx", "npm exec"]);
|
|
@@ -22450,7 +22827,7 @@ function resolveInstalled(name, cwd) {
|
|
|
22450
22827
|
const pkgDir = import_path10.default.join(dir2, "node_modules", ...name.split("/"));
|
|
22451
22828
|
const manifest = import_path10.default.join(pkgDir, "package.json");
|
|
22452
22829
|
try {
|
|
22453
|
-
const raw =
|
|
22830
|
+
const raw = import_fs12.default.readFileSync(manifest, "utf8");
|
|
22454
22831
|
const parsed = JSON.parse(raw);
|
|
22455
22832
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
22456
22833
|
return { version: parsed.version, dir: pkgDir };
|
|
@@ -22727,7 +23104,7 @@ async function runPackageCheck(toolName, args, cfg, cwd, opts = {}) {
|
|
|
22727
23104
|
init_cjs_shims();
|
|
22728
23105
|
var import_os8 = __toESM(require("os"));
|
|
22729
23106
|
var import_path12 = __toESM(require("path"));
|
|
22730
|
-
var
|
|
23107
|
+
var import_fs13 = __toESM(require("fs"));
|
|
22731
23108
|
init_dist();
|
|
22732
23109
|
var MAX_CONFIG_BYTES = 256 * 1024;
|
|
22733
23110
|
var MAX_PARENT_DIRS = 12;
|
|
@@ -22853,7 +23230,7 @@ function configuredRegistryHosts(cwd, env = process.env, home = import_os8.defau
|
|
|
22853
23230
|
const r = readCappedText(
|
|
22854
23231
|
file2,
|
|
22855
23232
|
MAX_CONFIG_BYTES,
|
|
22856
|
-
|
|
23233
|
+
import_fs13.default.constants.O_RDONLY | (import_fs13.default.constants.O_NONBLOCK ?? 0)
|
|
22857
23234
|
);
|
|
22858
23235
|
if (r) hostsInText(r.text, hosts);
|
|
22859
23236
|
}
|
|
@@ -22863,7 +23240,7 @@ function configuredRegistryHosts(cwd, env = process.env, home = import_os8.defau
|
|
|
22863
23240
|
|
|
22864
23241
|
// src/utils/provenance.ts
|
|
22865
23242
|
init_cjs_shims();
|
|
22866
|
-
var
|
|
23243
|
+
var import_fs14 = __toESM(require("fs"));
|
|
22867
23244
|
var import_path13 = __toESM(require("path"));
|
|
22868
23245
|
var import_os9 = __toESM(require("os"));
|
|
22869
23246
|
var SYSTEM_PREFIXES = ["/usr/bin", "/usr/sbin", "/bin", "/sbin"];
|
|
@@ -22883,7 +23260,7 @@ function findInPath(cmd) {
|
|
|
22883
23260
|
if (!dir2) continue;
|
|
22884
23261
|
const full = import_path13.default.join(dir2, cmd);
|
|
22885
23262
|
try {
|
|
22886
|
-
|
|
23263
|
+
import_fs14.default.accessSync(full, import_fs14.default.constants.X_OK);
|
|
22887
23264
|
return full;
|
|
22888
23265
|
} catch {
|
|
22889
23266
|
}
|
|
@@ -22928,7 +23305,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
22928
23305
|
reason: "binary not found in PATH"
|
|
22929
23306
|
};
|
|
22930
23307
|
}
|
|
22931
|
-
resolved =
|
|
23308
|
+
resolved = import_fs14.default.realpathSync(found);
|
|
22932
23309
|
} catch {
|
|
22933
23310
|
return {
|
|
22934
23311
|
resolvedPath: cmd,
|
|
@@ -22937,7 +23314,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
22937
23314
|
};
|
|
22938
23315
|
}
|
|
22939
23316
|
try {
|
|
22940
|
-
const stat =
|
|
23317
|
+
const stat = import_fs14.default.statSync(resolved);
|
|
22941
23318
|
if (stat.mode & 2) {
|
|
22942
23319
|
return {
|
|
22943
23320
|
resolvedPath: resolved,
|
|
@@ -22986,14 +23363,26 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
|
|
|
22986
23363
|
isTrustedHost: config.policy.trustedHostsManaged ? (host2) => matchesTrustedHost(host2, config.policy.trustedHosts) : isTrustedHost,
|
|
22987
23364
|
readAgentSettings,
|
|
22988
23365
|
isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2),
|
|
22989
|
-
isGitWorkTreeTop
|
|
23366
|
+
isGitWorkTreeTop,
|
|
23367
|
+
daemonPid: daemonPidFromFile
|
|
22990
23368
|
}
|
|
22991
23369
|
);
|
|
22992
23370
|
}
|
|
23371
|
+
function daemonPidFromFile() {
|
|
23372
|
+
if (forecastRun()) return null;
|
|
23373
|
+
const text = readSmallFile(import_path14.default.join(import_os10.default.homedir(), ".node9", "daemon.pid"), 4096);
|
|
23374
|
+
if (text === null) return null;
|
|
23375
|
+
try {
|
|
23376
|
+
const pid = JSON.parse(text).pid;
|
|
23377
|
+
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= 4194304 ? pid : null;
|
|
23378
|
+
} catch {
|
|
23379
|
+
return null;
|
|
23380
|
+
}
|
|
23381
|
+
}
|
|
22993
23382
|
function isGitWorkTreeTop(dir2, cwd) {
|
|
22994
23383
|
if (!import_path14.default.isAbsolute(cwd)) return true;
|
|
22995
23384
|
try {
|
|
22996
|
-
return
|
|
23385
|
+
return import_fs15.default.existsSync(import_path14.default.join(import_path14.default.resolve(cwd, dir2), ".git"));
|
|
22997
23386
|
} catch {
|
|
22998
23387
|
return true;
|
|
22999
23388
|
}
|
|
@@ -23003,7 +23392,7 @@ function readAgentSettings(absPath) {
|
|
|
23003
23392
|
const r = readCappedText(
|
|
23004
23393
|
absPath,
|
|
23005
23394
|
MAX_AGENT_SETTINGS_BYTES,
|
|
23006
|
-
|
|
23395
|
+
import_fs15.default.constants.O_RDONLY | (import_fs15.default.constants.O_NONBLOCK ?? 0)
|
|
23007
23396
|
);
|
|
23008
23397
|
return r && !r.truncated ? r.text : null;
|
|
23009
23398
|
}
|
|
@@ -23013,12 +23402,12 @@ function isIgnoredTool2(toolName) {
|
|
|
23013
23402
|
|
|
23014
23403
|
// src/auth/state.ts
|
|
23015
23404
|
init_cjs_shims();
|
|
23016
|
-
var
|
|
23405
|
+
var import_fs16 = __toESM(require("fs"));
|
|
23017
23406
|
var import_path15 = __toESM(require("path"));
|
|
23018
|
-
var
|
|
23407
|
+
var import_os11 = __toESM(require("os"));
|
|
23019
23408
|
init_forecast_context();
|
|
23020
|
-
var PAUSED_FILE = import_path15.default.join(
|
|
23021
|
-
var TRUST_FILE = import_path15.default.join(
|
|
23409
|
+
var PAUSED_FILE = import_path15.default.join(import_os11.default.homedir(), ".node9", "PAUSED");
|
|
23410
|
+
var TRUST_FILE = import_path15.default.join(import_os11.default.homedir(), ".node9", "trust.json");
|
|
23022
23411
|
function extractCommandPattern(toolName, args) {
|
|
23023
23412
|
const lower2 = toolName.toLowerCase();
|
|
23024
23413
|
if (lower2 !== "bash" && lower2 !== "execute_bash" && lower2 !== "shell") return void 0;
|
|
@@ -23031,11 +23420,11 @@ function extractCommandPattern(toolName, args) {
|
|
|
23031
23420
|
function checkPause() {
|
|
23032
23421
|
if (forecastRun()) return { paused: false };
|
|
23033
23422
|
try {
|
|
23034
|
-
if (!
|
|
23035
|
-
const state = JSON.parse(
|
|
23423
|
+
if (!import_fs16.default.existsSync(PAUSED_FILE)) return { paused: false };
|
|
23424
|
+
const state = JSON.parse(import_fs16.default.readFileSync(PAUSED_FILE, "utf-8"));
|
|
23036
23425
|
if (state.expiry > 0 && Date.now() >= state.expiry) {
|
|
23037
23426
|
try {
|
|
23038
|
-
|
|
23427
|
+
import_fs16.default.unlinkSync(PAUSED_FILE);
|
|
23039
23428
|
} catch {
|
|
23040
23429
|
}
|
|
23041
23430
|
return { paused: false };
|
|
@@ -23048,8 +23437,8 @@ function checkPause() {
|
|
|
23048
23437
|
function getActiveTrustSession(toolName, args) {
|
|
23049
23438
|
if (forecastRun()) return false;
|
|
23050
23439
|
try {
|
|
23051
|
-
if (!
|
|
23052
|
-
const trust = JSON.parse(
|
|
23440
|
+
if (!import_fs16.default.existsSync(TRUST_FILE)) return false;
|
|
23441
|
+
const trust = JSON.parse(import_fs16.default.readFileSync(TRUST_FILE, "utf-8"));
|
|
23053
23442
|
const now = Date.now();
|
|
23054
23443
|
const active = trust.entries.filter((e) => e.expiry > now);
|
|
23055
23444
|
if (active.length !== trust.entries.length) {
|
|
@@ -23072,8 +23461,8 @@ function writeTrustSession(toolName, durationMs, args) {
|
|
|
23072
23461
|
try {
|
|
23073
23462
|
let trust = { entries: [] };
|
|
23074
23463
|
try {
|
|
23075
|
-
if (
|
|
23076
|
-
trust = JSON.parse(
|
|
23464
|
+
if (import_fs16.default.existsSync(TRUST_FILE)) {
|
|
23465
|
+
trust = JSON.parse(import_fs16.default.readFileSync(TRUST_FILE, "utf-8"));
|
|
23077
23466
|
}
|
|
23078
23467
|
} catch {
|
|
23079
23468
|
}
|
|
@@ -23095,9 +23484,9 @@ function writeTrustSession(toolName, durationMs, args) {
|
|
|
23095
23484
|
}
|
|
23096
23485
|
function getPersistentDecision(toolName) {
|
|
23097
23486
|
try {
|
|
23098
|
-
const file2 = import_path15.default.join(
|
|
23099
|
-
if (!
|
|
23100
|
-
const decisions = JSON.parse(
|
|
23487
|
+
const file2 = import_path15.default.join(import_os11.default.homedir(), ".node9", "decisions.json");
|
|
23488
|
+
if (!import_fs16.default.existsSync(file2)) return null;
|
|
23489
|
+
const decisions = JSON.parse(import_fs16.default.readFileSync(file2, "utf-8"));
|
|
23101
23490
|
const d = decisions[toolName];
|
|
23102
23491
|
if (d === "allow" || d === "deny") return d;
|
|
23103
23492
|
} catch {
|
|
@@ -23107,16 +23496,16 @@ function getPersistentDecision(toolName) {
|
|
|
23107
23496
|
|
|
23108
23497
|
// src/auth/daemon.ts
|
|
23109
23498
|
init_cjs_shims();
|
|
23110
|
-
var
|
|
23499
|
+
var import_fs18 = __toESM(require("fs"));
|
|
23111
23500
|
var import_http = __toESM(require("http"));
|
|
23112
23501
|
var import_net4 = __toESM(require("net"));
|
|
23113
23502
|
var import_path17 = __toESM(require("path"));
|
|
23114
|
-
var
|
|
23503
|
+
var import_os12 = __toESM(require("os"));
|
|
23115
23504
|
init_forecast_context();
|
|
23116
23505
|
|
|
23117
23506
|
// src/utils/activity-socket.ts
|
|
23118
23507
|
init_cjs_shims();
|
|
23119
|
-
var
|
|
23508
|
+
var import_fs17 = __toESM(require("fs"));
|
|
23120
23509
|
var import_path16 = __toESM(require("path"));
|
|
23121
23510
|
|
|
23122
23511
|
// src/utils/own-dir.ts
|
|
@@ -23126,7 +23515,7 @@ init_cjs_shims();
|
|
|
23126
23515
|
var currentUid = () => typeof process.getuid === "function" ? process.getuid() : void 0;
|
|
23127
23516
|
function isPrivateDir(dir2, uid = currentUid()) {
|
|
23128
23517
|
try {
|
|
23129
|
-
const st =
|
|
23518
|
+
const st = import_fs17.default.lstatSync(dir2);
|
|
23130
23519
|
if (st.isSymbolicLink() || !st.isDirectory()) return false;
|
|
23131
23520
|
if (uid !== void 0 && st.uid !== uid) return false;
|
|
23132
23521
|
return (st.mode & 18) === 0;
|
|
@@ -23138,7 +23527,7 @@ var WINDOWS_PIPE = /^\\\\\.\\pipe\\node9-activity-[0-9a-f]{32}$/;
|
|
|
23138
23527
|
function isTrustedActivitySocket(socketPath, uid = currentUid()) {
|
|
23139
23528
|
if (process.platform === "win32") return WINDOWS_PIPE.test(socketPath);
|
|
23140
23529
|
try {
|
|
23141
|
-
const st =
|
|
23530
|
+
const st = import_fs17.default.lstatSync(socketPath);
|
|
23142
23531
|
if (!st.isSocket()) return false;
|
|
23143
23532
|
if (uid !== void 0 && st.uid !== uid) return false;
|
|
23144
23533
|
} catch {
|
|
@@ -23296,9 +23685,9 @@ function recordFromLegacyWait(body, now = Date.now()) {
|
|
|
23296
23685
|
}
|
|
23297
23686
|
|
|
23298
23687
|
// src/auth/daemon.ts
|
|
23299
|
-
function daemonActivitySocket(home =
|
|
23688
|
+
function daemonActivitySocket(home = import_os12.default.homedir()) {
|
|
23300
23689
|
try {
|
|
23301
|
-
const raw =
|
|
23690
|
+
const raw = import_fs18.default.readFileSync(import_path17.default.join(home, ".node9", "daemon.pid"), "utf-8");
|
|
23302
23691
|
const p = JSON.parse(raw).activitySocket;
|
|
23303
23692
|
return typeof p === "string" && isTrustedActivitySocket(p) ? p : null;
|
|
23304
23693
|
} catch {
|
|
@@ -23362,9 +23751,9 @@ var DAEMON_HOST = "127.0.0.1";
|
|
|
23362
23751
|
function getInternalToken() {
|
|
23363
23752
|
if (forecastRun()) return null;
|
|
23364
23753
|
try {
|
|
23365
|
-
const pidFile = import_path17.default.join(
|
|
23366
|
-
if (!
|
|
23367
|
-
const data = JSON.parse(
|
|
23754
|
+
const pidFile = import_path17.default.join(import_os12.default.homedir(), ".node9", "daemon.pid");
|
|
23755
|
+
if (!import_fs18.default.existsSync(pidFile)) return null;
|
|
23756
|
+
const data = JSON.parse(import_fs18.default.readFileSync(pidFile, "utf-8"));
|
|
23368
23757
|
process.kill(data.pid, 0);
|
|
23369
23758
|
return data.internalToken ?? null;
|
|
23370
23759
|
} catch {
|
|
@@ -23373,12 +23762,12 @@ function getInternalToken() {
|
|
|
23373
23762
|
}
|
|
23374
23763
|
function isDaemonRunning() {
|
|
23375
23764
|
if (forecastRun()) return false;
|
|
23376
|
-
const pidFile = import_path17.default.join(
|
|
23377
|
-
if (
|
|
23765
|
+
const pidFile = import_path17.default.join(import_os12.default.homedir(), ".node9", "daemon.pid");
|
|
23766
|
+
if (import_fs18.default.existsSync(pidFile)) {
|
|
23378
23767
|
let pid;
|
|
23379
23768
|
let port;
|
|
23380
23769
|
try {
|
|
23381
|
-
const data = JSON.parse(
|
|
23770
|
+
const data = JSON.parse(import_fs18.default.readFileSync(pidFile, "utf-8"));
|
|
23382
23771
|
pid = data.pid;
|
|
23383
23772
|
port = data.port;
|
|
23384
23773
|
} catch {
|
|
@@ -23396,7 +23785,7 @@ function isDaemonRunning() {
|
|
|
23396
23785
|
} catch (err) {
|
|
23397
23786
|
if (err instanceof Error && "code" in err && err.code === "ESRCH") {
|
|
23398
23787
|
try {
|
|
23399
|
-
|
|
23788
|
+
import_fs18.default.unlinkSync(pidFile);
|
|
23400
23789
|
} catch {
|
|
23401
23790
|
}
|
|
23402
23791
|
}
|
|
@@ -23420,11 +23809,11 @@ async function daemonHasInteractiveApprover(timeoutMs = 400) {
|
|
|
23420
23809
|
}
|
|
23421
23810
|
}
|
|
23422
23811
|
async function registerDaemonEntry(toolName, args, meta, riskMetadata, activityId, cwd, recoveryCommand, skipBackgroundAuth, viewOnly, localSmartRuleMatched, socketActivitySent, sessionId, card) {
|
|
23423
|
-
const
|
|
23812
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23424
23813
|
const ctrl = new AbortController();
|
|
23425
23814
|
const timer = setTimeout(() => ctrl.abort(), 5e3);
|
|
23426
23815
|
try {
|
|
23427
|
-
const res = await fetch(`${
|
|
23816
|
+
const res = await fetch(`${base3}/check`, {
|
|
23428
23817
|
method: "POST",
|
|
23429
23818
|
headers: { "Content-Type": "application/json" },
|
|
23430
23819
|
body: JSON.stringify({
|
|
@@ -23534,8 +23923,8 @@ function daemonGet(urlPath, signal, token = getInternalToken()) {
|
|
|
23534
23923
|
});
|
|
23535
23924
|
}
|
|
23536
23925
|
async function notifyDaemonViewer(toolName, args, meta, riskMetadata, activityId, socketActivitySent, extra) {
|
|
23537
|
-
const
|
|
23538
|
-
const res = await fetch(`${
|
|
23926
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23927
|
+
const res = await fetch(`${base3}/check`, {
|
|
23539
23928
|
method: "POST",
|
|
23540
23929
|
headers: { "Content-Type": "application/json" },
|
|
23541
23930
|
body: JSON.stringify({
|
|
@@ -23567,9 +23956,9 @@ async function notifyTaint(filePath, source, fromEid) {
|
|
|
23567
23956
|
return;
|
|
23568
23957
|
}
|
|
23569
23958
|
if (!isDaemonRunning()) return;
|
|
23570
|
-
const
|
|
23959
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23571
23960
|
try {
|
|
23572
|
-
await fetch(`${
|
|
23961
|
+
await fetch(`${base3}/taint`, {
|
|
23573
23962
|
method: "POST",
|
|
23574
23963
|
headers: { "Content-Type": "application/json" },
|
|
23575
23964
|
// Phase D2 — fromEid is the audit eid that created this taint (edge source).
|
|
@@ -23587,9 +23976,9 @@ async function checkTaint(paths) {
|
|
|
23587
23976
|
return record ? { tainted: true, record } : { tainted: false };
|
|
23588
23977
|
}
|
|
23589
23978
|
if (!isDaemonRunning()) return { tainted: false, daemonUnavailable: true };
|
|
23590
|
-
const
|
|
23979
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23591
23980
|
try {
|
|
23592
|
-
const res = await fetch(`${
|
|
23981
|
+
const res = await fetch(`${base3}/taint/check`, {
|
|
23593
23982
|
method: "POST",
|
|
23594
23983
|
headers: { "Content-Type": "application/json" },
|
|
23595
23984
|
body: JSON.stringify({ paths }),
|
|
@@ -23617,9 +24006,9 @@ async function notifyWritten(paths) {
|
|
|
23617
24006
|
return;
|
|
23618
24007
|
}
|
|
23619
24008
|
if (paths.length === 0 || !isDaemonRunning()) return;
|
|
23620
|
-
const
|
|
24009
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23621
24010
|
try {
|
|
23622
|
-
await fetch(`${
|
|
24011
|
+
await fetch(`${base3}/written`, {
|
|
23623
24012
|
method: "POST",
|
|
23624
24013
|
headers: exposureHeaders(),
|
|
23625
24014
|
body: JSON.stringify({ paths: paths.slice(0, 64) }),
|
|
@@ -23633,9 +24022,9 @@ async function checkWritten(paths) {
|
|
|
23633
24022
|
const forecast = forecastRun();
|
|
23634
24023
|
if (forecast) return { written: forecast.session.written(paths) };
|
|
23635
24024
|
if (!isDaemonRunning()) return { written: [], daemonUnavailable: true };
|
|
23636
|
-
const
|
|
24025
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23637
24026
|
try {
|
|
23638
|
-
const res = await fetch(`${
|
|
24027
|
+
const res = await fetch(`${base3}/written/check`, {
|
|
23639
24028
|
method: "POST",
|
|
23640
24029
|
headers: exposureHeaders(),
|
|
23641
24030
|
body: JSON.stringify({ paths: paths.slice(0, 64) }),
|
|
@@ -23657,9 +24046,9 @@ async function checkSessionTaint(sessionId) {
|
|
|
23657
24046
|
return record ? { tainted: true, record, exposed } : { tainted: false, exposed };
|
|
23658
24047
|
}
|
|
23659
24048
|
if (!sessionId || !isDaemonRunning()) return { tainted: false };
|
|
23660
|
-
const
|
|
24049
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
23661
24050
|
try {
|
|
23662
|
-
const res = await fetch(`${
|
|
24051
|
+
const res = await fetch(`${base3}/session-taint/check`, {
|
|
23663
24052
|
method: "POST",
|
|
23664
24053
|
headers: exposureHeaders(),
|
|
23665
24054
|
body: JSON.stringify({ sessionId }),
|
|
@@ -23677,8 +24066,8 @@ function exposureHeaders() {
|
|
|
23677
24066
|
};
|
|
23678
24067
|
}
|
|
23679
24068
|
async function exposurePost(route, body, timeoutMs) {
|
|
23680
|
-
const
|
|
23681
|
-
const res = await fetch(`${
|
|
24069
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
24070
|
+
const res = await fetch(`${base3}${route}`, {
|
|
23682
24071
|
method: "POST",
|
|
23683
24072
|
headers: exposureHeaders(),
|
|
23684
24073
|
body: JSON.stringify(body),
|
|
@@ -23693,7 +24082,8 @@ async function checkSessionExposure(sessionId) {
|
|
|
23693
24082
|
const record = forecast.session.checkExposure(forecast.now);
|
|
23694
24083
|
return record ? { exposed: true, record } : { exposed: false };
|
|
23695
24084
|
}
|
|
23696
|
-
if (!sessionId
|
|
24085
|
+
if (!sessionId) return { exposed: false };
|
|
24086
|
+
if (!isDaemonRunning()) return { exposed: false, daemonUnavailable: true };
|
|
23697
24087
|
try {
|
|
23698
24088
|
return await exposurePost(
|
|
23699
24089
|
"/session-exposure/check",
|
|
@@ -23717,8 +24107,8 @@ async function approveSessionExposure(sessionId, keys) {
|
|
|
23717
24107
|
}
|
|
23718
24108
|
}
|
|
23719
24109
|
async function resolveViaDaemon(id, decision, internalToken, source, record) {
|
|
23720
|
-
const
|
|
23721
|
-
const res = await fetch(`${
|
|
24110
|
+
const base3 = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
24111
|
+
const res = await fetch(`${base3}/resolve/${id}`, {
|
|
23722
24112
|
method: "POST",
|
|
23723
24113
|
headers: { "Content-Type": "application/json", "X-Node9-Internal": internalToken },
|
|
23724
24114
|
body: JSON.stringify({ decision, ...source && { source }, ...record && { record } }),
|
|
@@ -23736,8 +24126,8 @@ var import_crypto10 = require("crypto");
|
|
|
23736
24126
|
|
|
23737
24127
|
// src/apps/state.ts
|
|
23738
24128
|
init_cjs_shims();
|
|
23739
|
-
var
|
|
23740
|
-
var
|
|
24129
|
+
var import_fs20 = __toESM(require("fs"));
|
|
24130
|
+
var import_os14 = __toESM(require("os"));
|
|
23741
24131
|
var import_path19 = __toESM(require("path"));
|
|
23742
24132
|
|
|
23743
24133
|
// src/apps/catalog.ts
|
|
@@ -23872,22 +24262,22 @@ init_audit();
|
|
|
23872
24262
|
|
|
23873
24263
|
// src/daemon/mcp-tools.ts
|
|
23874
24264
|
init_cjs_shims();
|
|
23875
|
-
var
|
|
24265
|
+
var import_fs19 = __toESM(require("fs"));
|
|
23876
24266
|
var import_path18 = __toESM(require("path"));
|
|
23877
|
-
var
|
|
24267
|
+
var import_os13 = __toESM(require("os"));
|
|
23878
24268
|
|
|
23879
24269
|
// src/mcp-cmd.ts
|
|
23880
24270
|
init_cjs_shims();
|
|
23881
24271
|
|
|
23882
24272
|
// src/daemon/mcp-tools.ts
|
|
23883
24273
|
function getMcpToolsFile() {
|
|
23884
|
-
return import_path18.default.join(
|
|
24274
|
+
return import_path18.default.join(import_os13.default.homedir(), ".node9", "mcp-tools.json");
|
|
23885
24275
|
}
|
|
23886
24276
|
function readMcpToolsConfig() {
|
|
23887
24277
|
try {
|
|
23888
24278
|
const file2 = getMcpToolsFile();
|
|
23889
|
-
if (!
|
|
23890
|
-
const raw =
|
|
24279
|
+
if (!import_fs19.default.existsSync(file2)) return {};
|
|
24280
|
+
const raw = import_fs19.default.readFileSync(file2, "utf-8");
|
|
23891
24281
|
return JSON.parse(raw);
|
|
23892
24282
|
} catch {
|
|
23893
24283
|
return {};
|
|
@@ -23895,7 +24285,7 @@ function readMcpToolsConfig() {
|
|
|
23895
24285
|
}
|
|
23896
24286
|
|
|
23897
24287
|
// src/apps/state.ts
|
|
23898
|
-
function appsFilePath(home =
|
|
24288
|
+
function appsFilePath(home = import_os14.default.homedir()) {
|
|
23899
24289
|
return import_path19.default.join(home, ".node9", "apps.json");
|
|
23900
24290
|
}
|
|
23901
24291
|
var SIGNAL_KINDS = /* @__PURE__ */ new Set(["mcp-server", "command", "package", "env-name"]);
|
|
@@ -23944,7 +24334,7 @@ function readAppsFile(home) {
|
|
|
23944
24334
|
function readAppsFileStrict(home) {
|
|
23945
24335
|
let text;
|
|
23946
24336
|
try {
|
|
23947
|
-
text =
|
|
24337
|
+
text = import_fs20.default.readFileSync(appsFilePath(home), "utf8");
|
|
23948
24338
|
} catch (e) {
|
|
23949
24339
|
return e.code === "ENOENT" ? emptyFile() : null;
|
|
23950
24340
|
}
|
|
@@ -23959,7 +24349,7 @@ var NO_LINKS = /* @__PURE__ */ Object.create(null);
|
|
|
23959
24349
|
function localLinks() {
|
|
23960
24350
|
const file2 = appsFilePath();
|
|
23961
24351
|
try {
|
|
23962
|
-
const mtimeMs =
|
|
24352
|
+
const mtimeMs = import_fs20.default.statSync(file2).mtimeMs;
|
|
23963
24353
|
if (!linkCache || linkCache.file !== file2 || linkCache.mtimeMs !== mtimeMs) {
|
|
23964
24354
|
linkCache = { mtimeMs, file: file2, links: readAppsFile().links };
|
|
23965
24355
|
}
|
|
@@ -23999,7 +24389,7 @@ function resolveLinkedServer(label2, opts = {}) {
|
|
|
23999
24389
|
}
|
|
24000
24390
|
|
|
24001
24391
|
// src/auth/orchestrator.ts
|
|
24002
|
-
var
|
|
24392
|
+
var import_os22 = __toESM(require("os"));
|
|
24003
24393
|
var import_path31 = __toESM(require("path"));
|
|
24004
24394
|
|
|
24005
24395
|
// src/ui/native.ts
|
|
@@ -24350,12 +24740,12 @@ end run`;
|
|
|
24350
24740
|
|
|
24351
24741
|
// src/canary/registry.ts
|
|
24352
24742
|
init_cjs_shims();
|
|
24353
|
-
var
|
|
24354
|
-
var
|
|
24743
|
+
var import_fs21 = __toESM(require("fs"));
|
|
24744
|
+
var import_os15 = __toESM(require("os"));
|
|
24355
24745
|
var import_path22 = __toESM(require("path"));
|
|
24356
24746
|
init_dist();
|
|
24357
24747
|
function canaryStorePath() {
|
|
24358
|
-
return import_path22.default.join(
|
|
24748
|
+
return import_path22.default.join(import_os15.default.homedir(), ".node9", "canaries.json");
|
|
24359
24749
|
}
|
|
24360
24750
|
function isRecord(x) {
|
|
24361
24751
|
if (!x || typeof x !== "object") return false;
|
|
@@ -24366,7 +24756,7 @@ function loadCanaries(opts) {
|
|
|
24366
24756
|
const p = canaryStorePath();
|
|
24367
24757
|
let raw;
|
|
24368
24758
|
try {
|
|
24369
|
-
raw =
|
|
24759
|
+
raw = import_fs21.default.readFileSync(p, "utf-8");
|
|
24370
24760
|
} catch (e) {
|
|
24371
24761
|
if (e.code === "ENOENT") return [];
|
|
24372
24762
|
throw e;
|
|
@@ -24393,8 +24783,8 @@ init_dist();
|
|
|
24393
24783
|
|
|
24394
24784
|
// src/auth/session-script.ts
|
|
24395
24785
|
init_cjs_shims();
|
|
24396
|
-
var
|
|
24397
|
-
var
|
|
24786
|
+
var import_fs22 = __toESM(require("fs"));
|
|
24787
|
+
var import_os16 = __toESM(require("os"));
|
|
24398
24788
|
var import_path23 = __toESM(require("path"));
|
|
24399
24789
|
init_dist();
|
|
24400
24790
|
var MAX_SCRIPT_BYTES = 64 * 1024;
|
|
@@ -24402,13 +24792,13 @@ var MAX_RECORDED_WRITES = 32;
|
|
|
24402
24792
|
function readScriptFile(resolved) {
|
|
24403
24793
|
let fd;
|
|
24404
24794
|
try {
|
|
24405
|
-
fd =
|
|
24406
|
-
const st =
|
|
24795
|
+
fd = import_fs22.default.openSync(resolved, import_fs22.default.constants.O_RDONLY | (import_fs22.default.constants.O_NONBLOCK ?? 0));
|
|
24796
|
+
const st = import_fs22.default.fstatSync(fd);
|
|
24407
24797
|
if (!st.isFile() || st.size > MAX_SCRIPT_BYTES) return null;
|
|
24408
24798
|
const buf = Buffer.alloc(MAX_SCRIPT_BYTES + 1);
|
|
24409
24799
|
let n = 0;
|
|
24410
24800
|
while (n < buf.length) {
|
|
24411
|
-
const got =
|
|
24801
|
+
const got = import_fs22.default.readSync(fd, buf, n, buf.length - n, n);
|
|
24412
24802
|
if (got === 0) break;
|
|
24413
24803
|
n += got;
|
|
24414
24804
|
}
|
|
@@ -24419,7 +24809,7 @@ function readScriptFile(resolved) {
|
|
|
24419
24809
|
} finally {
|
|
24420
24810
|
if (fd !== void 0) {
|
|
24421
24811
|
try {
|
|
24422
|
-
|
|
24812
|
+
import_fs22.default.closeSync(fd);
|
|
24423
24813
|
} catch {
|
|
24424
24814
|
}
|
|
24425
24815
|
}
|
|
@@ -24429,16 +24819,16 @@ function absolute(p, cwd, home) {
|
|
|
24429
24819
|
const spelled = p === "~" || p.startsWith("~/") ? home + p.slice(1) : p;
|
|
24430
24820
|
return import_path23.default.resolve(cwd, spelled);
|
|
24431
24821
|
}
|
|
24432
|
-
async function resolveSessionScript(toolName, args, cwd, layers, deps, home =
|
|
24822
|
+
async function resolveSessionScript(toolName, args, cwd, layers, deps, home = import_os16.default.homedir()) {
|
|
24433
24823
|
try {
|
|
24434
24824
|
const d = deps ?? { checkWritten, readScript: readScriptFile };
|
|
24435
24825
|
const shell = resolveShellInput(toolName, args, layers);
|
|
24436
24826
|
if (shell.kind !== "shell") return null;
|
|
24437
24827
|
const operands2 = shellScriptOperands(shell.command);
|
|
24438
24828
|
if (operands2.length === 0) return null;
|
|
24439
|
-
const
|
|
24829
|
+
const base3 = cwd ?? process.cwd();
|
|
24440
24830
|
const byResolved = /* @__PURE__ */ new Map();
|
|
24441
|
-
for (const op of operands2) byResolved.set(absolute(op,
|
|
24831
|
+
for (const op of operands2) byResolved.set(absolute(op, base3, home), op);
|
|
24442
24832
|
const { written } = await d.checkWritten([...byResolved.keys()]);
|
|
24443
24833
|
for (const resolved of written) {
|
|
24444
24834
|
const spelled = byResolved.get(resolved);
|
|
@@ -24450,7 +24840,7 @@ async function resolveSessionScript(toolName, args, cwd, layers, deps, home = im
|
|
|
24450
24840
|
path: spelled,
|
|
24451
24841
|
resolved,
|
|
24452
24842
|
args: scriptArgs,
|
|
24453
|
-
fileAccess: prepareFileAccesses("Bash", scriptArgs,
|
|
24843
|
+
fileAccess: prepareFileAccesses("Bash", scriptArgs, base3, layers, home)
|
|
24454
24844
|
};
|
|
24455
24845
|
}
|
|
24456
24846
|
return null;
|
|
@@ -24458,17 +24848,17 @@ async function resolveSessionScript(toolName, args, cwd, layers, deps, home = im
|
|
|
24458
24848
|
return null;
|
|
24459
24849
|
}
|
|
24460
24850
|
}
|
|
24461
|
-
function sessionWriteTargets(toolName, args, fileAccess, cwd, home =
|
|
24462
|
-
const
|
|
24851
|
+
function sessionWriteTargets(toolName, args, fileAccess, cwd, home = import_os16.default.homedir()) {
|
|
24852
|
+
const base3 = cwd ?? process.cwd();
|
|
24463
24853
|
const out = /* @__PURE__ */ new Set();
|
|
24464
24854
|
const argsObj = args && typeof args === "object" ? args : {};
|
|
24465
24855
|
const named = argsObj.file_path ?? argsObj.path ?? argsObj.filename;
|
|
24466
24856
|
if (typeof named === "string" && named && /write|edit|create|save|append/i.test(toolName))
|
|
24467
|
-
out.add(absolute(named,
|
|
24857
|
+
out.add(absolute(named, base3, home));
|
|
24468
24858
|
for (const a of fileAccess?.accesses ?? []) {
|
|
24469
24859
|
if (a.operation !== "write" && a.operation !== "create") continue;
|
|
24470
24860
|
if (a.glob || a.recursive) continue;
|
|
24471
|
-
out.add(absolute(a.path, a.cwd ??
|
|
24861
|
+
out.add(absolute(a.path, a.cwd ?? base3, home));
|
|
24472
24862
|
if (out.size >= MAX_RECORDED_WRITES) break;
|
|
24473
24863
|
}
|
|
24474
24864
|
return [...out];
|
|
@@ -24489,27 +24879,27 @@ init_dist();
|
|
|
24489
24879
|
|
|
24490
24880
|
// src/exposure/known-hosts.ts
|
|
24491
24881
|
init_cjs_shims();
|
|
24492
|
-
var
|
|
24882
|
+
var import_fs24 = __toESM(require("fs"));
|
|
24493
24883
|
var import_path25 = __toESM(require("path"));
|
|
24494
24884
|
|
|
24495
24885
|
// src/utils/git-remotes.ts
|
|
24496
24886
|
init_cjs_shims();
|
|
24497
|
-
var
|
|
24887
|
+
var import_fs23 = __toESM(require("fs"));
|
|
24498
24888
|
var import_path24 = __toESM(require("path"));
|
|
24499
24889
|
init_dist();
|
|
24500
|
-
function
|
|
24890
|
+
function readSmallFile2(p, max) {
|
|
24501
24891
|
let fd;
|
|
24502
24892
|
try {
|
|
24503
|
-
fd =
|
|
24504
|
-
const st =
|
|
24893
|
+
fd = import_fs23.default.openSync(p, import_fs23.default.constants.O_RDONLY | (import_fs23.default.constants.O_NOFOLLOW ?? 0));
|
|
24894
|
+
const st = import_fs23.default.fstatSync(fd);
|
|
24505
24895
|
if (!st.isFile() || st.size > max) return null;
|
|
24506
24896
|
const buf = Buffer.alloc(st.size);
|
|
24507
|
-
const n =
|
|
24897
|
+
const n = import_fs23.default.readSync(fd, buf, 0, st.size, 0);
|
|
24508
24898
|
return buf.subarray(0, n).toString("utf8");
|
|
24509
24899
|
} catch {
|
|
24510
24900
|
return null;
|
|
24511
24901
|
} finally {
|
|
24512
|
-
if (fd !== void 0)
|
|
24902
|
+
if (fd !== void 0) import_fs23.default.closeSync(fd);
|
|
24513
24903
|
}
|
|
24514
24904
|
}
|
|
24515
24905
|
function gitRemoteHost(url) {
|
|
@@ -24531,15 +24921,15 @@ function findGitConfig(dir2, walkUp = true) {
|
|
|
24531
24921
|
let cur = import_path24.default.resolve(dir2);
|
|
24532
24922
|
for (let i = 0; i < (walkUp ? 64 : 1); i++) {
|
|
24533
24923
|
const dotGit = import_path24.default.join(cur, ".git");
|
|
24534
|
-
const direct =
|
|
24924
|
+
const direct = readSmallFile2(import_path24.default.join(dotGit, "config"), 1e6);
|
|
24535
24925
|
if (direct !== null) return direct;
|
|
24536
|
-
const pointer =
|
|
24926
|
+
const pointer = readSmallFile2(dotGit, 4096);
|
|
24537
24927
|
const m = pointer && /^gitdir:\s*(.+?)\s*$/m.exec(pointer);
|
|
24538
24928
|
if (m) {
|
|
24539
24929
|
let gitDir = import_path24.default.resolve(cur, m[1]);
|
|
24540
|
-
const common =
|
|
24930
|
+
const common = readSmallFile2(import_path24.default.join(gitDir, "commondir"), 4096);
|
|
24541
24931
|
if (common !== null) gitDir = import_path24.default.resolve(gitDir, common.trim());
|
|
24542
|
-
return
|
|
24932
|
+
return readSmallFile2(import_path24.default.join(gitDir, "config"), 1e6);
|
|
24543
24933
|
}
|
|
24544
24934
|
const parent = import_path24.default.dirname(cur);
|
|
24545
24935
|
if (parent === cur) return null;
|
|
@@ -24596,7 +24986,7 @@ function manifestRoot(dir2) {
|
|
|
24596
24986
|
for (let i = 0; i < 64; i++) {
|
|
24597
24987
|
for (const [m] of ECOSYSTEMS) {
|
|
24598
24988
|
try {
|
|
24599
|
-
if (
|
|
24989
|
+
if (import_fs24.default.existsSync(import_path25.default.join(cur, m))) return cur;
|
|
24600
24990
|
} catch {
|
|
24601
24991
|
}
|
|
24602
24992
|
}
|
|
@@ -24622,10 +25012,10 @@ function knownProjectHosts(dir2) {
|
|
|
24622
25012
|
const root = manifestRoot(key);
|
|
24623
25013
|
if (root !== null) {
|
|
24624
25014
|
for (const [m, registry] of ECOSYSTEMS) {
|
|
24625
|
-
if (
|
|
25015
|
+
if (import_fs24.default.existsSync(import_path25.default.join(root, m))) out.hosts.add(registry);
|
|
24626
25016
|
}
|
|
24627
25017
|
try {
|
|
24628
|
-
if (
|
|
25018
|
+
if (import_fs24.default.readdirSync(root).some((f) => f.endsWith(".gemspec")))
|
|
24629
25019
|
out.hosts.add("host:rubygems.org");
|
|
24630
25020
|
} catch {
|
|
24631
25021
|
}
|
|
@@ -24638,8 +25028,8 @@ function knownProjectHosts(dir2) {
|
|
|
24638
25028
|
|
|
24639
25029
|
// src/exposure/writes.ts
|
|
24640
25030
|
init_cjs_shims();
|
|
24641
|
-
var
|
|
24642
|
-
var
|
|
25031
|
+
var import_fs25 = __toESM(require("fs"));
|
|
25032
|
+
var import_os17 = __toESM(require("os"));
|
|
24643
25033
|
var import_path26 = __toESM(require("path"));
|
|
24644
25034
|
init_dist();
|
|
24645
25035
|
var WRITE_OPS = /* @__PURE__ */ new Set(["write", "create", "remove"]);
|
|
@@ -24670,7 +25060,7 @@ function packageScriptsTouched(args, absPath, shellCommand) {
|
|
|
24670
25060
|
if (typeof a.content === "string") {
|
|
24671
25061
|
try {
|
|
24672
25062
|
const next = JSON.parse(a.content);
|
|
24673
|
-
const prev = JSON.parse(
|
|
25063
|
+
const prev = JSON.parse(import_fs25.default.readFileSync(absPath, "utf8"));
|
|
24674
25064
|
return JSON.stringify(next.scripts ?? null) !== JSON.stringify(prev.scripts ?? null);
|
|
24675
25065
|
} catch {
|
|
24676
25066
|
return LIFECYCLE_RE.test(a.content);
|
|
@@ -24680,8 +25070,8 @@ function packageScriptsTouched(args, absPath, shellCommand) {
|
|
|
24680
25070
|
}
|
|
24681
25071
|
function judgeWritesAfterExposure(opts) {
|
|
24682
25072
|
const holds = [];
|
|
24683
|
-
const home = opts.home ??
|
|
24684
|
-
const tmp = normalizeFilePath(
|
|
25073
|
+
const home = opts.home ?? import_os17.default.homedir();
|
|
25074
|
+
const tmp = normalizeFilePath(import_os17.default.tmpdir());
|
|
24685
25075
|
const root = opts.cwd ? normalizeFilePath(opts.cwd, "", home) : null;
|
|
24686
25076
|
const seen = /* @__PURE__ */ new Set();
|
|
24687
25077
|
for (const access of opts.accesses) {
|
|
@@ -24714,8 +25104,8 @@ function judgeWritesAfterExposure(opts) {
|
|
|
24714
25104
|
// src/exposure/marker.ts
|
|
24715
25105
|
init_cjs_shims();
|
|
24716
25106
|
var import_crypto9 = __toESM(require("crypto"));
|
|
24717
|
-
var
|
|
24718
|
-
var
|
|
25107
|
+
var import_fs26 = __toESM(require("fs"));
|
|
25108
|
+
var import_os18 = __toESM(require("os"));
|
|
24719
25109
|
var import_path27 = __toESM(require("path"));
|
|
24720
25110
|
|
|
24721
25111
|
// src/daemon/exposure-store.ts
|
|
@@ -24725,7 +25115,7 @@ var SESSION_EXPOSURE_TTL_MS = 4 * 60 * 60 * 1e3;
|
|
|
24725
25115
|
// src/exposure/marker.ts
|
|
24726
25116
|
init_forecast_context();
|
|
24727
25117
|
function dir() {
|
|
24728
|
-
return import_path27.default.join(
|
|
25118
|
+
return import_path27.default.join(import_os18.default.homedir(), ".node9", "exposure-sessions");
|
|
24729
25119
|
}
|
|
24730
25120
|
function file(sessionId) {
|
|
24731
25121
|
const id = import_crypto9.default.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
|
|
@@ -24736,7 +25126,7 @@ function maybeSessionExposed(sessionId) {
|
|
|
24736
25126
|
const forecast = forecastRun();
|
|
24737
25127
|
if (forecast) return forecast.session.checkExposure(forecast.now) !== null;
|
|
24738
25128
|
try {
|
|
24739
|
-
const st =
|
|
25129
|
+
const st = import_fs26.default.statSync(file(sessionId));
|
|
24740
25130
|
return Date.now() - st.mtimeMs < SESSION_EXPOSURE_TTL_MS;
|
|
24741
25131
|
} catch (e) {
|
|
24742
25132
|
return e.code !== "ENOENT";
|
|
@@ -24745,7 +25135,7 @@ function maybeSessionExposed(sessionId) {
|
|
|
24745
25135
|
|
|
24746
25136
|
// src/exposure/roles.ts
|
|
24747
25137
|
init_cjs_shims();
|
|
24748
|
-
var
|
|
25138
|
+
var import_fs27 = __toESM(require("fs"));
|
|
24749
25139
|
var EXPOSURE_LABEL = "\u{1F6E1}\uFE0F Node9 Exposure";
|
|
24750
25140
|
var AGENT_INTERNAL_PREFIXES = ["ccd_", "visualize"];
|
|
24751
25141
|
function foldServerName(name) {
|
|
@@ -24755,7 +25145,7 @@ var inventoryCache = null;
|
|
|
24755
25145
|
var inventoryStamp = null;
|
|
24756
25146
|
function inventoryFileStamp() {
|
|
24757
25147
|
try {
|
|
24758
|
-
const st =
|
|
25148
|
+
const st = import_fs27.default.statSync(getMcpToolsFile());
|
|
24759
25149
|
return `${st.mtimeMs}:${st.size}`;
|
|
24760
25150
|
} catch {
|
|
24761
25151
|
return "";
|
|
@@ -24840,16 +25230,16 @@ function sourceWord(toolName) {
|
|
|
24840
25230
|
|
|
24841
25231
|
// src/auth/trusted-recipients.ts
|
|
24842
25232
|
init_cjs_shims();
|
|
24843
|
-
var
|
|
25233
|
+
var import_fs28 = __toESM(require("fs"));
|
|
24844
25234
|
var import_path28 = __toESM(require("path"));
|
|
24845
|
-
var
|
|
25235
|
+
var import_os19 = __toESM(require("os"));
|
|
24846
25236
|
init_dist();
|
|
24847
25237
|
function getTrustedRecipientsPath() {
|
|
24848
|
-
return import_path28.default.join(
|
|
25238
|
+
return import_path28.default.join(import_os19.default.homedir(), ".node9", "trusted-recipients.json");
|
|
24849
25239
|
}
|
|
24850
25240
|
function readTrustedRecipients() {
|
|
24851
25241
|
try {
|
|
24852
|
-
const raw =
|
|
25242
|
+
const raw = import_fs28.default.readFileSync(getTrustedRecipientsPath(), "utf8");
|
|
24853
25243
|
const parsed = JSON.parse(raw);
|
|
24854
25244
|
return Array.isArray(parsed.entries) ? parsed.entries.filter((e) => e && typeof e.value === "string") : [];
|
|
24855
25245
|
} catch {
|
|
@@ -24858,10 +25248,10 @@ function readTrustedRecipients() {
|
|
|
24858
25248
|
}
|
|
24859
25249
|
function writeTrustedRecipients(entries) {
|
|
24860
25250
|
const filePath = getTrustedRecipientsPath();
|
|
24861
|
-
|
|
25251
|
+
import_fs28.default.mkdirSync(import_path28.default.dirname(filePath), { recursive: true });
|
|
24862
25252
|
const tmp = filePath + ".node9-tmp";
|
|
24863
|
-
|
|
24864
|
-
|
|
25253
|
+
import_fs28.default.writeFileSync(tmp, JSON.stringify({ entries }, null, 2), { mode: 384 });
|
|
25254
|
+
import_fs28.default.renameSync(tmp, filePath);
|
|
24865
25255
|
}
|
|
24866
25256
|
function addTrustedRecipient(raw, addedBy = "user") {
|
|
24867
25257
|
const value = normalizeRecipient(raw);
|
|
@@ -24876,7 +25266,7 @@ function addTrustedRecipient(raw, addedBy = "user") {
|
|
|
24876
25266
|
var cache6 = null;
|
|
24877
25267
|
function mtimeOf() {
|
|
24878
25268
|
try {
|
|
24879
|
-
return
|
|
25269
|
+
return import_fs28.default.statSync(getTrustedRecipientsPath()).mtimeMs;
|
|
24880
25270
|
} catch {
|
|
24881
25271
|
return 0;
|
|
24882
25272
|
}
|
|
@@ -24894,8 +25284,8 @@ init_forecast_context();
|
|
|
24894
25284
|
|
|
24895
25285
|
// src/auth/cloud.ts
|
|
24896
25286
|
init_cjs_shims();
|
|
24897
|
-
var
|
|
24898
|
-
var
|
|
25287
|
+
var import_fs29 = __toESM(require("fs"));
|
|
25288
|
+
var import_os20 = __toESM(require("os"));
|
|
24899
25289
|
var import_path29 = __toESM(require("path"));
|
|
24900
25290
|
init_audit();
|
|
24901
25291
|
init_dist();
|
|
@@ -24932,7 +25322,7 @@ async function initNode9SaaS(toolName, args, creds, meta, riskMetadata, agentPol
|
|
|
24932
25322
|
let ciContext;
|
|
24933
25323
|
if (process.env.CI) {
|
|
24934
25324
|
try {
|
|
24935
|
-
const ciContextPath = import_path29.default.join(
|
|
25325
|
+
const ciContextPath = import_path29.default.join(import_os20.default.homedir(), ".node9", "ci-context.json");
|
|
24936
25326
|
const ci = readCappedText(ciContextPath, 1e4);
|
|
24937
25327
|
if (!ci) throw new Error("ci-context.json unreadable");
|
|
24938
25328
|
if (ci.truncated) throw new Error("ci-context.json exceeds 10 KB");
|
|
@@ -24974,9 +25364,9 @@ async function initNode9SaaS(toolName, args, creds, meta, riskMetadata, agentPol
|
|
|
24974
25364
|
context: {
|
|
24975
25365
|
agent: meta?.agent,
|
|
24976
25366
|
mcpServer: meta?.mcpServer,
|
|
24977
|
-
hostname:
|
|
25367
|
+
hostname: import_os20.default.hostname(),
|
|
24978
25368
|
cwd: process.cwd(),
|
|
24979
|
-
platform:
|
|
25369
|
+
platform: import_os20.default.platform()
|
|
24980
25370
|
},
|
|
24981
25371
|
// The SaaS validates riskMetadata strictly and would drop it whole on
|
|
24982
25372
|
// an unknown key, so only fields its schema declares go on the wire.
|
|
@@ -25050,14 +25440,14 @@ async function resolveNode9SaaS(requestId, creds, approved, decidedBy) {
|
|
|
25050
25440
|
});
|
|
25051
25441
|
clearTimeout(timer);
|
|
25052
25442
|
if (!res.ok) {
|
|
25053
|
-
|
|
25443
|
+
import_fs29.default.appendFileSync(
|
|
25054
25444
|
HOOK_DEBUG_LOG,
|
|
25055
25445
|
`[resolve-cloud] PATCH ${safeMessage(resolveUrl, 200)} \u2192 HTTP ${res.status}
|
|
25056
25446
|
`
|
|
25057
25447
|
);
|
|
25058
25448
|
}
|
|
25059
25449
|
} catch (err) {
|
|
25060
|
-
|
|
25450
|
+
import_fs29.default.appendFileSync(
|
|
25061
25451
|
HOOK_DEBUG_LOG,
|
|
25062
25452
|
`[resolve-cloud] PATCH failed for ${safeMessage(requestId, 64)}: ${safeMessage(err)}
|
|
25063
25453
|
`
|
|
@@ -25067,19 +25457,19 @@ async function resolveNode9SaaS(requestId, creds, approved, decidedBy) {
|
|
|
25067
25457
|
|
|
25068
25458
|
// src/loop-detector.ts
|
|
25069
25459
|
init_cjs_shims();
|
|
25070
|
-
var
|
|
25460
|
+
var import_fs30 = __toESM(require("fs"));
|
|
25071
25461
|
var import_path30 = __toESM(require("path"));
|
|
25072
|
-
var
|
|
25462
|
+
var import_os21 = __toESM(require("os"));
|
|
25073
25463
|
init_dist();
|
|
25074
25464
|
init_forecast_context();
|
|
25075
25465
|
init_dist();
|
|
25076
25466
|
function loopStateFile() {
|
|
25077
|
-
return import_path30.default.join(
|
|
25467
|
+
return import_path30.default.join(import_os21.default.homedir(), ".node9", "loop-state.json");
|
|
25078
25468
|
}
|
|
25079
25469
|
function readState() {
|
|
25080
25470
|
try {
|
|
25081
|
-
if (!
|
|
25082
|
-
const raw =
|
|
25471
|
+
if (!import_fs30.default.existsSync(loopStateFile())) return [];
|
|
25472
|
+
const raw = import_fs30.default.readFileSync(loopStateFile(), "utf-8");
|
|
25083
25473
|
const parsed = JSON.parse(raw);
|
|
25084
25474
|
if (!Array.isArray(parsed)) return [];
|
|
25085
25475
|
return parsed;
|
|
@@ -25089,10 +25479,10 @@ function readState() {
|
|
|
25089
25479
|
}
|
|
25090
25480
|
function writeState(records) {
|
|
25091
25481
|
const dir2 = import_path30.default.dirname(loopStateFile());
|
|
25092
|
-
if (!
|
|
25093
|
-
const tmpPath = `${loopStateFile()}.${
|
|
25094
|
-
|
|
25095
|
-
|
|
25482
|
+
if (!import_fs30.default.existsSync(dir2)) import_fs30.default.mkdirSync(dir2, { recursive: true });
|
|
25483
|
+
const tmpPath = `${loopStateFile()}.${import_os21.default.hostname()}.${process.pid}.tmp`;
|
|
25484
|
+
import_fs30.default.writeFileSync(tmpPath, JSON.stringify(records));
|
|
25485
|
+
import_fs30.default.renameSync(tmpPath, loopStateFile());
|
|
25096
25486
|
}
|
|
25097
25487
|
function recordAndCheck(tool, args, threshold = 3, windowMs = 12e4) {
|
|
25098
25488
|
try {
|
|
@@ -25291,7 +25681,7 @@ function isMcpToolName(toolName) {
|
|
|
25291
25681
|
return /^mcp__[^_](?:[^_]|_(?!_))*?__/i.test(toolName);
|
|
25292
25682
|
}
|
|
25293
25683
|
function absoluteUploadPath(spelled, cwd) {
|
|
25294
|
-
const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path31.default.join(
|
|
25684
|
+
const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path31.default.join(import_os22.default.homedir(), spelled.slice(1)) : spelled;
|
|
25295
25685
|
if (import_path31.default.isAbsolute(expanded)) return expanded;
|
|
25296
25686
|
return cwd && import_path31.default.isAbsolute(cwd) ? import_path31.default.resolve(cwd, expanded) : expanded;
|
|
25297
25687
|
}
|
|
@@ -25617,8 +26007,17 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25617
26007
|
const judged = sendsSomething || (!!shellExp?.fetches || writes.length > 0) && mayBeExposed;
|
|
25618
26008
|
if (judged) {
|
|
25619
26009
|
const exposure = await checkSessionExposure(meta.sessionId);
|
|
25620
|
-
|
|
25621
|
-
|
|
26010
|
+
const unknownRead = exposure.daemonUnavailable === true && holdsSendsWithoutDaemon(config.settings.mode);
|
|
26011
|
+
const rec = exposure.exposed && exposure.record ? exposure.record : unknownRead ? {
|
|
26012
|
+
sessionId: meta.sessionId,
|
|
26013
|
+
sources: [],
|
|
26014
|
+
destinations: [],
|
|
26015
|
+
userMentioned: [],
|
|
26016
|
+
approved: [],
|
|
26017
|
+
createdAt: 0,
|
|
26018
|
+
expiresAt: 0
|
|
26019
|
+
} : null;
|
|
26020
|
+
if (rec) {
|
|
25622
26021
|
const dests = new Set(
|
|
25623
26022
|
acts && !shellExp && !mcpFileWrite ? extractArgDestinations(args) : []
|
|
25624
26023
|
);
|
|
@@ -25677,7 +26076,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25677
26076
|
if (dests.size === 0 && acts && !mcpFileWrite && (role.destructive === true || isDestructiveToolName(bare))) {
|
|
25678
26077
|
held.push({ dest: "", why: "destructive" });
|
|
25679
26078
|
}
|
|
25680
|
-
const writeHolds = writes.length > 0 ? judgeWritesAfterExposure({
|
|
26079
|
+
const writeHolds = writes.length > 0 && !(unknownRead && !exposure.exposed) ? judgeWritesAfterExposure({
|
|
25681
26080
|
accesses: writes,
|
|
25682
26081
|
args,
|
|
25683
26082
|
shellCommand: shellInput.kind === "shell" ? shellInput.command : null,
|
|
@@ -25704,14 +26103,14 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
25704
26103
|
const parts = held.map(
|
|
25705
26104
|
(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`
|
|
25706
26105
|
);
|
|
25707
|
-
const home =
|
|
26106
|
+
const home = import_os22.default.homedir();
|
|
25708
26107
|
const short = (p) => p.startsWith(home + "/") ? "~" + p.slice(home.length) : p;
|
|
25709
26108
|
for (const w of writeHolds) {
|
|
25710
26109
|
parts.push(
|
|
25711
26110
|
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}`
|
|
25712
26111
|
);
|
|
25713
26112
|
}
|
|
25714
|
-
exposureReview = `\u{1F6E1}\uFE0F Node9: this session read ${read2}. This call ${parts.join("; and ")}.`;
|
|
26113
|
+
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 ")}.`;
|
|
25715
26114
|
exposureFromEid = last?.eid;
|
|
25716
26115
|
if (exposureFromEid) exposureMeta = { exposureFromEid };
|
|
25717
26116
|
exposureKeys = [
|