@node9/proxy 2.46.1 → 2.47.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.mjs CHANGED
@@ -101,22 +101,16 @@ var init_forecast_context = __esm({
101
101
  });
102
102
 
103
103
  // packages/policy-engine/dist/index.mjs
104
- import mvdanSh3 from "mvdan-sh";
105
104
  import picomatch from "picomatch";
106
105
  import safeRegex from "safe-regex2";
107
106
  import pm from "picomatch";
108
- import mvdanSh from "mvdan-sh";
109
107
  import mvdanSh2 from "mvdan-sh";
108
+ import mvdanSh from "mvdan-sh";
109
+ import mvdanSh3 from "mvdan-sh";
110
110
  import safeRegex2 from "safe-regex2";
111
111
  import { createHash as createHash2 } from "crypto";
112
112
  import { createHash as createHash22 } from "crypto";
113
- import mvdanSh4 from "mvdan-sh";
114
- import mvdanSh5 from "mvdan-sh";
115
- import mvdanSh6 from "mvdan-sh";
116
- import mvdanSh8 from "mvdan-sh";
117
- import mvdanSh7 from "mvdan-sh";
118
113
  import { createHash as createHash3 } from "crypto";
119
- import mvdanSh9 from "mvdan-sh";
120
114
  import crypto from "crypto";
121
115
  function validateRegex(pattern) {
122
116
  if (!pattern) return "Pattern is required";
@@ -701,6 +695,62 @@ function resolveCheckMap(settings) {
701
695
  for (const c of CHECKS) out[c.id] = checkValue(settings, c.id);
702
696
  return out;
703
697
  }
698
+ function isGoNode(v) {
699
+ return v !== null && typeof v === "object" && typeof v.Pos === "function";
700
+ }
701
+ function toPlainTree(goNode) {
702
+ const kind = syntax.NodeType(goNode);
703
+ const out = { kind, pos: goNode.Pos().Offset(), end: goNode.End().Offset() };
704
+ const spec = KINDS[kind];
705
+ if (!spec) {
706
+ unknownKinds.add(kind);
707
+ return out;
708
+ }
709
+ convertFields(goNode, spec, out, kind);
710
+ return out;
711
+ }
712
+ function convertFields(goNode, spec, out, kind) {
713
+ for (const f of spec.scalars ?? []) out[f] = goNode[f];
714
+ for (const f of spec.nodes ?? []) {
715
+ const v = goNode[f];
716
+ if (v === void 0 || v === null) {
717
+ out[f] = null;
718
+ } else if (Array.isArray(v)) {
719
+ out[f] = v.map((c) => isGoNode(c) ? toPlainTree(c) : c);
720
+ } else if (isGoNode(v)) {
721
+ out[f] = toPlainTree(v);
722
+ } else if (typeof v === "object" && STRUCTS[`${kind}.${f}`]) {
723
+ const sub = { struct: `${kind}.${f}` };
724
+ convertFields(v, STRUCTS[`${kind}.${f}`], sub, `${kind}.${f}`);
725
+ out[f] = sub;
726
+ } else {
727
+ out[f] = v;
728
+ }
729
+ }
730
+ }
731
+ function childrenOf(n) {
732
+ const spec = n.kind ? KINDS[n.kind] : STRUCTS[n.struct];
733
+ if (!spec?.nodes) return [];
734
+ const out = [];
735
+ for (const f of spec.nodes) {
736
+ if (spec.notWalked?.includes(f)) continue;
737
+ const v = n[f];
738
+ if (!v) continue;
739
+ if (Array.isArray(v)) {
740
+ for (const c of v) if (c) out.push(c);
741
+ } else if (v.kind) {
742
+ out.push(v);
743
+ } else if (v.struct) {
744
+ out.push(...childrenOf(v));
745
+ }
746
+ }
747
+ return out;
748
+ }
749
+ function walk(root, fn) {
750
+ if (!root) return;
751
+ if (!fn(root)) return;
752
+ for (const c of childrenOf(root)) walk(c, fn);
753
+ }
704
754
  function isInvisibleChar(char) {
705
755
  return INVISIBLE_ONE.test(char);
706
756
  }
@@ -856,7 +906,7 @@ function judgeInlineCode(language, code2, isProtected) {
856
906
  }
857
907
  function isCatHeredocOrLit(part) {
858
908
  if (!part) return false;
859
- const t = syntax.NodeType(part);
909
+ const t = part.kind;
860
910
  if (t === "Lit") return true;
861
911
  if (t !== "CmdSubst") return false;
862
912
  const stmts = part.Stmts || [];
@@ -866,9 +916,9 @@ function isCatHeredocOrLit(part) {
866
916
  const hasHeredoc = redirs.some((r) => r && r.Hdoc);
867
917
  if (!hasHeredoc) return false;
868
918
  const cmd = stmt.Cmd;
869
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return false;
919
+ if (!cmd || cmd.kind !== "CallExpr") return false;
870
920
  const firstArg2 = cmd.Args?.[0]?.Parts || [];
871
- if (firstArg2.length !== 1 || syntax.NodeType(firstArg2[0]) !== "Lit") return false;
921
+ if (firstArg2.length !== 1 || firstArg2[0].kind !== "Lit") return false;
872
922
  return (firstArg2[0].Value || "").toLowerCase() === "cat";
873
923
  }
874
924
  function parseShared(command) {
@@ -880,7 +930,7 @@ function parseShared(command) {
880
930
  }
881
931
  let parsed;
882
932
  try {
883
- parsed = sharedParser.Parse(command, "cmd");
933
+ parsed = toPlainTree(sharedParser.Parse(command, "cmd"));
884
934
  } catch {
885
935
  parsed = PARSE_FAIL;
886
936
  }
@@ -941,10 +991,10 @@ function fileAccessViewImpl(command) {
941
991
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
942
992
  const edits = [];
943
993
  try {
944
- syntax.Walk(f, (node) => {
994
+ walk(f, (node) => {
945
995
  if (!node) return false;
946
996
  const n = node;
947
- if (syntax.NodeType(n) !== "CallExpr") return true;
997
+ if (n.kind !== "CallExpr") return true;
948
998
  const args = n.Args || [];
949
999
  const words = args.map((a) => resolveWordLiteral(a));
950
1000
  const head = unwrapCommandHead(words);
@@ -956,8 +1006,8 @@ function fileAccessViewImpl(command) {
956
1006
  if (!PROGRAM_DIR.test(word)) continue;
957
1007
  const name = word.split(/[\\/]/).pop() ?? "";
958
1008
  if (!name) continue;
959
- const s = at(args[i].Pos().Offset());
960
- const e = at(args[i].End().Offset());
1009
+ const s = at(args[i].pos);
1010
+ const e = at(args[i].end);
961
1011
  if (s < 0 || e < 0) continue;
962
1012
  edits.push([s, e, name]);
963
1013
  }
@@ -985,10 +1035,10 @@ function literalPayloadsOf(command, depth) {
985
1035
  if (f === PARSE_FAIL) return [];
986
1036
  const out = [];
987
1037
  try {
988
- syntax.Walk(f, (node) => {
1038
+ walk(f, (node) => {
989
1039
  if (!node || out.length >= MAX_READING_PAYLOADS) return false;
990
1040
  const n = node;
991
- if (syntax.NodeType(n) !== "CallExpr") return true;
1041
+ if (n.kind !== "CallExpr") return true;
992
1042
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
993
1043
  if (words.length === 0) return true;
994
1044
  const payload = literalShellPayload(words, baseWord(words[0]));
@@ -1008,23 +1058,23 @@ function foldCommandWords(reading) {
1008
1058
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
1009
1059
  const edits = [];
1010
1060
  try {
1011
- syntax.Walk(f, (node) => {
1061
+ walk(f, (node) => {
1012
1062
  if (!node) return false;
1013
1063
  const n = node;
1014
- if (syntax.NodeType(n) !== "CallExpr") return true;
1064
+ if (n.kind !== "CallExpr") return true;
1015
1065
  const args = n.Args || [];
1016
1066
  const words = args.map((a) => resolveWordLiteral(a));
1017
1067
  const folded = words.map((w) => w === null ? null : foldHomoglyphs(w));
1018
1068
  const head = unwrapCommandHead(folded);
1019
1069
  for (let i = 0; i <= head && i < args.length; i++) {
1020
1070
  const parts = args[i].Parts || [];
1021
- if (parts.length !== 1 || syntax.NodeType(parts[0]) !== "Lit") continue;
1071
+ if (parts.length !== 1 || parts[0].kind !== "Lit") continue;
1022
1072
  const value = parts[0].Value ?? "";
1023
1073
  const word = folded[i];
1024
1074
  if (word === null || word === value || !/[^\x00-\x7f]/.test(value)) continue;
1025
1075
  if (!/^[A-Za-z0-9._/-]+$/.test(word)) continue;
1026
- const s = at(args[i].Pos().Offset());
1027
- const e = at(args[i].End().Offset());
1076
+ const s = at(args[i].pos);
1077
+ const e = at(args[i].end);
1028
1078
  if (s < 0 || e < 0) continue;
1029
1079
  edits.push([s, e, word]);
1030
1080
  }
@@ -1061,10 +1111,10 @@ function interpreterHeredocSpans(f, at) {
1061
1111
  const stmts = f?.Stmts || [];
1062
1112
  const candidates2 = [];
1063
1113
  let unsafe = false;
1064
- syntax.Walk(f, (node) => {
1114
+ walk(f, (node) => {
1065
1115
  if (!node || unsafe) return false;
1066
1116
  const n = node;
1067
- const t = syntax.NodeType(n);
1117
+ const t = n.kind;
1068
1118
  if (t === "FuncDecl") {
1069
1119
  unsafe = true;
1070
1120
  return false;
@@ -1084,7 +1134,7 @@ function interpreterHeredocSpans(f, at) {
1084
1134
  });
1085
1135
  if (unsafe) return [];
1086
1136
  for (const st of stmts) {
1087
- if (!st?.Cmd || syntax.NodeType(st.Cmd) !== "CallExpr") continue;
1137
+ if (!st?.Cmd || st.Cmd.kind !== "CallExpr") continue;
1088
1138
  const words = (st.Cmd.Args || []).map((a) => resolveWordLiteral(a));
1089
1139
  const name = (words[0] ?? "").toLowerCase();
1090
1140
  if (!STDIN_CODE_INTERPRETERS.test(name)) continue;
@@ -1099,8 +1149,8 @@ function interpreterHeredocSpans(f, at) {
1099
1149
  if (stdin.length !== 1 || others > 0) continue;
1100
1150
  const r = stdin[0];
1101
1151
  if (heredocText(r.Hdoc) === null) continue;
1102
- const hs = at(r.Hdoc.Pos().Offset());
1103
- const he = at(r.Hdoc.End().Offset());
1152
+ const hs = at(r.Hdoc.pos);
1153
+ const he = at(r.Hdoc.end);
1104
1154
  if (hs < 0 || he < 0 || he <= hs) continue;
1105
1155
  spans.push([hs, he]);
1106
1156
  }
@@ -1120,24 +1170,24 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1120
1170
  strips.push([hs, he]);
1121
1171
  msgSpans.add(`${hs}:${he}`);
1122
1172
  }
1123
- syntax.Walk(f, (node) => {
1173
+ walk(f, (node) => {
1124
1174
  if (!node) return false;
1125
1175
  const n = node;
1126
- if (syntax.NodeType(n) !== "CallExpr") return true;
1176
+ if (n.kind !== "CallExpr") return true;
1127
1177
  const args = n.Args || [];
1128
1178
  for (let i = 0; i < args.length - 1; i++) {
1129
1179
  const argParts = args[i].Parts || [];
1130
- if (argParts.length !== 1 || syntax.NodeType(argParts[0]) !== "Lit") continue;
1180
+ if (argParts.length !== 1 || argParts[0].kind !== "Lit") continue;
1131
1181
  const flagVal = argParts[0].Value || "";
1132
1182
  if (!MESSAGE_FLAGS.has(flagVal.toLowerCase())) continue;
1133
1183
  const next = args[i + 1];
1134
1184
  const nextParts = next.Parts || [];
1135
1185
  if (nextParts.length !== 1) continue;
1136
1186
  const quotedNode = nextParts[0];
1137
- const nt = syntax.NodeType(quotedNode);
1187
+ const nt = quotedNode.kind;
1138
1188
  const markStrip = () => {
1139
- const s = at(next.Pos().Offset());
1140
- const e = at(next.End().Offset());
1189
+ const s = at(next.pos);
1190
+ const e = at(next.end);
1141
1191
  if (s < 0 || e < 0) return;
1142
1192
  strips.push([s, e]);
1143
1193
  msgSpans.add(`${s}:${e}`);
@@ -1146,7 +1196,7 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1146
1196
  markStrip();
1147
1197
  } else if (nt === "DblQuoted") {
1148
1198
  const innerParts = quotedNode.Parts || [];
1149
- const allLit = innerParts.length === 0 || innerParts.every((p) => syntax.NodeType(p) === "Lit");
1199
+ const allLit = innerParts.length === 0 || innerParts.every((p) => p.kind === "Lit");
1150
1200
  if (allLit) {
1151
1201
  markStrip();
1152
1202
  } else if (innerParts.every((p) => isCatHeredocOrLit(p))) {
@@ -1155,8 +1205,8 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1155
1205
  }
1156
1206
  }
1157
1207
  for (const arg of args) {
1158
- const s = at(arg.Pos().Offset());
1159
- const e = at(arg.End().Offset());
1208
+ const s = at(arg.pos);
1209
+ const e = at(arg.end);
1160
1210
  if (s < 0 || e < 0) continue;
1161
1211
  if (msgSpans.has(`${s}:${e}`)) continue;
1162
1212
  const resolved = resolveWordLiteral(arg);
@@ -1196,10 +1246,10 @@ function scanArgsForDynamicExec(args, startIdx) {
1196
1246
  let hasParamExp = false;
1197
1247
  let hasCurl = false;
1198
1248
  for (let i = startIdx; i < args.length; i++) {
1199
- syntax.Walk(args[i], (inner) => {
1249
+ walk(args[i], (inner) => {
1200
1250
  if (!inner) return false;
1201
1251
  const inn = inner;
1202
- const it = syntax.NodeType(inn);
1252
+ const it = inn.kind;
1203
1253
  if (it === "CmdSubst") hasCmdSubst = true;
1204
1254
  if (it === "ParamExp") hasParamExp = true;
1205
1255
  if (it === "Lit" && DOWNLOAD_CMDS.has(inn.Value?.toLowerCase())) hasCurl = true;
@@ -1212,15 +1262,16 @@ function scanArgsForDynamicExec(args, startIdx) {
1212
1262
  }
1213
1263
  function detectDangerousShellExec(command) {
1214
1264
  try {
1215
- const f = sharedParser.Parse(command, "cmd");
1265
+ const f = parseShared(command);
1266
+ if (f === PARSE_FAIL) return null;
1216
1267
  let result = null;
1217
1268
  const assigned = assignedNames(f);
1218
- syntax.Walk(f, (node) => {
1269
+ walk(f, (node) => {
1219
1270
  if (!node || result === "block") return false;
1220
1271
  const n = node;
1221
- if (syntax.NodeType(n) === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1272
+ if (n.kind === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1222
1273
  const call = n.Y.Cmd;
1223
- if (call && syntax.NodeType(call) === "CallExpr") {
1274
+ if (call && call.kind === "CallExpr") {
1224
1275
  const words = (call.Args || []).map((a) => resolveWordLiteral(a));
1225
1276
  const head2 = unwrapCommandHead(words);
1226
1277
  const name = (words[head2] ?? "").split("/").pop() ?? "";
@@ -1233,7 +1284,7 @@ function detectDangerousShellExec(command) {
1233
1284
  result = "review";
1234
1285
  }
1235
1286
  }
1236
- if (syntax.NodeType(n) !== "CallExpr") return true;
1287
+ if (n.kind !== "CallExpr") return true;
1237
1288
  const args = n.Args || [];
1238
1289
  if (args.length === 0) return true;
1239
1290
  const headWords = args.map(
@@ -1244,7 +1295,7 @@ function detectDangerousShellExec(command) {
1244
1295
  if (!lookup && (opaqueExecutable(args[0], assigned) || opaqueExecutable(args[head], assigned)))
1245
1296
  result = "review";
1246
1297
  const firstParts = args[0].Parts || [];
1247
- if (firstParts.length !== 1 || syntax.NodeType(firstParts[0]) !== "Lit") return true;
1298
+ if (firstParts.length !== 1 || firstParts[0].kind !== "Lit") return true;
1248
1299
  const cmdName = firstParts[0].Value?.toLowerCase() ?? "";
1249
1300
  if (cmdName === "eval") {
1250
1301
  const v = scanArgsForDynamicExec(args, 1);
@@ -1252,7 +1303,7 @@ function detectDangerousShellExec(command) {
1252
1303
  } else if (SHELL_INTERPRETERS.has(cmdName)) {
1253
1304
  for (let i = 1; i < args.length - 1; i++) {
1254
1305
  const flagParts = args[i].Parts || [];
1255
- if (flagParts.length !== 1 || syntax.NodeType(flagParts[0]) !== "Lit" || flagParts[0].Value !== "-c")
1306
+ if (flagParts.length !== 1 || flagParts[0].kind !== "Lit" || flagParts[0].Value !== "-c")
1256
1307
  continue;
1257
1308
  const v = scanArgsForDynamicExec(args, i + 1);
1258
1309
  if (v === "block" || v === "review" && result === null) result = v;
@@ -1276,8 +1327,7 @@ function isDefaultExpansion(part) {
1276
1327
  }
1277
1328
  function lookupSubstitution(part) {
1278
1329
  const stmts = part.Stmts ?? [];
1279
- if (stmts.length !== 1 || !stmts[0].Cmd || syntax.NodeType(stmts[0].Cmd) !== "CallExpr")
1280
- return null;
1330
+ if (stmts.length !== 1 || !stmts[0].Cmd || stmts[0].Cmd.kind !== "CallExpr") return null;
1281
1331
  const words = (stmts[0].Cmd.Args ?? []).map((a) => resolveWordLiteral(a));
1282
1332
  if (words.some((w) => w === null)) return null;
1283
1333
  if (words.length === 2 && words[0] === "which") return words[1];
@@ -1287,9 +1337,9 @@ function lookupSubstitution(part) {
1287
1337
  }
1288
1338
  function assignedNames(f) {
1289
1339
  const names = /* @__PURE__ */ new Set();
1290
- syntax.Walk(f, (node) => {
1340
+ walk(f, (node) => {
1291
1341
  if (!node) return false;
1292
- const kind = syntax.NodeType(node);
1342
+ const kind = node.kind;
1293
1343
  if (kind === "Assign" && node.Name?.Value) names.add(node.Name.Value);
1294
1344
  if (kind === "ForClause" && node.Loop?.Name?.Value) names.add(node.Loop.Name.Value);
1295
1345
  if (kind === "CallExpr") {
@@ -1304,7 +1354,7 @@ function assignedNames(f) {
1304
1354
  }
1305
1355
  function executableParts(word, assigned, quoted = false) {
1306
1356
  return (word?.Parts ?? []).flatMap((part) => {
1307
- const kind = syntax.NodeType(part);
1357
+ const kind = part.kind;
1308
1358
  if (kind === "DblQuoted") return executableParts(part, assigned, true);
1309
1359
  if (kind === "Lit") return [{ kind: "Lit", value: part.Value ?? "", quoted }];
1310
1360
  if (kind === "SglQuoted")
@@ -1372,10 +1422,10 @@ function chmodHasOpenPermMode(command) {
1372
1422
  if (f === PARSE_FAIL) return false;
1373
1423
  let found = false;
1374
1424
  try {
1375
- syntax.Walk(f, (node) => {
1425
+ walk(f, (node) => {
1376
1426
  if (!node || found) return false;
1377
1427
  const n = node;
1378
- if (syntax.NodeType(n) !== "CallExpr") return true;
1428
+ if (n.kind !== "CallExpr") return true;
1379
1429
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1380
1430
  if (words.length === 0) return true;
1381
1431
  const name = (words[0] ?? "").toLowerCase();
@@ -1428,11 +1478,11 @@ function redirStdinOps() {
1428
1478
  }
1429
1479
  function deriveBinaryOp(sample) {
1430
1480
  try {
1431
- const f = sharedParser.Parse(sample, "cmd");
1481
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
1432
1482
  let op = -1;
1433
- syntax.Walk(f, (node) => {
1483
+ walk(f, (node) => {
1434
1484
  const n = node;
1435
- if (n && syntax.NodeType(n) === "BinaryCmd" && op < 0) op = n.Op;
1485
+ if (n && n.kind === "BinaryCmd" && op < 0) op = n.Op;
1436
1486
  return true;
1437
1487
  });
1438
1488
  return op;
@@ -1506,7 +1556,7 @@ function heredocText(word) {
1506
1556
  const parts = word?.Parts ?? [];
1507
1557
  let out = "";
1508
1558
  for (const p of parts) {
1509
- if (syntax.NodeType(p) !== "Lit") return null;
1559
+ if (p.kind !== "Lit") return null;
1510
1560
  out += p.Value ?? "";
1511
1561
  }
1512
1562
  return out;
@@ -1542,7 +1592,7 @@ function attachedCode(interp, flag) {
1542
1592
  }
1543
1593
  function inlineExecCall(stmt, pipeFed) {
1544
1594
  const cmd = stmt?.Cmd;
1545
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return null;
1595
+ if (!cmd || cmd.kind !== "CallExpr") return null;
1546
1596
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1547
1597
  if (words.length === 0) return null;
1548
1598
  const headIdx = unwrapCommandHead(words);
@@ -1623,10 +1673,10 @@ function shellPayloadNeedsReview(payload) {
1623
1673
  let review = false;
1624
1674
  payloadNesting++;
1625
1675
  try {
1626
- syntax.Walk(f, (node) => {
1676
+ walk(f, (node) => {
1627
1677
  if (!node || review) return false;
1628
1678
  const n = node;
1629
- if (syntax.NodeType(n) !== "CallExpr") return true;
1679
+ if (n.kind !== "CallExpr") return true;
1630
1680
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1631
1681
  if (words.length === 0) return true;
1632
1682
  const h = unwrapCommandHead(words);
@@ -1660,10 +1710,10 @@ function inlineExecCalls(command) {
1660
1710
  if (f === PARSE_FAIL) return PARSE_FAIL;
1661
1711
  const calls = [];
1662
1712
  try {
1663
- syntax.Walk(f, (node) => {
1713
+ walk(f, (node) => {
1664
1714
  if (!node || calls.length >= MAX_INLINE_CALLS) return false;
1665
1715
  const n = node;
1666
- const t = syntax.NodeType(n);
1716
+ const t = n.kind;
1667
1717
  if (t === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1668
1718
  const call = inlineExecCall(n.Y, true);
1669
1719
  if (call) calls.push(call);
@@ -1798,7 +1848,7 @@ function shellScriptOperands(command) {
1798
1848
  walkWithCalls(f, (node) => {
1799
1849
  if (!node) return false;
1800
1850
  const n = node;
1801
- if (syntax.NodeType(n) !== "CallExpr") return true;
1851
+ if (n.kind !== "CallExpr") return true;
1802
1852
  const callArgs = n.Args || [];
1803
1853
  if (callArgs.length === 0) return true;
1804
1854
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -1834,7 +1884,7 @@ function shellScriptOperands(command) {
1834
1884
  }
1835
1885
  function windowsDrivePathSpelling(word) {
1836
1886
  const parts = word?.Parts || [];
1837
- if (parts.length === 0 || !parts.every((p) => syntax.NodeType(p) === "Lit")) return null;
1887
+ if (parts.length === 0 || !parts.every((p) => p.kind === "Lit")) return null;
1838
1888
  const raw = parts.map((p) => p.Value ?? "").join("");
1839
1889
  return /^[A-Za-z]:\\[^\s'"$`]*$/.test(raw) ? raw : null;
1840
1890
  }
@@ -1872,15 +1922,15 @@ function recordTopLevelAssignments(f) {
1872
1922
  }
1873
1923
  function probeBinOp(src) {
1874
1924
  try {
1875
- const cmd = syntax.NewParser().Parse(src, "probe")?.Stmts?.[0]?.Cmd;
1876
- if (cmd && syntax.NodeType(cmd) === "BinaryCmd") return cmd.Op;
1925
+ const cmd = toPlainTree(syntax2.NewParser().Parse(src, "probe"))?.Stmts?.[0]?.Cmd;
1926
+ if (cmd && cmd.kind === "BinaryCmd") return cmd.Op;
1877
1927
  } catch {
1878
1928
  }
1879
1929
  return null;
1880
1930
  }
1881
1931
  function recordTopLevelStmt(stmt) {
1882
1932
  if (!stmt || !stmt.Cmd) return false;
1883
- const t = syntax.NodeType(stmt.Cmd);
1933
+ const t = stmt.Cmd.kind;
1884
1934
  if (t === "BinaryCmd") {
1885
1935
  if (!AND_OR_OPS.has(stmt.Cmd.Op)) return false;
1886
1936
  if (!recordTopLevelStmt(stmt.Cmd.X)) return false;
@@ -1890,7 +1940,7 @@ function recordTopLevelStmt(stmt) {
1890
1940
  if (t !== "CallExpr" && t !== "DeclClause") return false;
1891
1941
  let at = 0;
1892
1942
  try {
1893
- at = stmt.Pos().Offset();
1943
+ at = stmt.pos;
1894
1944
  } catch {
1895
1945
  at = 0;
1896
1946
  }
@@ -1901,14 +1951,14 @@ function recordTopLevelStmt(stmt) {
1901
1951
  }
1902
1952
  function recordAssignments(n, at) {
1903
1953
  if (!assignmentTable) return;
1904
- const t = syntax.NodeType(n);
1954
+ const t = n.kind;
1905
1955
  let assigns = [];
1906
1956
  if (t === "CallExpr") {
1907
1957
  if ((n.Args || []).length > 0) return;
1908
1958
  assigns = n.Assigns || [];
1909
1959
  } else if (t === "DeclClause") {
1910
1960
  if (!ASSIGNMENT_HEADS.has(n.Variant?.Value ?? "")) return;
1911
- assigns = (n.Args || []).filter((a) => syntax.NodeType(a) === "Assign");
1961
+ assigns = (n.Args || []).filter((a) => a.kind === "Assign");
1912
1962
  } else return;
1913
1963
  for (const a of assigns) {
1914
1964
  const name = a?.Name?.Value;
@@ -1917,13 +1967,13 @@ function recordAssignments(n, at) {
1917
1967
  }
1918
1968
  }
1919
1969
  function resolveTrivialSubst(part) {
1920
- if (syntax.NodeType(part) !== "CmdSubst") return void 0;
1970
+ if (part.kind !== "CmdSubst") return void 0;
1921
1971
  const stmts = part.Stmts || [];
1922
1972
  if (stmts.length !== 1) return void 0;
1923
1973
  const st = stmts[0];
1924
1974
  if ((st.Redirs || []).length > 0 || st.Negated || st.Background) return void 0;
1925
1975
  const cmd = st.Cmd;
1926
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return void 0;
1976
+ if (!cmd || cmd.kind !== "CallExpr") return void 0;
1927
1977
  if ((cmd.Assigns || []).length > 0) return void 0;
1928
1978
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1929
1979
  if (words.length === 0 || words.some((w) => w === null)) return void 0;
@@ -1948,7 +1998,7 @@ function recordedExpansion(name) {
1948
1998
  return rec.value;
1949
1999
  }
1950
2000
  function isPlainParam(p) {
1951
- if (syntax.NodeType(p) !== "ParamExp") return false;
2001
+ if (p.kind !== "ParamExp") return false;
1952
2002
  return !(p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp);
1953
2003
  }
1954
2004
  function expandPlainParam(p) {
@@ -1960,9 +2010,9 @@ function expandPlainParam(p) {
1960
2010
  }
1961
2011
  function functionBodies(f) {
1962
2012
  const out = /* @__PURE__ */ new Map();
1963
- syntax.Walk(f, (node) => {
2013
+ walk(f, (node) => {
1964
2014
  const n = node;
1965
- if (n && syntax.NodeType(n) === "FuncDecl" && n.Name?.Value && n.Body) {
2015
+ if (n && n.kind === "FuncDecl" && n.Name?.Value && n.Body) {
1966
2016
  const list2 = out.get(n.Name.Value) ?? [];
1967
2017
  list2.push(n.Body);
1968
2018
  out.set(n.Name.Value, list2);
@@ -1973,10 +2023,10 @@ function functionBodies(f) {
1973
2023
  }
1974
2024
  function rebindsPositionals(body) {
1975
2025
  let found = false;
1976
- syntax.Walk(body, (node) => {
2026
+ walk(body, (node) => {
1977
2027
  const n = node;
1978
2028
  if (found || !n) return false;
1979
- if (syntax.NodeType(n) === "CallExpr") {
2029
+ if (n.kind === "CallExpr") {
1980
2030
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1981
2031
  if (words[0] === "shift") found = true;
1982
2032
  else if (words[0] === "set" && words.slice(1).some((w) => w === null || w === "--" || !/^[-+]/.test(w)))
@@ -1996,7 +2046,7 @@ function tableBindings() {
1996
2046
  function walkWithCalls(f, visit2) {
1997
2047
  const bodies = functionBodies(f);
1998
2048
  if (bodies.size === 0) {
1999
- syntax.Walk(f, visit2);
2049
+ walk(f, visit2);
2000
2050
  return;
2001
2051
  }
2002
2052
  const seenCalls = /* @__PURE__ */ new Set();
@@ -2030,8 +2080,8 @@ function walkWithCalls(f, visit2) {
2030
2080
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2031
2081
  callDepth++;
2032
2082
  try {
2033
- if (body.Cmd && syntax.NodeType(body.Cmd) === "Block") recordTopLevelAssignments(body.Cmd);
2034
- syntax.Walk(body, step);
2083
+ if (body.Cmd && body.Cmd.kind === "Block") recordTopLevelAssignments(body.Cmd);
2084
+ walk(body, step);
2035
2085
  } finally {
2036
2086
  callDepth--;
2037
2087
  assignmentTable = outerTable;
@@ -2042,10 +2092,10 @@ function walkWithCalls(f, visit2) {
2042
2092
  const step = (node) => {
2043
2093
  if (!node) return false;
2044
2094
  const go = visit2(node);
2045
- if (go !== false && syntax.NodeType(node) === "CallExpr") inline(node);
2095
+ if (go !== false && node.kind === "CallExpr") inline(node);
2046
2096
  return go;
2047
2097
  };
2048
- syntax.Walk(f, step);
2098
+ walk(f, step);
2049
2099
  }
2050
2100
  function withAssignments(f, body) {
2051
2101
  const outerTable = assignmentTable;
@@ -2070,7 +2120,7 @@ function walkCommandScope(command, visit2) {
2070
2120
  if (f === PARSE_FAIL) return "parse-fail";
2071
2121
  withAssignments(f, () => {
2072
2122
  walkWithCalls(f, (node) => {
2073
- if (node && syntax.NodeType(node) === "Stmt") trackStatement(node);
2123
+ if (node && node.kind === "Stmt") trackStatement(node);
2074
2124
  return visit2(node);
2075
2125
  });
2076
2126
  });
@@ -2078,7 +2128,7 @@ function walkCommandScope(command, visit2) {
2078
2128
  }
2079
2129
  function trackStatement(n) {
2080
2130
  try {
2081
- currentStmtOffset = n.Pos().Offset();
2131
+ currentStmtOffset = n.pos;
2082
2132
  } catch {
2083
2133
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2084
2134
  }
@@ -2094,11 +2144,11 @@ function resolveWordLiteral(w) {
2094
2144
  return s;
2095
2145
  }
2096
2146
  function resolveWordPrefix(w) {
2097
- const walk2 = (parts) => {
2147
+ const walk3 = (parts) => {
2098
2148
  let s = "";
2099
2149
  for (const p of parts) {
2100
2150
  if (p && typeof p === "object" && Array.isArray(p.Parts) && p.Dollar !== void 0) {
2101
- const inner = walk2(p.Parts);
2151
+ const inner = walk3(p.Parts);
2102
2152
  s += inner.prefix;
2103
2153
  if (inner.dynamic) return { prefix: s, dynamic: true };
2104
2154
  continue;
@@ -2109,10 +2159,10 @@ function resolveWordPrefix(w) {
2109
2159
  }
2110
2160
  return { prefix: s, dynamic: false };
2111
2161
  };
2112
- return walk2(w?.Parts || []);
2162
+ return walk3(w?.Parts || []);
2113
2163
  }
2114
2164
  function resolvePart(p, inQuotes) {
2115
- const t = syntax.NodeType(p);
2165
+ const t = p.kind;
2116
2166
  if (t === "Lit") {
2117
2167
  const raw = p.Value ?? "";
2118
2168
  if (!inQuotes) return raw.replace(/\\(.)/g, "$1");
@@ -2208,7 +2258,7 @@ function extractShellDestinations(command) {
2208
2258
  () => walkWithCalls(f, (node) => {
2209
2259
  if (!node) return false;
2210
2260
  const n = node;
2211
- if (syntax.NodeType(n) === "Stmt") {
2261
+ if (n.kind === "Stmt") {
2212
2262
  trackStatement(n);
2213
2263
  for (const raw of redirectWords(n)) {
2214
2264
  const host2 = devNetRedirectHost(raw);
@@ -2220,7 +2270,7 @@ function extractShellDestinations(command) {
2220
2270
  out.push({ host: host2, binary, raw });
2221
2271
  }
2222
2272
  }
2223
- if (syntax.NodeType(n) !== "CallExpr") return true;
2273
+ if (n.kind !== "CallExpr") return true;
2224
2274
  const callArgs = n.Args || [];
2225
2275
  if (callArgs.length === 0) return true;
2226
2276
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2255,7 +2305,7 @@ function extractShellDestTokens(command) {
2255
2305
  () => walkWithCalls(f, (node) => {
2256
2306
  if (!node) return false;
2257
2307
  const n = node;
2258
- if (syntax.NodeType(n) === "Stmt") {
2308
+ if (n.kind === "Stmt") {
2259
2309
  trackStatement(n);
2260
2310
  for (const raw of redirectWords(n)) {
2261
2311
  const host2 = devNetRedirectHost(raw);
@@ -2267,7 +2317,7 @@ function extractShellDestTokens(command) {
2267
2317
  out.push({ token: host2, binary });
2268
2318
  }
2269
2319
  }
2270
- if (syntax.NodeType(n) !== "CallExpr") return true;
2320
+ if (n.kind !== "CallExpr") return true;
2271
2321
  const callArgs = n.Args || [];
2272
2322
  if (callArgs.length === 0) return true;
2273
2323
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2335,11 +2385,11 @@ function isWaivableCleanupTarget(p) {
2335
2385
  }
2336
2386
  function deriveRedirOp(sample) {
2337
2387
  try {
2338
- const f = sharedParser.Parse(sample, "cmd");
2388
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
2339
2389
  let op = -1;
2340
- syntax.Walk(f, (node) => {
2390
+ walk(f, (node) => {
2341
2391
  const n = node;
2342
- if (n && syntax.NodeType(n) === "Redirect" && op < 0) op = n.Op;
2392
+ if (n && n.kind === "Redirect" && op < 0) op = n.Op;
2343
2393
  return true;
2344
2394
  });
2345
2395
  return op;
@@ -2352,7 +2402,7 @@ function collectSameCommandCreations(f) {
2352
2402
  try {
2353
2403
  const stmts = Array.isArray(f?.Stmts) ? f.Stmts : [];
2354
2404
  for (const stmt of stmts) {
2355
- if (!stmt || !stmt.Cmd || syntax.NodeType(stmt.Cmd) !== "CallExpr") continue;
2405
+ if (!stmt || !stmt.Cmd || stmt.Cmd.kind !== "CallExpr") continue;
2356
2406
  const redirs = stmt.Redirs || [];
2357
2407
  if (!redirs.some((r) => r && REDIR_HEREDOC_OPS.has(r.Op))) continue;
2358
2408
  for (const r of redirs) {
@@ -2376,10 +2426,10 @@ function isRmCreatedInCommandCleanup(command) {
2376
2426
  let sawRm = false;
2377
2427
  let ok2 = true;
2378
2428
  try {
2379
- syntax.Walk(f, (node) => {
2429
+ walk(f, (node) => {
2380
2430
  if (!node || !ok2) return false;
2381
2431
  const n = node;
2382
- if (syntax.NodeType(n) !== "CallExpr") return true;
2432
+ if (n.kind !== "CallExpr") return true;
2383
2433
  const args = n.Args || [];
2384
2434
  const name = (resolveWordLiteral(args[0]) ?? "").toLowerCase();
2385
2435
  if (name !== "rm") return true;
@@ -2429,10 +2479,10 @@ function analyzeFsOperationImpl(command, depth = 0) {
2429
2479
  walkWithCalls(f, (node) => {
2430
2480
  if (!node || result?.verdict === "block") return false;
2431
2481
  const n = node;
2432
- const nodeType = syntax.NodeType(n);
2482
+ const nodeType = n.kind;
2433
2483
  if (nodeType === "Stmt") {
2434
2484
  try {
2435
- currentStmtOffset = n.Pos().Offset();
2485
+ currentStmtOffset = n.pos;
2436
2486
  } catch {
2437
2487
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2438
2488
  }
@@ -2945,11 +2995,12 @@ function analyzeShellCommand(command) {
2945
2995
  if (lower2.startsWith("-")) allTokens.push(lower2.replace(/^-+/, ""));
2946
2996
  };
2947
2997
  try {
2948
- const f = sharedParser.Parse(command, "cmd");
2949
- syntax.Walk(f, (node) => {
2998
+ const f = parseShared(command);
2999
+ if (f === PARSE_FAIL) throw new Error("parse failed");
3000
+ walk(f, (node) => {
2950
3001
  if (!node) return false;
2951
3002
  const n = node;
2952
- if (syntax.NodeType(n) !== "CallExpr") return true;
3003
+ if (n.kind !== "CallExpr") return true;
2953
3004
  const wordValues2 = (n.Args || []).map((arg) => {
2954
3005
  return (arg.Parts || []).map((p) => (p.Value ?? "").replace(/\\(.)/g, "$1")).join("");
2955
3006
  }).filter((s) => s.length > 0);
@@ -3221,7 +3272,7 @@ function runnablePrefix(command) {
3221
3272
  let text = command;
3222
3273
  for (let attempt = 0; attempt < 32; attempt++) {
3223
3274
  try {
3224
- return syntax2.NewParser().Parse(text, "");
3275
+ return toPlainTree(syntax3.NewParser().Parse(text, ""));
3225
3276
  } catch (error) {
3226
3277
  const message = String(typeof error?.Error === "function" ? error.Error() : error?.message);
3227
3278
  const line = Number(/^(\d+):/.exec(message)?.[1]);
@@ -3289,7 +3340,7 @@ function wordValues(word, state) {
3289
3340
  out2 = next.slice(0, MAX_ALTERNATIVES);
3290
3341
  };
3291
3342
  for (const node of nodes) {
3292
- const kind = syntax2.NodeType(node);
3343
+ const kind = node.kind;
3293
3344
  let pieces;
3294
3345
  if (kind === "ParamExp") pieces = paramValues(node, quoted);
3295
3346
  else if (kind === "DblQuoted") {
@@ -3357,9 +3408,9 @@ function collectShellFileAccesses(command, context = {}) {
3357
3408
  }
3358
3409
  function substitutions2(word, state, depth) {
3359
3410
  if (!word) return;
3360
- syntax2.Walk(word, (node) => {
3411
+ walk(word, (node) => {
3361
3412
  if (!node) return false;
3362
- if (["CmdSubst", "ProcSubst"].includes(syntax2.NodeType(node))) {
3413
+ if (["CmdSubst", "ProcSubst"].includes(node.kind)) {
3363
3414
  statements(node.Stmts ?? [], clone(state), depth + 1);
3364
3415
  return false;
3365
3416
  }
@@ -3783,7 +3834,7 @@ function collectShellFileAccesses(command, context = {}) {
3783
3834
  }
3784
3835
  function readsScriptFromStdin(stmt) {
3785
3836
  const cmd = stmt?.Cmd;
3786
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return false;
3837
+ if (!cmd || cmd.kind !== "CallExpr") return false;
3787
3838
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3788
3839
  const head = unwrapCommandHead(words);
3789
3840
  return SHELL_INTERPRETERS.has(base(words[head])) && shellConsumesPipe(words.slice(head + 1));
@@ -3797,7 +3848,7 @@ function collectShellFileAccesses(command, context = {}) {
3797
3848
  }
3798
3849
  function producedText(stmt) {
3799
3850
  const cmd = stmt?.Cmd;
3800
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return null;
3851
+ if (!cmd || cmd.kind !== "CallExpr") return null;
3801
3852
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3802
3853
  if (words.some((w) => w === null)) return null;
3803
3854
  const head = unwrapCommandHead(words);
@@ -3816,7 +3867,7 @@ function collectShellFileAccesses(command, context = {}) {
3816
3867
  if (!stmt || depth > MAX_DEPTH) return;
3817
3868
  state.onSuccess = void 0;
3818
3869
  if (stmt.Background) state = clone(state);
3819
- const headWord = stmt.Cmd && syntax2.NodeType(stmt.Cmd) === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3870
+ const headWord = stmt.Cmd && stmt.Cmd.kind === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3820
3871
  const sends = SENDING_STDIN.has(headWord);
3821
3872
  for (const redir of stmt.Redirs ?? []) {
3822
3873
  substitutions2(redir.Word, state, depth);
@@ -3832,7 +3883,7 @@ function collectShellFileAccesses(command, context = {}) {
3832
3883
  const cmd = stmt.Cmd;
3833
3884
  if (!cmd) return;
3834
3885
  stdinScript(stmt, state, depth);
3835
- switch (syntax2.NodeType(cmd)) {
3886
+ switch (cmd.kind) {
3836
3887
  case "CallExpr":
3837
3888
  call(cmd, state, depth);
3838
3889
  break;
@@ -3846,7 +3897,7 @@ function collectShellFileAccesses(command, context = {}) {
3846
3897
  for (; ; ) {
3847
3898
  segments2.unshift({ op: node.Op, part: node.Y });
3848
3899
  const left = node.X;
3849
- if (left?.Cmd && syntax2.NodeType(left.Cmd) === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3900
+ if (left?.Cmd && left.Cmd.kind === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3850
3901
  node = left.Cmd;
3851
3902
  else {
3852
3903
  segments2.unshift({ op: node.Op, part: left });
@@ -4142,13 +4193,13 @@ function pipelineTexts(command) {
4142
4193
  const visit2 = (stmt, depth) => {
4143
4194
  if (!stmt || depth > 64) return;
4144
4195
  const cmd = stmt.Cmd;
4145
- if (cmd && syntax3.NodeType(cmd) === "BinaryCmd" && SEQUENCE_OPS.has(cmd.Op)) {
4196
+ if (cmd && cmd.kind === "BinaryCmd" && SEQUENCE_OPS.has(cmd.Op)) {
4146
4197
  visit2(cmd.X, depth + 1);
4147
4198
  visit2(cmd.Y, depth + 1);
4148
4199
  return;
4149
4200
  }
4150
- const s = at(stmt.Pos().Offset());
4151
- const e = at(stmt.End().Offset());
4201
+ const s = at(stmt.pos);
4202
+ const e = at(stmt.end);
4152
4203
  const text = s >= 0 && e > s ? command.slice(s, e).replace(/[\s;&]+$/, "") : "";
4153
4204
  if (text) out.push(text);
4154
4205
  };
@@ -5310,11 +5361,10 @@ function shellWriteUnseen(command, target) {
5310
5361
  let unseen = false;
5311
5362
  let seen = false;
5312
5363
  try {
5313
- syntax4.Walk(f, (node) => {
5364
+ walk(f, (node) => {
5314
5365
  if (!node || unseen) return false;
5315
5366
  const n = node;
5316
- if (syntax4.NodeType(n) !== "Stmt" || !n.Cmd || syntax4.NodeType(n.Cmd) !== "CallExpr")
5317
- return true;
5367
+ if (n.kind !== "Stmt" || !n.Cmd || n.Cmd.kind !== "CallExpr") return true;
5318
5368
  const words = (n.Cmd.Args || []).map(
5319
5369
  (a) => resolveWordLiteral(a)
5320
5370
  );
@@ -5369,14 +5419,14 @@ function analyzeGitImpl(command) {
5369
5419
  seen.add(key);
5370
5420
  findings.push(f);
5371
5421
  };
5372
- const walk2 = new GitWalk((inv) => classify(inv).forEach(found), found);
5373
- const parsed = walk2.run(command, 0);
5422
+ const walk3 = new GitWalk((inv) => classify(inv).forEach(found), found);
5423
+ const parsed = walk3.run(command, 0);
5374
5424
  return { parsed, findings };
5375
5425
  }
5376
5426
  function isPositionalParam(word) {
5377
5427
  let parts = word?.Parts || [];
5378
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
5379
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return false;
5428
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
5429
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return false;
5380
5430
  return /^(\d+|@|\*)$/.test(parts[0].Param?.Value ?? "");
5381
5431
  }
5382
5432
  function boundPositionals() {
@@ -5390,11 +5440,11 @@ function boundPositionals() {
5390
5440
  function plainParamName(word) {
5391
5441
  let parts = word?.Parts || [];
5392
5442
  let quoted = false;
5393
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") {
5443
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") {
5394
5444
  parts = parts[0].Parts || [];
5395
5445
  quoted = true;
5396
5446
  }
5397
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return null;
5447
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
5398
5448
  const p = parts[0];
5399
5449
  if (p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp) return null;
5400
5450
  const name = p.Param?.Value;
@@ -5419,7 +5469,7 @@ function resolveGitWords(word) {
5419
5469
  }
5420
5470
  const parts = word?.Parts || [];
5421
5471
  const expansion = parts.some((p) => {
5422
- const t = syntax5.NodeType(p);
5472
+ const t = p.kind;
5423
5473
  return t === "ParamExp" || t === "CmdSubst";
5424
5474
  });
5425
5475
  return expansion ? splitFields(value) : [value];
@@ -5820,14 +5870,14 @@ function hookCommands(text) {
5820
5870
  const root = parsed?.hooks;
5821
5871
  if (!root || typeof root !== "object") return null;
5822
5872
  const out = [];
5823
- const walk2 = (v, depth) => {
5873
+ const walk3 = (v, depth) => {
5824
5874
  if (depth > 8 || !v || typeof v !== "object") return;
5825
5875
  for (const [k, x] of Object.entries(v)) {
5826
5876
  if (k === "command" && typeof x === "string") out.push(x);
5827
- else walk2(x, depth + 1);
5877
+ else walk3(x, depth + 1);
5828
5878
  }
5829
5879
  };
5830
- walk2(root, 0);
5880
+ walk3(root, 0);
5831
5881
  return out;
5832
5882
  }
5833
5883
  function hooksDisarmed(text) {
@@ -5994,9 +6044,9 @@ function isDupInOp(op) {
5994
6044
  if (dupInOp === null) {
5995
6045
  let found = -1;
5996
6046
  try {
5997
- syntax6.Walk(parseShared("cat <&3"), (node) => {
6047
+ walk(parseShared("cat <&3"), (node) => {
5998
6048
  const n = node;
5999
- if (found === -1 && n && syntax6.NodeType(n) === "Stmt" && n.Redirs?.[0]) {
6049
+ if (found === -1 && n && n.kind === "Stmt" && n.Redirs?.[0]) {
6000
6050
  found = n.Redirs[0].Op;
6001
6051
  }
6002
6052
  return true;
@@ -6017,10 +6067,10 @@ function analyzeOutbound(command) {
6017
6067
  return hit;
6018
6068
  }
6019
6069
  const findings = [];
6020
- const walk2 = new OutboundWalk(findings);
6021
- const parsed = walk2.run(command, 0);
6070
+ const walk3 = new OutboundWalk(findings);
6071
+ const parsed = walk3.run(command, 0);
6022
6072
  const envOut = findings.find((f) => f.checkId === "data.env-exfil");
6023
- if (envOut) envOut.destinations = walk2.envDestinations();
6073
+ if (envOut) envOut.destinations = walk3.envDestinations();
6024
6074
  const computed = { parsed, findings };
6025
6075
  if (cache2.size >= CACHE_MAX2) {
6026
6076
  const oldest = cache2.keys().next().value;
@@ -6036,7 +6086,7 @@ function wordShape(word) {
6036
6086
  const parts = word?.Parts || [];
6037
6087
  let out = "";
6038
6088
  for (const p of parts) {
6039
- const t = syntax6.NodeType(p);
6089
+ const t = p.kind;
6040
6090
  if (t === "Lit" || t === "SglQuoted") out += p.Value ?? "";
6041
6091
  else if (t === "DblQuoted") out += wordShape(p);
6042
6092
  else out += "X";
@@ -6171,16 +6221,16 @@ function declDumpsEnv(decl) {
6171
6221
  }
6172
6222
  function paramName(word) {
6173
6223
  let parts = word?.Parts || [];
6174
- if (parts.length === 1 && syntax6.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
6175
- if (parts.length !== 1 || syntax6.NodeType(parts[0]) !== "ParamExp") return null;
6224
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
6225
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
6176
6226
  return parts[0].Param?.Value ?? null;
6177
6227
  }
6178
6228
  function refersTo(word, names) {
6179
6229
  let hit = false;
6180
- syntax6.Walk(word, (node) => {
6230
+ walk(word, (node) => {
6181
6231
  if (hit || !node) return false;
6182
6232
  const n = node;
6183
- if (syntax6.NodeType(n) === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6233
+ if (n.kind === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6184
6234
  return !hit;
6185
6235
  });
6186
6236
  return hit;
@@ -6188,10 +6238,10 @@ function refersTo(word, names) {
6188
6238
  function runsCommandsIn(stmt) {
6189
6239
  const readVars = /* @__PURE__ */ new Set();
6190
6240
  let hit = false;
6191
- syntax6.Walk(stmt, (node) => {
6241
+ walk(stmt, (node) => {
6192
6242
  if (hit || !node) return false;
6193
6243
  const n = node;
6194
- if (syntax6.NodeType(n) !== "CallExpr") return true;
6244
+ if (n.kind !== "CallExpr") return true;
6195
6245
  const words = wordsOf(n);
6196
6246
  if (words.length === 0) return true;
6197
6247
  const { head, at } = headOf(words);
@@ -6768,7 +6818,7 @@ function localContexts(file2) {
6768
6818
  if (depth > 64) return null;
6769
6819
  if (!stmt || stmt.Background || stmt.Negated || stmt.Redirs?.length) return null;
6770
6820
  const cmd = stmt.Cmd;
6771
- const kind = syntax7.NodeType(cmd);
6821
+ const kind = cmd.kind;
6772
6822
  if (kind === "BinaryCmd" && cmd.Op === andOp) {
6773
6823
  const next = visit2(cmd.X, steps, depth + 1);
6774
6824
  return next === null ? null : visit2(cmd.Y, next, depth + 1);
@@ -6784,7 +6834,7 @@ function localContexts(file2) {
6784
6834
  )
6785
6835
  ))
6786
6836
  return null;
6787
- contexts.set(cmd.Pos().Offset(), steps);
6837
+ contexts.set(cmd.pos, steps);
6788
6838
  return null;
6789
6839
  }
6790
6840
  if (file2.Stmts?.length === 1) visit2(file2.Stmts[0], []);
@@ -6795,12 +6845,12 @@ function collect(command, out, depth) {
6795
6845
  const f = parseShared(command);
6796
6846
  if (typeof f === "symbol") return;
6797
6847
  const contexts = depth === 0 ? localContexts(f) : /* @__PURE__ */ new Map();
6798
- syntax7.Walk(f, (node) => {
6799
- if (node && syntax7.NodeType(node) === "CallExpr") {
6848
+ walk(f, (node) => {
6849
+ if (node && node.kind === "CallExpr") {
6800
6850
  const words = (node.Args || []).map((a) => resolveWordLiteral(a));
6801
6851
  const start = out.length;
6802
6852
  if (words.length > 0) fromCall(words, out, depth);
6803
- const steps = contexts.get(node.Pos().Offset());
6853
+ const steps = contexts.get(node.pos);
6804
6854
  for (let i = start; i < out.length; i++) {
6805
6855
  if (["npx", "bunx", "npm exec"].includes(out[i].manager)) {
6806
6856
  if (!steps) out[i].localCwd = null;
@@ -6847,7 +6897,7 @@ function collect2(command, out, depth) {
6847
6897
  try {
6848
6898
  walkCommandScope(command, (node) => {
6849
6899
  const n = node;
6850
- if (!n || syntax8.NodeType(n) !== "CallExpr") return true;
6900
+ if (!n || n.kind !== "CallExpr") return true;
6851
6901
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
6852
6902
  if (words.length === 0) return true;
6853
6903
  const prefix = (n.Assigns || []).filter((a) => a?.Name?.Value).map(
@@ -8277,12 +8327,12 @@ function extractContentDestinations(text) {
8277
8327
  function extractArgDestinations(args) {
8278
8328
  const out = /* @__PURE__ */ new Set();
8279
8329
  try {
8280
- walk(args, void 0, out, 0);
8330
+ walk2(args, void 0, out, 0);
8281
8331
  } catch {
8282
8332
  }
8283
8333
  return [...out];
8284
8334
  }
8285
- function walk(value, key, out, depth) {
8335
+ function walk2(value, key, out, depth) {
8286
8336
  if (out.size >= MAX_DESTINATIONS || depth > 12) return;
8287
8337
  if (typeof value === "string") {
8288
8338
  const s = value.length > MAX_SCAN_CHARS ? value.slice(0, MAX_SCAN_CHARS) : value;
@@ -8301,12 +8351,12 @@ function walk(value, key, out, depth) {
8301
8351
  return;
8302
8352
  }
8303
8353
  if (Array.isArray(value)) {
8304
- for (const v of value) walk(v, key, out, depth + 1);
8354
+ for (const v of value) walk2(v, key, out, depth + 1);
8305
8355
  return;
8306
8356
  }
8307
8357
  if (value && typeof value === "object") {
8308
8358
  for (const [k, v] of Object.entries(value))
8309
- walk(v, k, out, depth + 1);
8359
+ walk2(v, k, out, depth + 1);
8310
8360
  }
8311
8361
  }
8312
8362
  function destinationDomain(dest) {
@@ -8958,9 +9008,9 @@ function classifyCall(head, args, prefixes2, env, state, out) {
8958
9008
  function walkCalls(command, out, depth, state) {
8959
9009
  const f = parseShared(command);
8960
9010
  if (typeof f === "symbol" || !f) return;
8961
- syntax9.Walk(f, (node) => {
9011
+ walk(f, (node) => {
8962
9012
  if (!node) return false;
8963
- const type = syntax9.NodeType(node);
9013
+ const type = node.kind;
8964
9014
  if (type === "DeclClause") {
8965
9015
  for (const a of node.Args || []) if (a?.Name?.Value) state.env.add(a.Name.Value);
8966
9016
  return true;
@@ -9364,7 +9414,7 @@ function matchCanaryArgs(args, values) {
9364
9414
  if (values.length === 0) return null;
9365
9415
  const needles = prepare(values);
9366
9416
  if (needles.length === 0) return null;
9367
- const walk2 = (v, depth, fieldPath) => {
9417
+ const walk3 = (v, depth, fieldPath) => {
9368
9418
  if (depth > MAX_DEPTH4) return null;
9369
9419
  if (typeof v === "string") {
9370
9420
  const hit = matchPrepared(v, needles);
@@ -9373,31 +9423,31 @@ function matchCanaryArgs(args, values) {
9373
9423
  const trimmed = v.trim();
9374
9424
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
9375
9425
  try {
9376
- return walk2(JSON.parse(v), depth + 1, fieldPath);
9426
+ return walk3(JSON.parse(v), depth + 1, fieldPath);
9377
9427
  } catch {
9378
9428
  }
9379
9429
  }
9380
9430
  }
9381
9431
  return null;
9382
9432
  }
9383
- if (typeof v === "number" && Number.isFinite(v)) return walk2(String(v), depth, fieldPath);
9433
+ if (typeof v === "number" && Number.isFinite(v)) return walk3(String(v), depth, fieldPath);
9384
9434
  if (Array.isArray(v)) {
9385
9435
  for (let i = 0; i < v.length; i++) {
9386
- const h = walk2(v[i], depth + 1, `${fieldPath}[${i}]`);
9436
+ const h = walk3(v[i], depth + 1, `${fieldPath}[${i}]`);
9387
9437
  if (h) return h;
9388
9438
  }
9389
9439
  return null;
9390
9440
  }
9391
9441
  if (v && typeof v === "object") {
9392
9442
  for (const [k, child] of Object.entries(v)) {
9393
- const h = walk2(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
9443
+ const h = walk3(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
9394
9444
  if (h) return h;
9395
9445
  }
9396
9446
  }
9397
9447
  return null;
9398
9448
  };
9399
9449
  try {
9400
- return walk2(args, 0, "");
9450
+ return walk3(args, 0, "");
9401
9451
  } catch (e) {
9402
9452
  console.error(
9403
9453
  "[node9 engine] canary args walk failed:",
@@ -9830,7 +9880,7 @@ function* stringLeavesWithKeys(obj, depth = 0, key) {
9830
9880
  }
9831
9881
  for (const [k, v] of Object.entries(obj)) yield* stringLeavesWithKeys(v, depth + 1, k);
9832
9882
  }
9833
- var 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, REPLACED_SHIELDS, 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, VERDICTS, CHECK_VERDICT_RANK, CHECK_GROUPS, 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, 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_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, syntax, 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, VARIABLE_READERS, 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, AND_OP, OR_OP, AND_OR_OPS, MAX_CALL_DEPTH, MAX_CALL_WALKS, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax2, MAX_ALTERNATIVES, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, 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, WRITES, APPENDS, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, exempt, RANK, syntax3, 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, DLP_SCAN_LIMITS, BATCH_SEPARATOR, ENCODED_RUN_RE, IMPERATIVE, SECRET_TARGET, GUARD, SIGNALS, DESTINATION_RE, REUSED_SIGNALS, NEVER_NEGATED, NEGATION_BEFORE, syntax4, RDR_IN, COPY_VERBS2, LITERAL_VERBS, syntax5, 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, FORCE_PUSH, DESTRUCTIVE, UNREADABLE, PUSH_LONG_VALUE, BRANCH_LONG_VALUE, TAG_LONG_VALUE, CLEAN_LONG_VALUE, HOOKS_BYPASS, NO_VERIFY_SUBS, HOOK_KILL_SWITCHES, COMMIT_LONG_VALUE, CHMOD_OPTION_RE, STAGE_ALL, ADD_LONG_VALUE, CHECK_ID, RULE_NAME, INERT_LINE_RE, CHECK_ID2, INSTRUCTION_NAMES, SETTINGS_RE, HOOK_WORDS_RE, syntax6, 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, syntax7, 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, syntax8, 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, syntax9, 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, CONTROL_CHAR_RE, SHIELD_RULE, ACTION_RULE, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, MAX_BLAST_PATH, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, 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, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, ENGINE_VERSION;
9883
+ var 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, REPLACED_SHIELDS, 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, VERDICTS, CHECK_VERDICT_RANK, CHECK_GROUPS, 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_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, syntax2, 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, VARIABLE_READERS, 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, AND_OP, OR_OP, AND_OR_OPS, MAX_CALL_DEPTH, MAX_CALL_WALKS, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax3, MAX_ALTERNATIVES, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, 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, WRITES, APPENDS, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, 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, DLP_SCAN_LIMITS, BATCH_SEPARATOR, ENCODED_RUN_RE, 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, FORCE_PUSH, DESTRUCTIVE, UNREADABLE, PUSH_LONG_VALUE, BRANCH_LONG_VALUE, TAG_LONG_VALUE, CLEAN_LONG_VALUE, HOOKS_BYPASS, NO_VERIFY_SUBS, HOOK_KILL_SWITCHES, COMMIT_LONG_VALUE, CHMOD_OPTION_RE, 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, CONTROL_CHAR_RE, SHIELD_RULE, ACTION_RULE, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, MAX_BLAST_PATH, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, 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, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, ENGINE_VERSION;
9834
9884
  var init_dist = __esm({
9835
9885
  "packages/policy-engine/dist/index.mjs"() {
9836
9886
  "use strict";
@@ -12494,6 +12544,61 @@ var init_dist = __esm({
12494
12544
  return s.untrustedContent.afterExposure === "log-only" ? "log" : "review";
12495
12545
  }
12496
12546
  };
12547
+ ({ syntax } = mvdanSh);
12548
+ KINDS = {
12549
+ File: { nodes: ["Stmts"] },
12550
+ Stmt: { nodes: ["Cmd", "Redirs"], scalars: ["Negated", "Background", "Coprocess"] },
12551
+ CallExpr: { nodes: ["Assigns", "Args"] },
12552
+ Assign: { nodes: ["Name", "Value", "Index", "Array"], scalars: ["Append", "Naked"] },
12553
+ Word: { nodes: ["Parts"] },
12554
+ Lit: { scalars: ["Value"] },
12555
+ SglQuoted: { scalars: ["Value", "Dollar"] },
12556
+ DblQuoted: { nodes: ["Parts"], scalars: ["Dollar"] },
12557
+ ParamExp: {
12558
+ nodes: ["Param", "Index", "Slice", "Repl", "Exp"],
12559
+ scalars: ["Short", "Excl", "Length", "Width"]
12560
+ },
12561
+ CmdSubst: { nodes: ["Stmts"], scalars: ["Backquotes", "TempFile", "ReplyVar"] },
12562
+ ArithmExp: { nodes: ["X"], scalars: ["Bracket", "Unsigned"] },
12563
+ ArithmCmd: { nodes: ["X"], scalars: ["Unsigned"] },
12564
+ ProcSubst: { nodes: ["Stmts"], scalars: ["Op"] },
12565
+ ExtGlob: { nodes: ["Pattern"], scalars: ["Op"] },
12566
+ BraceExp: { nodes: ["Elems"], scalars: ["Sequence"] },
12567
+ // only with SplitBraces, unused here
12568
+ BinaryCmd: { nodes: ["X", "Y"], scalars: ["Op"] },
12569
+ BinaryArithm: { nodes: ["X", "Y"], scalars: ["Op"] },
12570
+ UnaryArithm: { nodes: ["X"], scalars: ["Op", "Post"] },
12571
+ ParenArithm: { nodes: ["X"] },
12572
+ BinaryTest: { nodes: ["X", "Y"], scalars: ["Op"] },
12573
+ UnaryTest: { nodes: ["X"], scalars: ["Op"] },
12574
+ ParenTest: { nodes: ["X"] },
12575
+ Redirect: { nodes: ["N", "Word", "Hdoc"], scalars: ["Op"] },
12576
+ Block: { nodes: ["Stmts"] },
12577
+ Subshell: { nodes: ["Stmts"] },
12578
+ IfClause: { nodes: ["Cond", "Then", "Else"] },
12579
+ WhileClause: { nodes: ["Cond", "Do"], scalars: ["Until"] },
12580
+ ForClause: { nodes: ["Loop", "Do"], scalars: ["Select"] },
12581
+ WordIter: { nodes: ["Name", "Items"] },
12582
+ CStyleLoop: { nodes: ["Init", "Cond", "Post"] },
12583
+ CaseClause: { nodes: ["Word", "Items"] },
12584
+ CaseItem: { nodes: ["Patterns", "Stmts"], scalars: ["Op"] },
12585
+ FuncDecl: { nodes: ["Name", "Body"], scalars: ["RsrvWord"] },
12586
+ DeclClause: { nodes: ["Variant", "Args"], notWalked: ["Variant"] },
12587
+ LetClause: { nodes: ["Exprs"] },
12588
+ TimeClause: { nodes: ["Stmt"], scalars: ["PosixFormat"] },
12589
+ CoprocClause: { nodes: ["Name", "Stmt"] },
12590
+ TestClause: { nodes: ["X"] },
12591
+ TestDecl: { nodes: ["Description", "Body"] },
12592
+ ArrayExpr: { nodes: ["Elems"] },
12593
+ ArrayElem: { nodes: ["Index", "Value"] },
12594
+ Comment: { scalars: ["Text"] }
12595
+ };
12596
+ STRUCTS = {
12597
+ "ParamExp.Slice": { nodes: ["Offset", "Length"], notWalked: ["Offset", "Length"] },
12598
+ "ParamExp.Repl": { nodes: ["Orig", "With"], scalars: ["All"] },
12599
+ "ParamExp.Exp": { nodes: ["Word"], scalars: ["Op"] }
12600
+ };
12601
+ unknownKinds = /* @__PURE__ */ new Set();
12497
12602
  INVISIBLE_RE = /[­͏؜᠎​-‏‪-‮⁠-⁤-︀-️]|[\u{E0000}-\u{E007F}]/gu;
12498
12603
  INVISIBLE_ONE = new RegExp(`^(?:${INVISIBLE_RE.source.split("|")[0]})$`, "u");
12499
12604
  HOMOGLYPHS = {
@@ -12779,8 +12884,8 @@ var init_dist = __esm({
12779
12884
  php: PHP
12780
12885
  };
12781
12886
  STRING_LITERAL = /(['"`])((?:\\.|(?!\1)[^\\\n]){1,4096})\1/g;
12782
- ({ syntax } = mvdanSh);
12783
- sharedParser = syntax.NewParser();
12887
+ ({ syntax: syntax2 } = mvdanSh2);
12888
+ sharedParser = syntax2.NewParser();
12784
12889
  MESSAGE_FLAGS = /* @__PURE__ */ new Set([
12785
12890
  "-m",
12786
12891
  "--message",
@@ -12814,7 +12919,7 @@ var init_dist = __esm({
12814
12919
  NORMALIZE_CACHE_MAX = 5e3;
12815
12920
  normalizeCache = /* @__PURE__ */ new Map();
12816
12921
  codeBodiesCache = /* @__PURE__ */ new Map();
12817
- AST_CACHE_MAX = 5e3;
12922
+ AST_CACHE_MAX = 256;
12818
12923
  astCache = /* @__PURE__ */ new Map();
12819
12924
  PARSE_FAIL = /* @__PURE__ */ Symbol("parse-fail");
12820
12925
  INTERPRETER_LINE = /^#![ \t]*[\w./+-]+(?:[ \t]+[\w./+=:-]+)*[ \t]*\r?(?=\n|$)/;
@@ -13799,7 +13904,7 @@ var init_dist = __esm({
13799
13904
  ARGV_FIELDS = ["args", "argv"];
13800
13905
  BARE_WORD = /^[A-Za-z0-9_./+:@%,-]+$/;
13801
13906
  MAX_ARGV_CHARACTERS = 262144;
13802
- ({ syntax: syntax2 } = mvdanSh2);
13907
+ ({ syntax: syntax3 } = mvdanSh3);
13803
13908
  MAX_ALTERNATIVES = 64;
13804
13909
  MAX_CALL_DEPTH2 = 4;
13805
13910
  MAX_CALL_WALKS2 = 256;
@@ -13891,7 +13996,6 @@ var init_dist = __esm({
13891
13996
  );
13892
13997
  exempt = (p) => SYSTEM_DIRS_EXEMPT.some((d) => within(p, d));
13893
13998
  RANK = { allow: 0, review: 1, block: 2 };
13894
- ({ syntax: syntax3 } = mvdanSh3);
13895
13999
  SEQUENCE_OPS = (() => {
13896
14000
  const ops = /* @__PURE__ */ new Set();
13897
14001
  for (const text of ["x && y", "x || y"]) {
@@ -17060,7 +17164,6 @@ zoo`.split("\n");
17060
17164
  );
17061
17165
  NEVER_NEGATED = /* @__PURE__ */ new Set([SIGNALS[1].any[0]]);
17062
17166
  NEGATION_BEFORE = /\b(never|do not|don'?t|must not|mustn'?t|should not|shouldn'?t|not allowed to|forbidden to|avoid|without|no|not)\b[^.!?;:\n]{0,24}$/i;
17063
- ({ syntax: syntax4 } = mvdanSh4);
17064
17167
  RDR_IN = (() => {
17065
17168
  try {
17066
17169
  return parseShared("x <y").Stmts[0].Redirs[0].Op;
@@ -17089,7 +17192,6 @@ zoo`.split("\n");
17089
17192
  "tar"
17090
17193
  ]);
17091
17194
  LITERAL_VERBS = /* @__PURE__ */ new Set(["echo", "printf", ":", "true", "touch", "sed"]);
17092
- ({ syntax: syntax5 } = mvdanSh5);
17093
17195
  GIT_PRESCREEN_RE = /git|husky/i;
17094
17196
  MAX_PAYLOAD_DEPTH2 = 8;
17095
17197
  MAX_ALIAS_DEPTH = 5;
@@ -17158,7 +17260,7 @@ zoo`.split("\n");
17158
17260
  visit(node, depth) {
17159
17261
  if (!node) return false;
17160
17262
  const n = node;
17161
- const type = syntax5.NodeType(n);
17263
+ const type = n.kind;
17162
17264
  if (type === "Stmt") {
17163
17265
  this.visitHeredocShell(n, depth);
17164
17266
  return true;
@@ -17166,7 +17268,7 @@ zoo`.split("\n");
17166
17268
  if (type === "ForClause") {
17167
17269
  const loop = n.Loop;
17168
17270
  const name = loop?.Name?.Value;
17169
- if (name && syntax5.NodeType(loop) === "WordIter") {
17271
+ if (name && loop.kind === "WordIter") {
17170
17272
  const items = (loop.Items || []).map((w) => resolveWordLiteral(w));
17171
17273
  const literal = items.length > 0 && items.every((v) => v !== null);
17172
17274
  this.loopVars.set(name, literal ? items.slice(0, MAX_LOOP_ITEMS) : null);
@@ -17233,7 +17335,7 @@ zoo`.split("\n");
17233
17335
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
17234
17336
  visitHeredocShell(stmt, depth) {
17235
17337
  const cmd = stmt.Cmd;
17236
- if (!cmd || syntax5.NodeType(cmd) !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
17338
+ if (!cmd || cmd.kind !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
17237
17339
  const redirs = stmt.Redirs || [];
17238
17340
  const hdoc = redirs.find((r) => r?.Hdoc && (r.N == null || r.N.Value === "0"));
17239
17341
  if (!hdoc) return;
@@ -17487,7 +17589,6 @@ zoo`.split("\n");
17487
17589
  ]);
17488
17590
  SETTINGS_RE = /\/(?:\.claude\/settings(?:\.local)?\.json|\.gemini\/settings\.json|\.codex\/hooks\.json|\.cursor\/hooks\.json)$/i;
17489
17591
  HOOK_WORDS_RE = /"hooks"|\b(PreToolUse|PostToolUse|UserPromptSubmit|Notification|Stop|SubagentStop|SessionStart|SessionEnd|PreCompact|BeforeTool|AfterTool)\b|"command"\s*:/;
17490
- ({ syntax: syntax6 } = mvdanSh6);
17491
17592
  SHELLS = /* @__PURE__ */ new Set([...SHELL_INTERPRETERS, "mksh", "ash", "csh", "tcsh"]);
17492
17593
  NETCATS = /* @__PURE__ */ new Set(["nc", "ncat", "netcat", "nc.traditional", "nc.openbsd"]);
17493
17594
  NET_CLIENTS = /* @__PURE__ */ new Set([...NETCATS, "telnet", "socat"]);
@@ -17545,7 +17646,7 @@ zoo`.split("\n");
17545
17646
  const f = parseShared(command);
17546
17647
  if (!f || typeof f !== "object" || !f.Stmts) return false;
17547
17648
  try {
17548
- syntax6.Walk(f, (node) => this.visit(node, depth));
17649
+ walk(f, (node) => this.visit(node, depth));
17549
17650
  } catch {
17550
17651
  return false;
17551
17652
  }
@@ -17584,7 +17685,7 @@ zoo`.split("\n");
17584
17685
  }
17585
17686
  visit(n, depth) {
17586
17687
  if (!n) return false;
17587
- const type = syntax6.NodeType(n);
17688
+ const type = n.kind;
17588
17689
  if (type === "Stmt") {
17589
17690
  this.visitStmt(n, depth);
17590
17691
  return true;
@@ -17604,7 +17705,7 @@ zoo`.split("\n");
17604
17705
  const redirs = redirectWords(stmt);
17605
17706
  const toSocket = redirs.some((w) => w !== null && DEV_NET_RE.test(w));
17606
17707
  if (!cmd) return;
17607
- const type = syntax6.NodeType(cmd);
17708
+ const type = cmd.kind;
17608
17709
  if (type !== "CallExpr" || wordsOf(cmd).length > 0) {
17609
17710
  if (this.readsNetFd(stmt) && runsCommandsIn(stmt)) {
17610
17711
  this.reverseShell("commands are read from a network socket opened with exec");
@@ -17690,7 +17791,7 @@ zoo`.split("\n");
17690
17791
  const stages = [];
17691
17792
  const flatten = (s) => {
17692
17793
  const c = s?.Cmd;
17693
- if (c && syntax6.NodeType(c) === "BinaryCmd" && isPipeOp(c.Op)) {
17794
+ if (c && c.kind === "BinaryCmd" && isPipeOp(c.Op)) {
17694
17795
  flatten(c.X);
17695
17796
  flatten(c.Y);
17696
17797
  } else stages.push(s);
@@ -17712,8 +17813,8 @@ zoo`.split("\n");
17712
17813
  sinks.set(i, socketHosts(st));
17713
17814
  }
17714
17815
  if (!c) return;
17715
- if (syntax6.NodeType(c) === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
17716
- if (syntax6.NodeType(c) !== "CallExpr") {
17816
+ if (c.kind === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
17817
+ if (c.kind !== "CallExpr") {
17717
17818
  if (runsCommandsIn(st)) shell = i;
17718
17819
  return;
17719
17820
  }
@@ -17754,10 +17855,10 @@ zoo`.split("\n");
17754
17855
  /** A word (or assignment value) whose text includes an env dump's output. */
17755
17856
  carriesEnv(word) {
17756
17857
  let hit = false;
17757
- syntax6.Walk(word, (node) => {
17858
+ walk(word, (node) => {
17758
17859
  if (hit || !node) return false;
17759
17860
  const n = node;
17760
- const t = syntax6.NodeType(n);
17861
+ const t = n.kind;
17761
17862
  if (t === "ParamExp" && n.Param?.Value && this.envVars.has(n.Param.Value)) {
17762
17863
  hit = true;
17763
17864
  return false;
@@ -17774,11 +17875,11 @@ zoo`.split("\n");
17774
17875
  stmtsDumpEnv(stmts) {
17775
17876
  let hit = false;
17776
17877
  for (const s of stmts) {
17777
- syntax6.Walk(s, (node) => {
17878
+ walk(s, (node) => {
17778
17879
  if (hit || !node) return false;
17779
17880
  const n = node;
17780
- const t = syntax6.NodeType(n);
17781
- if (t === "Stmt" && n.Cmd && syntax6.NodeType(n.Cmd) === "CallExpr") {
17881
+ const t = n.kind;
17882
+ if (t === "Stmt" && n.Cmd && n.Cmd.kind === "CallExpr") {
17782
17883
  const words = wordsOf(n.Cmd);
17783
17884
  if (words.length > 0 && dumpsEnv(words, n)) hit = true;
17784
17885
  }
@@ -17795,7 +17896,6 @@ zoo`.split("\n");
17795
17896
  this.run(payload, depth + 1);
17796
17897
  }
17797
17898
  };
17798
- ({ syntax: syntax7 } = mvdanSh7);
17799
17899
  NPM_INSTALL_VERBS = /* @__PURE__ */ new Set([
17800
17900
  "install",
17801
17901
  "i",
@@ -18177,7 +18277,6 @@ zoo`.split("\n");
18177
18277
  SHELLS2 = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "ksh", "ash"]);
18178
18278
  MAX_NESTING = 3;
18179
18279
  SHELL_VALUE_FLAGS = /* @__PURE__ */ new Set(["--rcfile", "--init-file", "-O", "+O", "-o", "+o"]);
18180
- ({ syntax: syntax8 } = mvdanSh8);
18181
18280
  NPM_FAMILY = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "npx", "pnpx", "bunx"]);
18182
18281
  PIP_FAMILY = /* @__PURE__ */ new Set(["pip", "pip3", "uv", "uvx", "pipx", "pipenv"]);
18183
18282
  NPM_FETCH_VERBS = /* @__PURE__ */ new Set([
@@ -18709,7 +18808,6 @@ zoo`.split("\n");
18709
18808
  ACCOUNT_KEY_RE = /("(?:iban|account|account_number|accountNumber)"\s*:\s*")([A-Za-z0-9 .-]{6,40})(")/g;
18710
18809
  ACCOUNT_VALUE_RE = /"([A-Z]{2}\d{2}[A-Z0-9]{11,30})"/g;
18711
18810
  MAX_MASK_DEPTH = 64;
18712
- ({ syntax: syntax9 } = mvdanSh9);
18713
18811
  EMPTY = {
18714
18812
  fetches: false,
18715
18813
  sends: false,
@@ -33770,18 +33868,18 @@ function statAndFirstLine(file2) {
33770
33868
  }
33771
33869
  function listCodexSessionFiles(base2 = codexSessionsDir()) {
33772
33870
  const files = [];
33773
- const walk2 = (dir2) => {
33871
+ const walk3 = (dir2) => {
33774
33872
  try {
33775
33873
  for (const entry of fs46.readdirSync(dir2, { withFileTypes: true })) {
33776
33874
  const file2 = path47.join(dir2, entry.name);
33777
- if (entry.isDirectory()) walk2(file2);
33875
+ if (entry.isDirectory()) walk3(file2);
33778
33876
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) files.push(file2);
33779
33877
  }
33780
33878
  } catch {
33781
33879
  }
33782
33880
  };
33783
- walk2(base2);
33784
- if (path47.basename(base2) === "sessions") walk2(path47.join(path47.dirname(base2), "archived_sessions"));
33881
+ walk3(base2);
33882
+ if (path47.basename(base2) === "sessions") walk3(path47.join(path47.dirname(base2), "archived_sessions"));
33785
33883
  const sessions = /* @__PURE__ */ new Map();
33786
33884
  for (const file2 of files.sort()) {
33787
33885
  try {
@@ -34271,7 +34369,7 @@ import * as fs49 from "fs";
34271
34369
  import * as path50 from "path";
34272
34370
  function listSessionFiles(dir2, maxDepth = 6) {
34273
34371
  const out = [];
34274
- const walk2 = (d, rel, depth) => {
34372
+ const walk3 = (d, rel, depth) => {
34275
34373
  if (depth > maxDepth) return;
34276
34374
  let entries;
34277
34375
  try {
@@ -34281,11 +34379,11 @@ function listSessionFiles(dir2, maxDepth = 6) {
34281
34379
  }
34282
34380
  for (const e of entries) {
34283
34381
  const childRel = rel ? path50.join(rel, e.name) : e.name;
34284
- if (e.isDirectory()) walk2(path50.join(d, e.name), childRel, depth + 1);
34382
+ if (e.isDirectory()) walk3(path50.join(d, e.name), childRel, depth + 1);
34285
34383
  else if (e.name.endsWith(".jsonl")) out.push(childRel);
34286
34384
  }
34287
34385
  };
34288
- walk2(dir2, "", 0);
34386
+ walk3(dir2, "", 0);
34289
34387
  return out;
34290
34388
  }
34291
34389
  function sessionIdOf(relPath) {
@@ -37586,19 +37684,19 @@ function scrubDecoys(subject, values) {
37586
37684
  for (const v of values) if (v) out = out.split(v).join("[node9-decoy]");
37587
37685
  return out;
37588
37686
  };
37589
- const walk2 = (v, depth) => {
37687
+ const walk3 = (v, depth) => {
37590
37688
  if (depth > 6) return v;
37591
37689
  if (typeof v === "string") return scrubText(v);
37592
- if (Array.isArray(v)) return v.map((x) => walk2(x, depth + 1));
37690
+ if (Array.isArray(v)) return v.map((x) => walk3(x, depth + 1));
37593
37691
  if (v && typeof v === "object") {
37594
37692
  const out = {};
37595
37693
  for (const [k, child] of Object.entries(v))
37596
- out[k] = walk2(child, depth + 1);
37694
+ out[k] = walk3(child, depth + 1);
37597
37695
  return out;
37598
37696
  }
37599
37697
  return v;
37600
37698
  };
37601
- return walk2(subject, 0);
37699
+ return walk3(subject, 0);
37602
37700
  }
37603
37701
  function isStaleFinding(timestamp2, now = Date.now()) {
37604
37702
  if (!timestamp2) return false;
@@ -75050,14 +75148,14 @@ function collectToolOutputText(toolResponse, opts = {}) {
75050
75148
  size += s.length + 1;
75051
75149
  return true;
75052
75150
  };
75053
- const walk2 = (v, depth) => {
75151
+ const walk3 = (v, depth) => {
75054
75152
  if (typeof v === "string") return push3(v);
75055
75153
  if (depth >= MAX_DEPTH5 || v === null || typeof v !== "object") return true;
75056
75154
  const children = Array.isArray(v) ? v : Object.values(v);
75057
- for (const child of children) if (!walk2(child, depth + 1)) return false;
75155
+ for (const child of children) if (!walk3(child, depth + 1)) return false;
75058
75156
  return true;
75059
75157
  };
75060
- walk2(toolResponse, 0);
75158
+ walk3(toolResponse, 0);
75061
75159
  return { text: parts.join("\n"), truncated, fields };
75062
75160
  }
75063
75161
  function shellOutputText(toolResponse) {
@@ -75070,15 +75168,15 @@ function shellOutputText(toolResponse) {
75070
75168
  return collectToolOutputText(toolResponse).text;
75071
75169
  }
75072
75170
  function mapToolOutputStrings(toolResponse, fn) {
75073
- const walk2 = (v, depth) => {
75171
+ const walk3 = (v, depth) => {
75074
75172
  if (typeof v === "string") return fn(v);
75075
75173
  if (depth >= MAX_DEPTH5 || v === null || typeof v !== "object") return v;
75076
- if (Array.isArray(v)) return v.map((x) => walk2(x, depth + 1));
75174
+ if (Array.isArray(v)) return v.map((x) => walk3(x, depth + 1));
75077
75175
  const out = {};
75078
- for (const [k, x] of Object.entries(v)) out[k] = walk2(x, depth + 1);
75176
+ for (const [k, x] of Object.entries(v)) out[k] = walk3(x, depth + 1);
75079
75177
  return out;
75080
75178
  };
75081
- return walk2(toolResponse, 0);
75179
+ return walk3(toolResponse, 0);
75082
75180
  }
75083
75181
  function frameToolOutputLeaves(toolResponse, isSuspect, frame, neutralize) {
75084
75182
  const suspect = [];