@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/index.mjs CHANGED
@@ -64,22 +64,16 @@ var init_forecast_context = __esm({
64
64
  });
65
65
 
66
66
  // packages/policy-engine/dist/index.mjs
67
- import mvdanSh3 from "mvdan-sh";
68
67
  import picomatch from "picomatch";
69
68
  import safeRegex from "safe-regex2";
70
69
  import pm from "picomatch";
71
- import mvdanSh from "mvdan-sh";
72
70
  import mvdanSh2 from "mvdan-sh";
71
+ import mvdanSh from "mvdan-sh";
72
+ import mvdanSh3 from "mvdan-sh";
73
73
  import safeRegex2 from "safe-regex2";
74
74
  import { createHash as createHash2 } from "crypto";
75
75
  import { createHash as createHash22 } from "crypto";
76
- import mvdanSh4 from "mvdan-sh";
77
- import mvdanSh5 from "mvdan-sh";
78
- import mvdanSh6 from "mvdan-sh";
79
- import mvdanSh8 from "mvdan-sh";
80
- import mvdanSh7 from "mvdan-sh";
81
76
  import { createHash as createHash3 } from "crypto";
82
- import mvdanSh9 from "mvdan-sh";
83
77
  import crypto from "crypto";
84
78
  function validateRegex(pattern) {
85
79
  if (!pattern) return "Pattern is required";
@@ -661,6 +655,62 @@ function resolveCheckMap(settings) {
661
655
  for (const c of CHECKS) out[c.id] = checkValue(settings, c.id);
662
656
  return out;
663
657
  }
658
+ function isGoNode(v) {
659
+ return v !== null && typeof v === "object" && typeof v.Pos === "function";
660
+ }
661
+ function toPlainTree(goNode) {
662
+ const kind = syntax.NodeType(goNode);
663
+ const out = { kind, pos: goNode.Pos().Offset(), end: goNode.End().Offset() };
664
+ const spec = KINDS[kind];
665
+ if (!spec) {
666
+ unknownKinds.add(kind);
667
+ return out;
668
+ }
669
+ convertFields(goNode, spec, out, kind);
670
+ return out;
671
+ }
672
+ function convertFields(goNode, spec, out, kind) {
673
+ for (const f of spec.scalars ?? []) out[f] = goNode[f];
674
+ for (const f of spec.nodes ?? []) {
675
+ const v = goNode[f];
676
+ if (v === void 0 || v === null) {
677
+ out[f] = null;
678
+ } else if (Array.isArray(v)) {
679
+ out[f] = v.map((c) => isGoNode(c) ? toPlainTree(c) : c);
680
+ } else if (isGoNode(v)) {
681
+ out[f] = toPlainTree(v);
682
+ } else if (typeof v === "object" && STRUCTS[`${kind}.${f}`]) {
683
+ const sub = { struct: `${kind}.${f}` };
684
+ convertFields(v, STRUCTS[`${kind}.${f}`], sub, `${kind}.${f}`);
685
+ out[f] = sub;
686
+ } else {
687
+ out[f] = v;
688
+ }
689
+ }
690
+ }
691
+ function childrenOf(n) {
692
+ const spec = n.kind ? KINDS[n.kind] : STRUCTS[n.struct];
693
+ if (!spec?.nodes) return [];
694
+ const out = [];
695
+ for (const f of spec.nodes) {
696
+ if (spec.notWalked?.includes(f)) continue;
697
+ const v = n[f];
698
+ if (!v) continue;
699
+ if (Array.isArray(v)) {
700
+ for (const c of v) if (c) out.push(c);
701
+ } else if (v.kind) {
702
+ out.push(v);
703
+ } else if (v.struct) {
704
+ out.push(...childrenOf(v));
705
+ }
706
+ }
707
+ return out;
708
+ }
709
+ function walk(root, fn) {
710
+ if (!root) return;
711
+ if (!fn(root)) return;
712
+ for (const c of childrenOf(root)) walk(c, fn);
713
+ }
664
714
  function isInvisibleChar(char) {
665
715
  return INVISIBLE_ONE.test(char);
666
716
  }
@@ -816,7 +866,7 @@ function judgeInlineCode(language, code, isProtected) {
816
866
  }
817
867
  function isCatHeredocOrLit(part) {
818
868
  if (!part) return false;
819
- const t = syntax.NodeType(part);
869
+ const t = part.kind;
820
870
  if (t === "Lit") return true;
821
871
  if (t !== "CmdSubst") return false;
822
872
  const stmts = part.Stmts || [];
@@ -826,9 +876,9 @@ function isCatHeredocOrLit(part) {
826
876
  const hasHeredoc = redirs.some((r) => r && r.Hdoc);
827
877
  if (!hasHeredoc) return false;
828
878
  const cmd = stmt.Cmd;
829
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return false;
879
+ if (!cmd || cmd.kind !== "CallExpr") return false;
830
880
  const firstArg = cmd.Args?.[0]?.Parts || [];
831
- if (firstArg.length !== 1 || syntax.NodeType(firstArg[0]) !== "Lit") return false;
881
+ if (firstArg.length !== 1 || firstArg[0].kind !== "Lit") return false;
832
882
  return (firstArg[0].Value || "").toLowerCase() === "cat";
833
883
  }
834
884
  function parseShared(command) {
@@ -840,7 +890,7 @@ function parseShared(command) {
840
890
  }
841
891
  let parsed;
842
892
  try {
843
- parsed = sharedParser.Parse(command, "cmd");
893
+ parsed = toPlainTree(sharedParser.Parse(command, "cmd"));
844
894
  } catch {
845
895
  parsed = PARSE_FAIL;
846
896
  }
@@ -901,10 +951,10 @@ function fileAccessViewImpl(command) {
901
951
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
902
952
  const edits = [];
903
953
  try {
904
- syntax.Walk(f, (node) => {
954
+ walk(f, (node) => {
905
955
  if (!node) return false;
906
956
  const n = node;
907
- if (syntax.NodeType(n) !== "CallExpr") return true;
957
+ if (n.kind !== "CallExpr") return true;
908
958
  const args = n.Args || [];
909
959
  const words = args.map((a) => resolveWordLiteral(a));
910
960
  const head = unwrapCommandHead(words);
@@ -916,8 +966,8 @@ function fileAccessViewImpl(command) {
916
966
  if (!PROGRAM_DIR.test(word)) continue;
917
967
  const name = word.split(/[\\/]/).pop() ?? "";
918
968
  if (!name) continue;
919
- const s = at(args[i].Pos().Offset());
920
- const e = at(args[i].End().Offset());
969
+ const s = at(args[i].pos);
970
+ const e = at(args[i].end);
921
971
  if (s < 0 || e < 0) continue;
922
972
  edits.push([s, e, name]);
923
973
  }
@@ -945,10 +995,10 @@ function literalPayloadsOf(command, depth) {
945
995
  if (f === PARSE_FAIL) return [];
946
996
  const out = [];
947
997
  try {
948
- syntax.Walk(f, (node) => {
998
+ walk(f, (node) => {
949
999
  if (!node || out.length >= MAX_READING_PAYLOADS) return false;
950
1000
  const n = node;
951
- if (syntax.NodeType(n) !== "CallExpr") return true;
1001
+ if (n.kind !== "CallExpr") return true;
952
1002
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
953
1003
  if (words.length === 0) return true;
954
1004
  const payload = literalShellPayload(words, baseWord(words[0]));
@@ -968,23 +1018,23 @@ function foldCommandWords(reading) {
968
1018
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
969
1019
  const edits = [];
970
1020
  try {
971
- syntax.Walk(f, (node) => {
1021
+ walk(f, (node) => {
972
1022
  if (!node) return false;
973
1023
  const n = node;
974
- if (syntax.NodeType(n) !== "CallExpr") return true;
1024
+ if (n.kind !== "CallExpr") return true;
975
1025
  const args = n.Args || [];
976
1026
  const words = args.map((a) => resolveWordLiteral(a));
977
1027
  const folded = words.map((w) => w === null ? null : foldHomoglyphs(w));
978
1028
  const head = unwrapCommandHead(folded);
979
1029
  for (let i = 0; i <= head && i < args.length; i++) {
980
1030
  const parts = args[i].Parts || [];
981
- if (parts.length !== 1 || syntax.NodeType(parts[0]) !== "Lit") continue;
1031
+ if (parts.length !== 1 || parts[0].kind !== "Lit") continue;
982
1032
  const value = parts[0].Value ?? "";
983
1033
  const word = folded[i];
984
1034
  if (word === null || word === value || !/[^\x00-\x7f]/.test(value)) continue;
985
1035
  if (!/^[A-Za-z0-9._/-]+$/.test(word)) continue;
986
- const s = at(args[i].Pos().Offset());
987
- const e = at(args[i].End().Offset());
1036
+ const s = at(args[i].pos);
1037
+ const e = at(args[i].end);
988
1038
  if (s < 0 || e < 0) continue;
989
1039
  edits.push([s, e, word]);
990
1040
  }
@@ -1021,10 +1071,10 @@ function interpreterHeredocSpans(f, at) {
1021
1071
  const stmts = f?.Stmts || [];
1022
1072
  const candidates = [];
1023
1073
  let unsafe = false;
1024
- syntax.Walk(f, (node) => {
1074
+ walk(f, (node) => {
1025
1075
  if (!node || unsafe) return false;
1026
1076
  const n = node;
1027
- const t = syntax.NodeType(n);
1077
+ const t = n.kind;
1028
1078
  if (t === "FuncDecl") {
1029
1079
  unsafe = true;
1030
1080
  return false;
@@ -1044,7 +1094,7 @@ function interpreterHeredocSpans(f, at) {
1044
1094
  });
1045
1095
  if (unsafe) return [];
1046
1096
  for (const st of stmts) {
1047
- if (!st?.Cmd || syntax.NodeType(st.Cmd) !== "CallExpr") continue;
1097
+ if (!st?.Cmd || st.Cmd.kind !== "CallExpr") continue;
1048
1098
  const words = (st.Cmd.Args || []).map((a) => resolveWordLiteral(a));
1049
1099
  const name = (words[0] ?? "").toLowerCase();
1050
1100
  if (!STDIN_CODE_INTERPRETERS.test(name)) continue;
@@ -1059,8 +1109,8 @@ function interpreterHeredocSpans(f, at) {
1059
1109
  if (stdin.length !== 1 || others > 0) continue;
1060
1110
  const r = stdin[0];
1061
1111
  if (heredocText(r.Hdoc) === null) continue;
1062
- const hs = at(r.Hdoc.Pos().Offset());
1063
- const he = at(r.Hdoc.End().Offset());
1112
+ const hs = at(r.Hdoc.pos);
1113
+ const he = at(r.Hdoc.end);
1064
1114
  if (hs < 0 || he < 0 || he <= hs) continue;
1065
1115
  spans.push([hs, he]);
1066
1116
  }
@@ -1080,24 +1130,24 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1080
1130
  strips.push([hs, he]);
1081
1131
  msgSpans.add(`${hs}:${he}`);
1082
1132
  }
1083
- syntax.Walk(f, (node) => {
1133
+ walk(f, (node) => {
1084
1134
  if (!node) return false;
1085
1135
  const n = node;
1086
- if (syntax.NodeType(n) !== "CallExpr") return true;
1136
+ if (n.kind !== "CallExpr") return true;
1087
1137
  const args = n.Args || [];
1088
1138
  for (let i = 0; i < args.length - 1; i++) {
1089
1139
  const argParts = args[i].Parts || [];
1090
- if (argParts.length !== 1 || syntax.NodeType(argParts[0]) !== "Lit") continue;
1140
+ if (argParts.length !== 1 || argParts[0].kind !== "Lit") continue;
1091
1141
  const flagVal = argParts[0].Value || "";
1092
1142
  if (!MESSAGE_FLAGS.has(flagVal.toLowerCase())) continue;
1093
1143
  const next = args[i + 1];
1094
1144
  const nextParts = next.Parts || [];
1095
1145
  if (nextParts.length !== 1) continue;
1096
1146
  const quotedNode = nextParts[0];
1097
- const nt = syntax.NodeType(quotedNode);
1147
+ const nt = quotedNode.kind;
1098
1148
  const markStrip = () => {
1099
- const s = at(next.Pos().Offset());
1100
- const e = at(next.End().Offset());
1149
+ const s = at(next.pos);
1150
+ const e = at(next.end);
1101
1151
  if (s < 0 || e < 0) return;
1102
1152
  strips.push([s, e]);
1103
1153
  msgSpans.add(`${s}:${e}`);
@@ -1106,7 +1156,7 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1106
1156
  markStrip();
1107
1157
  } else if (nt === "DblQuoted") {
1108
1158
  const innerParts = quotedNode.Parts || [];
1109
- const allLit = innerParts.length === 0 || innerParts.every((p) => syntax.NodeType(p) === "Lit");
1159
+ const allLit = innerParts.length === 0 || innerParts.every((p) => p.kind === "Lit");
1110
1160
  if (allLit) {
1111
1161
  markStrip();
1112
1162
  } else if (innerParts.every((p) => isCatHeredocOrLit(p))) {
@@ -1115,8 +1165,8 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1115
1165
  }
1116
1166
  }
1117
1167
  for (const arg of args) {
1118
- const s = at(arg.Pos().Offset());
1119
- const e = at(arg.End().Offset());
1168
+ const s = at(arg.pos);
1169
+ const e = at(arg.end);
1120
1170
  if (s < 0 || e < 0) continue;
1121
1171
  if (msgSpans.has(`${s}:${e}`)) continue;
1122
1172
  const resolved = resolveWordLiteral(arg);
@@ -1156,10 +1206,10 @@ function scanArgsForDynamicExec(args, startIdx) {
1156
1206
  let hasParamExp = false;
1157
1207
  let hasCurl = false;
1158
1208
  for (let i = startIdx; i < args.length; i++) {
1159
- syntax.Walk(args[i], (inner) => {
1209
+ walk(args[i], (inner) => {
1160
1210
  if (!inner) return false;
1161
1211
  const inn = inner;
1162
- const it = syntax.NodeType(inn);
1212
+ const it = inn.kind;
1163
1213
  if (it === "CmdSubst") hasCmdSubst = true;
1164
1214
  if (it === "ParamExp") hasParamExp = true;
1165
1215
  if (it === "Lit" && DOWNLOAD_CMDS.has(inn.Value?.toLowerCase())) hasCurl = true;
@@ -1172,15 +1222,16 @@ function scanArgsForDynamicExec(args, startIdx) {
1172
1222
  }
1173
1223
  function detectDangerousShellExec(command) {
1174
1224
  try {
1175
- const f = sharedParser.Parse(command, "cmd");
1225
+ const f = parseShared(command);
1226
+ if (f === PARSE_FAIL) return null;
1176
1227
  let result = null;
1177
1228
  const assigned = assignedNames(f);
1178
- syntax.Walk(f, (node) => {
1229
+ walk(f, (node) => {
1179
1230
  if (!node || result === "block") return false;
1180
1231
  const n = node;
1181
- if (syntax.NodeType(n) === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1232
+ if (n.kind === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1182
1233
  const call = n.Y.Cmd;
1183
- if (call && syntax.NodeType(call) === "CallExpr") {
1234
+ if (call && call.kind === "CallExpr") {
1184
1235
  const words = (call.Args || []).map((a) => resolveWordLiteral(a));
1185
1236
  const head2 = unwrapCommandHead(words);
1186
1237
  const name = (words[head2] ?? "").split("/").pop() ?? "";
@@ -1193,7 +1244,7 @@ function detectDangerousShellExec(command) {
1193
1244
  result = "review";
1194
1245
  }
1195
1246
  }
1196
- if (syntax.NodeType(n) !== "CallExpr") return true;
1247
+ if (n.kind !== "CallExpr") return true;
1197
1248
  const args = n.Args || [];
1198
1249
  if (args.length === 0) return true;
1199
1250
  const headWords = args.map(
@@ -1204,7 +1255,7 @@ function detectDangerousShellExec(command) {
1204
1255
  if (!lookup && (opaqueExecutable(args[0], assigned) || opaqueExecutable(args[head], assigned)))
1205
1256
  result = "review";
1206
1257
  const firstParts = args[0].Parts || [];
1207
- if (firstParts.length !== 1 || syntax.NodeType(firstParts[0]) !== "Lit") return true;
1258
+ if (firstParts.length !== 1 || firstParts[0].kind !== "Lit") return true;
1208
1259
  const cmdName = firstParts[0].Value?.toLowerCase() ?? "";
1209
1260
  if (cmdName === "eval") {
1210
1261
  const v = scanArgsForDynamicExec(args, 1);
@@ -1212,7 +1263,7 @@ function detectDangerousShellExec(command) {
1212
1263
  } else if (SHELL_INTERPRETERS.has(cmdName)) {
1213
1264
  for (let i = 1; i < args.length - 1; i++) {
1214
1265
  const flagParts = args[i].Parts || [];
1215
- if (flagParts.length !== 1 || syntax.NodeType(flagParts[0]) !== "Lit" || flagParts[0].Value !== "-c")
1266
+ if (flagParts.length !== 1 || flagParts[0].kind !== "Lit" || flagParts[0].Value !== "-c")
1216
1267
  continue;
1217
1268
  const v = scanArgsForDynamicExec(args, i + 1);
1218
1269
  if (v === "block" || v === "review" && result === null) result = v;
@@ -1236,8 +1287,7 @@ function isDefaultExpansion(part) {
1236
1287
  }
1237
1288
  function lookupSubstitution(part) {
1238
1289
  const stmts = part.Stmts ?? [];
1239
- if (stmts.length !== 1 || !stmts[0].Cmd || syntax.NodeType(stmts[0].Cmd) !== "CallExpr")
1240
- return null;
1290
+ if (stmts.length !== 1 || !stmts[0].Cmd || stmts[0].Cmd.kind !== "CallExpr") return null;
1241
1291
  const words = (stmts[0].Cmd.Args ?? []).map((a) => resolveWordLiteral(a));
1242
1292
  if (words.some((w) => w === null)) return null;
1243
1293
  if (words.length === 2 && words[0] === "which") return words[1];
@@ -1247,9 +1297,9 @@ function lookupSubstitution(part) {
1247
1297
  }
1248
1298
  function assignedNames(f) {
1249
1299
  const names = /* @__PURE__ */ new Set();
1250
- syntax.Walk(f, (node) => {
1300
+ walk(f, (node) => {
1251
1301
  if (!node) return false;
1252
- const kind = syntax.NodeType(node);
1302
+ const kind = node.kind;
1253
1303
  if (kind === "Assign" && node.Name?.Value) names.add(node.Name.Value);
1254
1304
  if (kind === "ForClause" && node.Loop?.Name?.Value) names.add(node.Loop.Name.Value);
1255
1305
  if (kind === "CallExpr") {
@@ -1264,7 +1314,7 @@ function assignedNames(f) {
1264
1314
  }
1265
1315
  function executableParts(word, assigned, quoted = false) {
1266
1316
  return (word?.Parts ?? []).flatMap((part) => {
1267
- const kind = syntax.NodeType(part);
1317
+ const kind = part.kind;
1268
1318
  if (kind === "DblQuoted") return executableParts(part, assigned, true);
1269
1319
  if (kind === "Lit") return [{ kind: "Lit", value: part.Value ?? "", quoted }];
1270
1320
  if (kind === "SglQuoted")
@@ -1332,10 +1382,10 @@ function chmodHasOpenPermMode(command) {
1332
1382
  if (f === PARSE_FAIL) return false;
1333
1383
  let found = false;
1334
1384
  try {
1335
- syntax.Walk(f, (node) => {
1385
+ walk(f, (node) => {
1336
1386
  if (!node || found) return false;
1337
1387
  const n = node;
1338
- if (syntax.NodeType(n) !== "CallExpr") return true;
1388
+ if (n.kind !== "CallExpr") return true;
1339
1389
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1340
1390
  if (words.length === 0) return true;
1341
1391
  const name = (words[0] ?? "").toLowerCase();
@@ -1388,11 +1438,11 @@ function redirStdinOps() {
1388
1438
  }
1389
1439
  function deriveBinaryOp(sample) {
1390
1440
  try {
1391
- const f = sharedParser.Parse(sample, "cmd");
1441
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
1392
1442
  let op = -1;
1393
- syntax.Walk(f, (node) => {
1443
+ walk(f, (node) => {
1394
1444
  const n = node;
1395
- if (n && syntax.NodeType(n) === "BinaryCmd" && op < 0) op = n.Op;
1445
+ if (n && n.kind === "BinaryCmd" && op < 0) op = n.Op;
1396
1446
  return true;
1397
1447
  });
1398
1448
  return op;
@@ -1466,7 +1516,7 @@ function heredocText(word) {
1466
1516
  const parts = word?.Parts ?? [];
1467
1517
  let out = "";
1468
1518
  for (const p of parts) {
1469
- if (syntax.NodeType(p) !== "Lit") return null;
1519
+ if (p.kind !== "Lit") return null;
1470
1520
  out += p.Value ?? "";
1471
1521
  }
1472
1522
  return out;
@@ -1502,7 +1552,7 @@ function attachedCode(interp, flag) {
1502
1552
  }
1503
1553
  function inlineExecCall(stmt, pipeFed) {
1504
1554
  const cmd = stmt?.Cmd;
1505
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return null;
1555
+ if (!cmd || cmd.kind !== "CallExpr") return null;
1506
1556
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1507
1557
  if (words.length === 0) return null;
1508
1558
  const headIdx = unwrapCommandHead(words);
@@ -1583,10 +1633,10 @@ function shellPayloadNeedsReview(payload) {
1583
1633
  let review = false;
1584
1634
  payloadNesting++;
1585
1635
  try {
1586
- syntax.Walk(f, (node) => {
1636
+ walk(f, (node) => {
1587
1637
  if (!node || review) return false;
1588
1638
  const n = node;
1589
- if (syntax.NodeType(n) !== "CallExpr") return true;
1639
+ if (n.kind !== "CallExpr") return true;
1590
1640
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1591
1641
  if (words.length === 0) return true;
1592
1642
  const h = unwrapCommandHead(words);
@@ -1620,10 +1670,10 @@ function inlineExecCalls(command) {
1620
1670
  if (f === PARSE_FAIL) return PARSE_FAIL;
1621
1671
  const calls = [];
1622
1672
  try {
1623
- syntax.Walk(f, (node) => {
1673
+ walk(f, (node) => {
1624
1674
  if (!node || calls.length >= MAX_INLINE_CALLS) return false;
1625
1675
  const n = node;
1626
- const t = syntax.NodeType(n);
1676
+ const t = n.kind;
1627
1677
  if (t === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1628
1678
  const call = inlineExecCall(n.Y, true);
1629
1679
  if (call) calls.push(call);
@@ -1758,7 +1808,7 @@ function shellScriptOperands(command) {
1758
1808
  walkWithCalls(f, (node) => {
1759
1809
  if (!node) return false;
1760
1810
  const n = node;
1761
- if (syntax.NodeType(n) !== "CallExpr") return true;
1811
+ if (n.kind !== "CallExpr") return true;
1762
1812
  const callArgs = n.Args || [];
1763
1813
  if (callArgs.length === 0) return true;
1764
1814
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -1794,7 +1844,7 @@ function shellScriptOperands(command) {
1794
1844
  }
1795
1845
  function windowsDrivePathSpelling(word) {
1796
1846
  const parts = word?.Parts || [];
1797
- if (parts.length === 0 || !parts.every((p) => syntax.NodeType(p) === "Lit")) return null;
1847
+ if (parts.length === 0 || !parts.every((p) => p.kind === "Lit")) return null;
1798
1848
  const raw = parts.map((p) => p.Value ?? "").join("");
1799
1849
  return /^[A-Za-z]:\\[^\s'"$`]*$/.test(raw) ? raw : null;
1800
1850
  }
@@ -1832,15 +1882,15 @@ function recordTopLevelAssignments(f) {
1832
1882
  }
1833
1883
  function probeBinOp(src) {
1834
1884
  try {
1835
- const cmd = syntax.NewParser().Parse(src, "probe")?.Stmts?.[0]?.Cmd;
1836
- if (cmd && syntax.NodeType(cmd) === "BinaryCmd") return cmd.Op;
1885
+ const cmd = toPlainTree(syntax2.NewParser().Parse(src, "probe"))?.Stmts?.[0]?.Cmd;
1886
+ if (cmd && cmd.kind === "BinaryCmd") return cmd.Op;
1837
1887
  } catch {
1838
1888
  }
1839
1889
  return null;
1840
1890
  }
1841
1891
  function recordTopLevelStmt(stmt) {
1842
1892
  if (!stmt || !stmt.Cmd) return false;
1843
- const t = syntax.NodeType(stmt.Cmd);
1893
+ const t = stmt.Cmd.kind;
1844
1894
  if (t === "BinaryCmd") {
1845
1895
  if (!AND_OR_OPS.has(stmt.Cmd.Op)) return false;
1846
1896
  if (!recordTopLevelStmt(stmt.Cmd.X)) return false;
@@ -1850,7 +1900,7 @@ function recordTopLevelStmt(stmt) {
1850
1900
  if (t !== "CallExpr" && t !== "DeclClause") return false;
1851
1901
  let at = 0;
1852
1902
  try {
1853
- at = stmt.Pos().Offset();
1903
+ at = stmt.pos;
1854
1904
  } catch {
1855
1905
  at = 0;
1856
1906
  }
@@ -1861,14 +1911,14 @@ function recordTopLevelStmt(stmt) {
1861
1911
  }
1862
1912
  function recordAssignments(n, at) {
1863
1913
  if (!assignmentTable) return;
1864
- const t = syntax.NodeType(n);
1914
+ const t = n.kind;
1865
1915
  let assigns = [];
1866
1916
  if (t === "CallExpr") {
1867
1917
  if ((n.Args || []).length > 0) return;
1868
1918
  assigns = n.Assigns || [];
1869
1919
  } else if (t === "DeclClause") {
1870
1920
  if (!ASSIGNMENT_HEADS.has(n.Variant?.Value ?? "")) return;
1871
- assigns = (n.Args || []).filter((a) => syntax.NodeType(a) === "Assign");
1921
+ assigns = (n.Args || []).filter((a) => a.kind === "Assign");
1872
1922
  } else return;
1873
1923
  for (const a of assigns) {
1874
1924
  const name = a?.Name?.Value;
@@ -1877,13 +1927,13 @@ function recordAssignments(n, at) {
1877
1927
  }
1878
1928
  }
1879
1929
  function resolveTrivialSubst(part) {
1880
- if (syntax.NodeType(part) !== "CmdSubst") return void 0;
1930
+ if (part.kind !== "CmdSubst") return void 0;
1881
1931
  const stmts = part.Stmts || [];
1882
1932
  if (stmts.length !== 1) return void 0;
1883
1933
  const st = stmts[0];
1884
1934
  if ((st.Redirs || []).length > 0 || st.Negated || st.Background) return void 0;
1885
1935
  const cmd = st.Cmd;
1886
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return void 0;
1936
+ if (!cmd || cmd.kind !== "CallExpr") return void 0;
1887
1937
  if ((cmd.Assigns || []).length > 0) return void 0;
1888
1938
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1889
1939
  if (words.length === 0 || words.some((w) => w === null)) return void 0;
@@ -1908,7 +1958,7 @@ function recordedExpansion(name) {
1908
1958
  return rec.value;
1909
1959
  }
1910
1960
  function isPlainParam(p) {
1911
- if (syntax.NodeType(p) !== "ParamExp") return false;
1961
+ if (p.kind !== "ParamExp") return false;
1912
1962
  return !(p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp);
1913
1963
  }
1914
1964
  function expandPlainParam(p) {
@@ -1920,9 +1970,9 @@ function expandPlainParam(p) {
1920
1970
  }
1921
1971
  function functionBodies(f) {
1922
1972
  const out = /* @__PURE__ */ new Map();
1923
- syntax.Walk(f, (node) => {
1973
+ walk(f, (node) => {
1924
1974
  const n = node;
1925
- if (n && syntax.NodeType(n) === "FuncDecl" && n.Name?.Value && n.Body) {
1975
+ if (n && n.kind === "FuncDecl" && n.Name?.Value && n.Body) {
1926
1976
  const list = out.get(n.Name.Value) ?? [];
1927
1977
  list.push(n.Body);
1928
1978
  out.set(n.Name.Value, list);
@@ -1933,10 +1983,10 @@ function functionBodies(f) {
1933
1983
  }
1934
1984
  function rebindsPositionals(body) {
1935
1985
  let found = false;
1936
- syntax.Walk(body, (node) => {
1986
+ walk(body, (node) => {
1937
1987
  const n = node;
1938
1988
  if (found || !n) return false;
1939
- if (syntax.NodeType(n) === "CallExpr") {
1989
+ if (n.kind === "CallExpr") {
1940
1990
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1941
1991
  if (words[0] === "shift") found = true;
1942
1992
  else if (words[0] === "set" && words.slice(1).some((w) => w === null || w === "--" || !/^[-+]/.test(w)))
@@ -1956,7 +2006,7 @@ function tableBindings() {
1956
2006
  function walkWithCalls(f, visit) {
1957
2007
  const bodies = functionBodies(f);
1958
2008
  if (bodies.size === 0) {
1959
- syntax.Walk(f, visit);
2009
+ walk(f, visit);
1960
2010
  return;
1961
2011
  }
1962
2012
  const seenCalls = /* @__PURE__ */ new Set();
@@ -1990,8 +2040,8 @@ function walkWithCalls(f, visit) {
1990
2040
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
1991
2041
  callDepth++;
1992
2042
  try {
1993
- if (body.Cmd && syntax.NodeType(body.Cmd) === "Block") recordTopLevelAssignments(body.Cmd);
1994
- syntax.Walk(body, step);
2043
+ if (body.Cmd && body.Cmd.kind === "Block") recordTopLevelAssignments(body.Cmd);
2044
+ walk(body, step);
1995
2045
  } finally {
1996
2046
  callDepth--;
1997
2047
  assignmentTable = outerTable;
@@ -2002,10 +2052,10 @@ function walkWithCalls(f, visit) {
2002
2052
  const step = (node) => {
2003
2053
  if (!node) return false;
2004
2054
  const go = visit(node);
2005
- if (go !== false && syntax.NodeType(node) === "CallExpr") inline(node);
2055
+ if (go !== false && node.kind === "CallExpr") inline(node);
2006
2056
  return go;
2007
2057
  };
2008
- syntax.Walk(f, step);
2058
+ walk(f, step);
2009
2059
  }
2010
2060
  function withAssignments(f, body) {
2011
2061
  const outerTable = assignmentTable;
@@ -2030,7 +2080,7 @@ function walkCommandScope(command, visit) {
2030
2080
  if (f === PARSE_FAIL) return "parse-fail";
2031
2081
  withAssignments(f, () => {
2032
2082
  walkWithCalls(f, (node) => {
2033
- if (node && syntax.NodeType(node) === "Stmt") trackStatement(node);
2083
+ if (node && node.kind === "Stmt") trackStatement(node);
2034
2084
  return visit(node);
2035
2085
  });
2036
2086
  });
@@ -2038,7 +2088,7 @@ function walkCommandScope(command, visit) {
2038
2088
  }
2039
2089
  function trackStatement(n) {
2040
2090
  try {
2041
- currentStmtOffset = n.Pos().Offset();
2091
+ currentStmtOffset = n.pos;
2042
2092
  } catch {
2043
2093
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2044
2094
  }
@@ -2054,11 +2104,11 @@ function resolveWordLiteral(w) {
2054
2104
  return s;
2055
2105
  }
2056
2106
  function resolveWordPrefix(w) {
2057
- const walk2 = (parts) => {
2107
+ const walk3 = (parts) => {
2058
2108
  let s = "";
2059
2109
  for (const p of parts) {
2060
2110
  if (p && typeof p === "object" && Array.isArray(p.Parts) && p.Dollar !== void 0) {
2061
- const inner = walk2(p.Parts);
2111
+ const inner = walk3(p.Parts);
2062
2112
  s += inner.prefix;
2063
2113
  if (inner.dynamic) return { prefix: s, dynamic: true };
2064
2114
  continue;
@@ -2069,10 +2119,10 @@ function resolveWordPrefix(w) {
2069
2119
  }
2070
2120
  return { prefix: s, dynamic: false };
2071
2121
  };
2072
- return walk2(w?.Parts || []);
2122
+ return walk3(w?.Parts || []);
2073
2123
  }
2074
2124
  function resolvePart(p, inQuotes) {
2075
- const t = syntax.NodeType(p);
2125
+ const t = p.kind;
2076
2126
  if (t === "Lit") {
2077
2127
  const raw = p.Value ?? "";
2078
2128
  if (!inQuotes) return raw.replace(/\\(.)/g, "$1");
@@ -2168,7 +2218,7 @@ function extractShellDestinations(command) {
2168
2218
  () => walkWithCalls(f, (node) => {
2169
2219
  if (!node) return false;
2170
2220
  const n = node;
2171
- if (syntax.NodeType(n) === "Stmt") {
2221
+ if (n.kind === "Stmt") {
2172
2222
  trackStatement(n);
2173
2223
  for (const raw of redirectWords(n)) {
2174
2224
  const host2 = devNetRedirectHost(raw);
@@ -2180,7 +2230,7 @@ function extractShellDestinations(command) {
2180
2230
  out.push({ host: host2, binary, raw });
2181
2231
  }
2182
2232
  }
2183
- if (syntax.NodeType(n) !== "CallExpr") return true;
2233
+ if (n.kind !== "CallExpr") return true;
2184
2234
  const callArgs = n.Args || [];
2185
2235
  if (callArgs.length === 0) return true;
2186
2236
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2215,7 +2265,7 @@ function extractShellDestTokens(command) {
2215
2265
  () => walkWithCalls(f, (node) => {
2216
2266
  if (!node) return false;
2217
2267
  const n = node;
2218
- if (syntax.NodeType(n) === "Stmt") {
2268
+ if (n.kind === "Stmt") {
2219
2269
  trackStatement(n);
2220
2270
  for (const raw of redirectWords(n)) {
2221
2271
  const host2 = devNetRedirectHost(raw);
@@ -2227,7 +2277,7 @@ function extractShellDestTokens(command) {
2227
2277
  out.push({ token: host2, binary });
2228
2278
  }
2229
2279
  }
2230
- if (syntax.NodeType(n) !== "CallExpr") return true;
2280
+ if (n.kind !== "CallExpr") return true;
2231
2281
  const callArgs = n.Args || [];
2232
2282
  if (callArgs.length === 0) return true;
2233
2283
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2295,11 +2345,11 @@ function isWaivableCleanupTarget(p) {
2295
2345
  }
2296
2346
  function deriveRedirOp(sample) {
2297
2347
  try {
2298
- const f = sharedParser.Parse(sample, "cmd");
2348
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
2299
2349
  let op = -1;
2300
- syntax.Walk(f, (node) => {
2350
+ walk(f, (node) => {
2301
2351
  const n = node;
2302
- if (n && syntax.NodeType(n) === "Redirect" && op < 0) op = n.Op;
2352
+ if (n && n.kind === "Redirect" && op < 0) op = n.Op;
2303
2353
  return true;
2304
2354
  });
2305
2355
  return op;
@@ -2312,7 +2362,7 @@ function collectSameCommandCreations(f) {
2312
2362
  try {
2313
2363
  const stmts = Array.isArray(f?.Stmts) ? f.Stmts : [];
2314
2364
  for (const stmt of stmts) {
2315
- if (!stmt || !stmt.Cmd || syntax.NodeType(stmt.Cmd) !== "CallExpr") continue;
2365
+ if (!stmt || !stmt.Cmd || stmt.Cmd.kind !== "CallExpr") continue;
2316
2366
  const redirs = stmt.Redirs || [];
2317
2367
  if (!redirs.some((r) => r && REDIR_HEREDOC_OPS.has(r.Op))) continue;
2318
2368
  for (const r of redirs) {
@@ -2336,10 +2386,10 @@ function isRmCreatedInCommandCleanup(command) {
2336
2386
  let sawRm = false;
2337
2387
  let ok = true;
2338
2388
  try {
2339
- syntax.Walk(f, (node) => {
2389
+ walk(f, (node) => {
2340
2390
  if (!node || !ok) return false;
2341
2391
  const n = node;
2342
- if (syntax.NodeType(n) !== "CallExpr") return true;
2392
+ if (n.kind !== "CallExpr") return true;
2343
2393
  const args = n.Args || [];
2344
2394
  const name = (resolveWordLiteral(args[0]) ?? "").toLowerCase();
2345
2395
  if (name !== "rm") return true;
@@ -2389,10 +2439,10 @@ function analyzeFsOperationImpl(command, depth = 0) {
2389
2439
  walkWithCalls(f, (node) => {
2390
2440
  if (!node || result?.verdict === "block") return false;
2391
2441
  const n = node;
2392
- const nodeType = syntax.NodeType(n);
2442
+ const nodeType = n.kind;
2393
2443
  if (nodeType === "Stmt") {
2394
2444
  try {
2395
- currentStmtOffset = n.Pos().Offset();
2445
+ currentStmtOffset = n.pos;
2396
2446
  } catch {
2397
2447
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2398
2448
  }
@@ -2905,11 +2955,12 @@ function analyzeShellCommand(command) {
2905
2955
  if (lower2.startsWith("-")) allTokens.push(lower2.replace(/^-+/, ""));
2906
2956
  };
2907
2957
  try {
2908
- const f = sharedParser.Parse(command, "cmd");
2909
- syntax.Walk(f, (node) => {
2958
+ const f = parseShared(command);
2959
+ if (f === PARSE_FAIL) throw new Error("parse failed");
2960
+ walk(f, (node) => {
2910
2961
  if (!node) return false;
2911
2962
  const n = node;
2912
- if (syntax.NodeType(n) !== "CallExpr") return true;
2963
+ if (n.kind !== "CallExpr") return true;
2913
2964
  const wordValues2 = (n.Args || []).map((arg) => {
2914
2965
  return (arg.Parts || []).map((p) => (p.Value ?? "").replace(/\\(.)/g, "$1")).join("");
2915
2966
  }).filter((s) => s.length > 0);
@@ -3181,7 +3232,7 @@ function runnablePrefix(command) {
3181
3232
  let text = command;
3182
3233
  for (let attempt = 0; attempt < 32; attempt++) {
3183
3234
  try {
3184
- return syntax2.NewParser().Parse(text, "");
3235
+ return toPlainTree(syntax3.NewParser().Parse(text, ""));
3185
3236
  } catch (error) {
3186
3237
  const message = String(typeof error?.Error === "function" ? error.Error() : error?.message);
3187
3238
  const line = Number(/^(\d+):/.exec(message)?.[1]);
@@ -3249,7 +3300,7 @@ function wordValues(word, state) {
3249
3300
  out2 = next.slice(0, MAX_ALTERNATIVES);
3250
3301
  };
3251
3302
  for (const node of nodes) {
3252
- const kind = syntax2.NodeType(node);
3303
+ const kind = node.kind;
3253
3304
  let pieces;
3254
3305
  if (kind === "ParamExp") pieces = paramValues(node, quoted);
3255
3306
  else if (kind === "DblQuoted") {
@@ -3317,9 +3368,9 @@ function collectShellFileAccesses(command, context = {}) {
3317
3368
  }
3318
3369
  function substitutions(word, state, depth) {
3319
3370
  if (!word) return;
3320
- syntax2.Walk(word, (node) => {
3371
+ walk(word, (node) => {
3321
3372
  if (!node) return false;
3322
- if (["CmdSubst", "ProcSubst"].includes(syntax2.NodeType(node))) {
3373
+ if (["CmdSubst", "ProcSubst"].includes(node.kind)) {
3323
3374
  statements(node.Stmts ?? [], clone(state), depth + 1);
3324
3375
  return false;
3325
3376
  }
@@ -3743,7 +3794,7 @@ function collectShellFileAccesses(command, context = {}) {
3743
3794
  }
3744
3795
  function readsScriptFromStdin(stmt) {
3745
3796
  const cmd = stmt?.Cmd;
3746
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return false;
3797
+ if (!cmd || cmd.kind !== "CallExpr") return false;
3747
3798
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3748
3799
  const head = unwrapCommandHead(words);
3749
3800
  return SHELL_INTERPRETERS.has(base(words[head])) && shellConsumesPipe(words.slice(head + 1));
@@ -3757,7 +3808,7 @@ function collectShellFileAccesses(command, context = {}) {
3757
3808
  }
3758
3809
  function producedText(stmt) {
3759
3810
  const cmd = stmt?.Cmd;
3760
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return null;
3811
+ if (!cmd || cmd.kind !== "CallExpr") return null;
3761
3812
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3762
3813
  if (words.some((w) => w === null)) return null;
3763
3814
  const head = unwrapCommandHead(words);
@@ -3776,7 +3827,7 @@ function collectShellFileAccesses(command, context = {}) {
3776
3827
  if (!stmt || depth > MAX_DEPTH) return;
3777
3828
  state.onSuccess = void 0;
3778
3829
  if (stmt.Background) state = clone(state);
3779
- const headWord = stmt.Cmd && syntax2.NodeType(stmt.Cmd) === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3830
+ const headWord = stmt.Cmd && stmt.Cmd.kind === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3780
3831
  const sends = SENDING_STDIN.has(headWord);
3781
3832
  for (const redir of stmt.Redirs ?? []) {
3782
3833
  substitutions(redir.Word, state, depth);
@@ -3792,7 +3843,7 @@ function collectShellFileAccesses(command, context = {}) {
3792
3843
  const cmd = stmt.Cmd;
3793
3844
  if (!cmd) return;
3794
3845
  stdinScript(stmt, state, depth);
3795
- switch (syntax2.NodeType(cmd)) {
3846
+ switch (cmd.kind) {
3796
3847
  case "CallExpr":
3797
3848
  call(cmd, state, depth);
3798
3849
  break;
@@ -3806,7 +3857,7 @@ function collectShellFileAccesses(command, context = {}) {
3806
3857
  for (; ; ) {
3807
3858
  segments2.unshift({ op: node.Op, part: node.Y });
3808
3859
  const left = node.X;
3809
- if (left?.Cmd && syntax2.NodeType(left.Cmd) === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3860
+ if (left?.Cmd && left.Cmd.kind === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3810
3861
  node = left.Cmd;
3811
3862
  else {
3812
3863
  segments2.unshift({ op: node.Op, part: left });
@@ -5144,11 +5195,10 @@ function shellWriteUnseen(command, target) {
5144
5195
  let unseen = false;
5145
5196
  let seen = false;
5146
5197
  try {
5147
- syntax4.Walk(f, (node) => {
5198
+ walk(f, (node) => {
5148
5199
  if (!node || unseen) return false;
5149
5200
  const n = node;
5150
- if (syntax4.NodeType(n) !== "Stmt" || !n.Cmd || syntax4.NodeType(n.Cmd) !== "CallExpr")
5151
- return true;
5201
+ if (n.kind !== "Stmt" || !n.Cmd || n.Cmd.kind !== "CallExpr") return true;
5152
5202
  const words = (n.Cmd.Args || []).map(
5153
5203
  (a) => resolveWordLiteral(a)
5154
5204
  );
@@ -5203,14 +5253,14 @@ function analyzeGitImpl(command) {
5203
5253
  seen.add(key);
5204
5254
  findings.push(f);
5205
5255
  };
5206
- const walk2 = new GitWalk((inv) => classify(inv).forEach(found), found);
5207
- const parsed = walk2.run(command, 0);
5256
+ const walk3 = new GitWalk((inv) => classify(inv).forEach(found), found);
5257
+ const parsed = walk3.run(command, 0);
5208
5258
  return { parsed, findings };
5209
5259
  }
5210
5260
  function isPositionalParam(word) {
5211
5261
  let parts = word?.Parts || [];
5212
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
5213
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return false;
5262
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
5263
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return false;
5214
5264
  return /^(\d+|@|\*)$/.test(parts[0].Param?.Value ?? "");
5215
5265
  }
5216
5266
  function boundPositionals() {
@@ -5224,11 +5274,11 @@ function boundPositionals() {
5224
5274
  function plainParamName(word) {
5225
5275
  let parts = word?.Parts || [];
5226
5276
  let quoted = false;
5227
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") {
5277
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") {
5228
5278
  parts = parts[0].Parts || [];
5229
5279
  quoted = true;
5230
5280
  }
5231
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return null;
5281
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
5232
5282
  const p = parts[0];
5233
5283
  if (p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp) return null;
5234
5284
  const name = p.Param?.Value;
@@ -5253,7 +5303,7 @@ function resolveGitWords(word) {
5253
5303
  }
5254
5304
  const parts = word?.Parts || [];
5255
5305
  const expansion = parts.some((p) => {
5256
- const t = syntax5.NodeType(p);
5306
+ const t = p.kind;
5257
5307
  return t === "ParamExp" || t === "CmdSubst";
5258
5308
  });
5259
5309
  return expansion ? splitFields(value) : [value];
@@ -5654,14 +5704,14 @@ function hookCommands(text) {
5654
5704
  const root = parsed?.hooks;
5655
5705
  if (!root || typeof root !== "object") return null;
5656
5706
  const out = [];
5657
- const walk2 = (v, depth) => {
5707
+ const walk3 = (v, depth) => {
5658
5708
  if (depth > 8 || !v || typeof v !== "object") return;
5659
5709
  for (const [k, x] of Object.entries(v)) {
5660
5710
  if (k === "command" && typeof x === "string") out.push(x);
5661
- else walk2(x, depth + 1);
5711
+ else walk3(x, depth + 1);
5662
5712
  }
5663
5713
  };
5664
- walk2(root, 0);
5714
+ walk3(root, 0);
5665
5715
  return out;
5666
5716
  }
5667
5717
  function hooksDisarmed(text) {
@@ -5828,9 +5878,9 @@ function isDupInOp(op) {
5828
5878
  if (dupInOp === null) {
5829
5879
  let found = -1;
5830
5880
  try {
5831
- syntax6.Walk(parseShared("cat <&3"), (node) => {
5881
+ walk(parseShared("cat <&3"), (node) => {
5832
5882
  const n = node;
5833
- if (found === -1 && n && syntax6.NodeType(n) === "Stmt" && n.Redirs?.[0]) {
5883
+ if (found === -1 && n && n.kind === "Stmt" && n.Redirs?.[0]) {
5834
5884
  found = n.Redirs[0].Op;
5835
5885
  }
5836
5886
  return true;
@@ -5851,10 +5901,10 @@ function analyzeOutbound(command) {
5851
5901
  return hit;
5852
5902
  }
5853
5903
  const findings = [];
5854
- const walk2 = new OutboundWalk(findings);
5855
- const parsed = walk2.run(command, 0);
5904
+ const walk3 = new OutboundWalk(findings);
5905
+ const parsed = walk3.run(command, 0);
5856
5906
  const envOut = findings.find((f) => f.checkId === "data.env-exfil");
5857
- if (envOut) envOut.destinations = walk2.envDestinations();
5907
+ if (envOut) envOut.destinations = walk3.envDestinations();
5858
5908
  const computed = { parsed, findings };
5859
5909
  if (cache2.size >= CACHE_MAX2) {
5860
5910
  const oldest = cache2.keys().next().value;
@@ -5870,7 +5920,7 @@ function wordShape(word) {
5870
5920
  const parts = word?.Parts || [];
5871
5921
  let out = "";
5872
5922
  for (const p of parts) {
5873
- const t = syntax6.NodeType(p);
5923
+ const t = p.kind;
5874
5924
  if (t === "Lit" || t === "SglQuoted") out += p.Value ?? "";
5875
5925
  else if (t === "DblQuoted") out += wordShape(p);
5876
5926
  else out += "X";
@@ -6005,16 +6055,16 @@ function declDumpsEnv(decl) {
6005
6055
  }
6006
6056
  function paramName(word) {
6007
6057
  let parts = word?.Parts || [];
6008
- if (parts.length === 1 && syntax6.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
6009
- if (parts.length !== 1 || syntax6.NodeType(parts[0]) !== "ParamExp") return null;
6058
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
6059
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
6010
6060
  return parts[0].Param?.Value ?? null;
6011
6061
  }
6012
6062
  function refersTo(word, names) {
6013
6063
  let hit = false;
6014
- syntax6.Walk(word, (node) => {
6064
+ walk(word, (node) => {
6015
6065
  if (hit || !node) return false;
6016
6066
  const n = node;
6017
- if (syntax6.NodeType(n) === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6067
+ if (n.kind === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6018
6068
  return !hit;
6019
6069
  });
6020
6070
  return hit;
@@ -6022,10 +6072,10 @@ function refersTo(word, names) {
6022
6072
  function runsCommandsIn(stmt) {
6023
6073
  const readVars = /* @__PURE__ */ new Set();
6024
6074
  let hit = false;
6025
- syntax6.Walk(stmt, (node) => {
6075
+ walk(stmt, (node) => {
6026
6076
  if (hit || !node) return false;
6027
6077
  const n = node;
6028
- if (syntax6.NodeType(n) !== "CallExpr") return true;
6078
+ if (n.kind !== "CallExpr") return true;
6029
6079
  const words = wordsOf(n);
6030
6080
  if (words.length === 0) return true;
6031
6081
  const { head, at } = headOf(words);
@@ -6602,7 +6652,7 @@ function localContexts(file2) {
6602
6652
  if (depth > 64) return null;
6603
6653
  if (!stmt || stmt.Background || stmt.Negated || stmt.Redirs?.length) return null;
6604
6654
  const cmd = stmt.Cmd;
6605
- const kind = syntax7.NodeType(cmd);
6655
+ const kind = cmd.kind;
6606
6656
  if (kind === "BinaryCmd" && cmd.Op === andOp) {
6607
6657
  const next = visit(cmd.X, steps, depth + 1);
6608
6658
  return next === null ? null : visit(cmd.Y, next, depth + 1);
@@ -6618,7 +6668,7 @@ function localContexts(file2) {
6618
6668
  )
6619
6669
  ))
6620
6670
  return null;
6621
- contexts.set(cmd.Pos().Offset(), steps);
6671
+ contexts.set(cmd.pos, steps);
6622
6672
  return null;
6623
6673
  }
6624
6674
  if (file2.Stmts?.length === 1) visit(file2.Stmts[0], []);
@@ -6629,12 +6679,12 @@ function collect(command, out, depth) {
6629
6679
  const f = parseShared(command);
6630
6680
  if (typeof f === "symbol") return;
6631
6681
  const contexts = depth === 0 ? localContexts(f) : /* @__PURE__ */ new Map();
6632
- syntax7.Walk(f, (node) => {
6633
- if (node && syntax7.NodeType(node) === "CallExpr") {
6682
+ walk(f, (node) => {
6683
+ if (node && node.kind === "CallExpr") {
6634
6684
  const words = (node.Args || []).map((a) => resolveWordLiteral(a));
6635
6685
  const start = out.length;
6636
6686
  if (words.length > 0) fromCall(words, out, depth);
6637
- const steps = contexts.get(node.Pos().Offset());
6687
+ const steps = contexts.get(node.pos);
6638
6688
  for (let i = start; i < out.length; i++) {
6639
6689
  if (["npx", "bunx", "npm exec"].includes(out[i].manager)) {
6640
6690
  if (!steps) out[i].localCwd = null;
@@ -6681,7 +6731,7 @@ function collect2(command, out, depth) {
6681
6731
  try {
6682
6732
  walkCommandScope(command, (node) => {
6683
6733
  const n = node;
6684
- if (!n || syntax8.NodeType(n) !== "CallExpr") return true;
6734
+ if (!n || n.kind !== "CallExpr") return true;
6685
6735
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
6686
6736
  if (words.length === 0) return true;
6687
6737
  const prefix = (n.Assigns || []).filter((a) => a?.Name?.Value).map(
@@ -8066,12 +8116,12 @@ function extractContentDestinations(text) {
8066
8116
  function extractArgDestinations(args) {
8067
8117
  const out = /* @__PURE__ */ new Set();
8068
8118
  try {
8069
- walk(args, void 0, out, 0);
8119
+ walk2(args, void 0, out, 0);
8070
8120
  } catch {
8071
8121
  }
8072
8122
  return [...out];
8073
8123
  }
8074
- function walk(value, key, out, depth) {
8124
+ function walk2(value, key, out, depth) {
8075
8125
  if (out.size >= MAX_DESTINATIONS || depth > 12) return;
8076
8126
  if (typeof value === "string") {
8077
8127
  const s = value.length > MAX_SCAN_CHARS ? value.slice(0, MAX_SCAN_CHARS) : value;
@@ -8090,12 +8140,12 @@ function walk(value, key, out, depth) {
8090
8140
  return;
8091
8141
  }
8092
8142
  if (Array.isArray(value)) {
8093
- for (const v of value) walk(v, key, out, depth + 1);
8143
+ for (const v of value) walk2(v, key, out, depth + 1);
8094
8144
  return;
8095
8145
  }
8096
8146
  if (value && typeof value === "object") {
8097
8147
  for (const [k, v] of Object.entries(value))
8098
- walk(v, k, out, depth + 1);
8148
+ walk2(v, k, out, depth + 1);
8099
8149
  }
8100
8150
  }
8101
8151
  function destinationDomain(dest) {
@@ -8747,9 +8797,9 @@ function classifyCall(head, args, prefixes, env, state, out) {
8747
8797
  function walkCalls(command, out, depth, state) {
8748
8798
  const f = parseShared(command);
8749
8799
  if (typeof f === "symbol" || !f) return;
8750
- syntax9.Walk(f, (node) => {
8800
+ walk(f, (node) => {
8751
8801
  if (!node) return false;
8752
- const type = syntax9.NodeType(node);
8802
+ const type = node.kind;
8753
8803
  if (type === "DeclClause") {
8754
8804
  for (const a of node.Args || []) if (a?.Name?.Value) state.env.add(a.Name.Value);
8755
8805
  return true;
@@ -8890,7 +8940,7 @@ function matchCanaryArgs(args, values) {
8890
8940
  if (values.length === 0) return null;
8891
8941
  const needles = prepare(values);
8892
8942
  if (needles.length === 0) return null;
8893
- const walk2 = (v, depth, fieldPath) => {
8943
+ const walk3 = (v, depth, fieldPath) => {
8894
8944
  if (depth > MAX_DEPTH4) return null;
8895
8945
  if (typeof v === "string") {
8896
8946
  const hit = matchPrepared(v, needles);
@@ -8899,31 +8949,31 @@ function matchCanaryArgs(args, values) {
8899
8949
  const trimmed = v.trim();
8900
8950
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
8901
8951
  try {
8902
- return walk2(JSON.parse(v), depth + 1, fieldPath);
8952
+ return walk3(JSON.parse(v), depth + 1, fieldPath);
8903
8953
  } catch {
8904
8954
  }
8905
8955
  }
8906
8956
  }
8907
8957
  return null;
8908
8958
  }
8909
- if (typeof v === "number" && Number.isFinite(v)) return walk2(String(v), depth, fieldPath);
8959
+ if (typeof v === "number" && Number.isFinite(v)) return walk3(String(v), depth, fieldPath);
8910
8960
  if (Array.isArray(v)) {
8911
8961
  for (let i = 0; i < v.length; i++) {
8912
- const h = walk2(v[i], depth + 1, `${fieldPath}[${i}]`);
8962
+ const h = walk3(v[i], depth + 1, `${fieldPath}[${i}]`);
8913
8963
  if (h) return h;
8914
8964
  }
8915
8965
  return null;
8916
8966
  }
8917
8967
  if (v && typeof v === "object") {
8918
8968
  for (const [k, child] of Object.entries(v)) {
8919
- const h = walk2(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
8969
+ const h = walk3(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
8920
8970
  if (h) return h;
8921
8971
  }
8922
8972
  }
8923
8973
  return null;
8924
8974
  };
8925
8975
  try {
8926
- return walk2(args, 0, "");
8976
+ return walk3(args, 0, "");
8927
8977
  } catch (e) {
8928
8978
  console.error(
8929
8979
  "[node9 engine] canary args walk failed:",
@@ -8932,7 +8982,7 @@ function matchCanaryArgs(args, values) {
8932
8982
  return null;
8933
8983
  }
8934
8984
  }
8935
- 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, 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, 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, BATCH_SEPARATOR, 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, 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;
8985
+ 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, 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, 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, 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, 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, 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;
8936
8986
  var init_dist = __esm({
8937
8987
  "packages/policy-engine/dist/index.mjs"() {
8938
8988
  "use strict";
@@ -11580,6 +11630,61 @@ var init_dist = __esm({
11580
11630
  return s.untrustedContent.afterExposure === "log-only" ? "log" : "review";
11581
11631
  }
11582
11632
  };
11633
+ ({ syntax } = mvdanSh);
11634
+ KINDS = {
11635
+ File: { nodes: ["Stmts"] },
11636
+ Stmt: { nodes: ["Cmd", "Redirs"], scalars: ["Negated", "Background", "Coprocess"] },
11637
+ CallExpr: { nodes: ["Assigns", "Args"] },
11638
+ Assign: { nodes: ["Name", "Value", "Index", "Array"], scalars: ["Append", "Naked"] },
11639
+ Word: { nodes: ["Parts"] },
11640
+ Lit: { scalars: ["Value"] },
11641
+ SglQuoted: { scalars: ["Value", "Dollar"] },
11642
+ DblQuoted: { nodes: ["Parts"], scalars: ["Dollar"] },
11643
+ ParamExp: {
11644
+ nodes: ["Param", "Index", "Slice", "Repl", "Exp"],
11645
+ scalars: ["Short", "Excl", "Length", "Width"]
11646
+ },
11647
+ CmdSubst: { nodes: ["Stmts"], scalars: ["Backquotes", "TempFile", "ReplyVar"] },
11648
+ ArithmExp: { nodes: ["X"], scalars: ["Bracket", "Unsigned"] },
11649
+ ArithmCmd: { nodes: ["X"], scalars: ["Unsigned"] },
11650
+ ProcSubst: { nodes: ["Stmts"], scalars: ["Op"] },
11651
+ ExtGlob: { nodes: ["Pattern"], scalars: ["Op"] },
11652
+ BraceExp: { nodes: ["Elems"], scalars: ["Sequence"] },
11653
+ // only with SplitBraces, unused here
11654
+ BinaryCmd: { nodes: ["X", "Y"], scalars: ["Op"] },
11655
+ BinaryArithm: { nodes: ["X", "Y"], scalars: ["Op"] },
11656
+ UnaryArithm: { nodes: ["X"], scalars: ["Op", "Post"] },
11657
+ ParenArithm: { nodes: ["X"] },
11658
+ BinaryTest: { nodes: ["X", "Y"], scalars: ["Op"] },
11659
+ UnaryTest: { nodes: ["X"], scalars: ["Op"] },
11660
+ ParenTest: { nodes: ["X"] },
11661
+ Redirect: { nodes: ["N", "Word", "Hdoc"], scalars: ["Op"] },
11662
+ Block: { nodes: ["Stmts"] },
11663
+ Subshell: { nodes: ["Stmts"] },
11664
+ IfClause: { nodes: ["Cond", "Then", "Else"] },
11665
+ WhileClause: { nodes: ["Cond", "Do"], scalars: ["Until"] },
11666
+ ForClause: { nodes: ["Loop", "Do"], scalars: ["Select"] },
11667
+ WordIter: { nodes: ["Name", "Items"] },
11668
+ CStyleLoop: { nodes: ["Init", "Cond", "Post"] },
11669
+ CaseClause: { nodes: ["Word", "Items"] },
11670
+ CaseItem: { nodes: ["Patterns", "Stmts"], scalars: ["Op"] },
11671
+ FuncDecl: { nodes: ["Name", "Body"], scalars: ["RsrvWord"] },
11672
+ DeclClause: { nodes: ["Variant", "Args"], notWalked: ["Variant"] },
11673
+ LetClause: { nodes: ["Exprs"] },
11674
+ TimeClause: { nodes: ["Stmt"], scalars: ["PosixFormat"] },
11675
+ CoprocClause: { nodes: ["Name", "Stmt"] },
11676
+ TestClause: { nodes: ["X"] },
11677
+ TestDecl: { nodes: ["Description", "Body"] },
11678
+ ArrayExpr: { nodes: ["Elems"] },
11679
+ ArrayElem: { nodes: ["Index", "Value"] },
11680
+ Comment: { scalars: ["Text"] }
11681
+ };
11682
+ STRUCTS = {
11683
+ "ParamExp.Slice": { nodes: ["Offset", "Length"], notWalked: ["Offset", "Length"] },
11684
+ "ParamExp.Repl": { nodes: ["Orig", "With"], scalars: ["All"] },
11685
+ "ParamExp.Exp": { nodes: ["Word"], scalars: ["Op"] }
11686
+ };
11687
+ unknownKinds = /* @__PURE__ */ new Set();
11583
11688
  INVISIBLE_RE = /[­͏؜᠎​-‏‪-‮⁠-⁤-︀-️]|[\u{E0000}-\u{E007F}]/gu;
11584
11689
  INVISIBLE_ONE = new RegExp(`^(?:${INVISIBLE_RE.source.split("|")[0]})$`, "u");
11585
11690
  HOMOGLYPHS = {
@@ -11865,8 +11970,8 @@ var init_dist = __esm({
11865
11970
  php: PHP
11866
11971
  };
11867
11972
  STRING_LITERAL = /(['"`])((?:\\.|(?!\1)[^\\\n]){1,4096})\1/g;
11868
- ({ syntax } = mvdanSh);
11869
- sharedParser = syntax.NewParser();
11973
+ ({ syntax: syntax2 } = mvdanSh2);
11974
+ sharedParser = syntax2.NewParser();
11870
11975
  MESSAGE_FLAGS = /* @__PURE__ */ new Set([
11871
11976
  "-m",
11872
11977
  "--message",
@@ -11900,7 +12005,7 @@ var init_dist = __esm({
11900
12005
  NORMALIZE_CACHE_MAX = 5e3;
11901
12006
  normalizeCache = /* @__PURE__ */ new Map();
11902
12007
  codeBodiesCache = /* @__PURE__ */ new Map();
11903
- AST_CACHE_MAX = 5e3;
12008
+ AST_CACHE_MAX = 256;
11904
12009
  astCache = /* @__PURE__ */ new Map();
11905
12010
  PARSE_FAIL = /* @__PURE__ */ Symbol("parse-fail");
11906
12011
  INTERPRETER_LINE = /^#![ \t]*[\w./+-]+(?:[ \t]+[\w./+=:-]+)*[ \t]*\r?(?=\n|$)/;
@@ -12885,7 +12990,7 @@ var init_dist = __esm({
12885
12990
  ARGV_FIELDS = ["args", "argv"];
12886
12991
  BARE_WORD = /^[A-Za-z0-9_./+:@%,-]+$/;
12887
12992
  MAX_ARGV_CHARACTERS = 262144;
12888
- ({ syntax: syntax2 } = mvdanSh2);
12993
+ ({ syntax: syntax3 } = mvdanSh3);
12889
12994
  MAX_ALTERNATIVES = 64;
12890
12995
  MAX_CALL_DEPTH2 = 4;
12891
12996
  MAX_CALL_WALKS2 = 256;
@@ -12977,7 +13082,6 @@ var init_dist = __esm({
12977
13082
  );
12978
13083
  exempt = (p) => SYSTEM_DIRS_EXEMPT.some((d) => within(p, d));
12979
13084
  RANK = { allow: 0, review: 1, block: 2 };
12980
- ({ syntax: syntax3 } = mvdanSh3);
12981
13085
  SEQUENCE_OPS = (() => {
12982
13086
  const ops = /* @__PURE__ */ new Set();
12983
13087
  for (const text of ["x && y", "x || y"]) {
@@ -16138,7 +16242,6 @@ zoo`.split("\n");
16138
16242
  );
16139
16243
  NEVER_NEGATED = /* @__PURE__ */ new Set([SIGNALS[1].any[0]]);
16140
16244
  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;
16141
- ({ syntax: syntax4 } = mvdanSh4);
16142
16245
  RDR_IN = (() => {
16143
16246
  try {
16144
16247
  return parseShared("x <y").Stmts[0].Redirs[0].Op;
@@ -16167,7 +16270,6 @@ zoo`.split("\n");
16167
16270
  "tar"
16168
16271
  ]);
16169
16272
  LITERAL_VERBS = /* @__PURE__ */ new Set(["echo", "printf", ":", "true", "touch", "sed"]);
16170
- ({ syntax: syntax5 } = mvdanSh5);
16171
16273
  GIT_PRESCREEN_RE = /git|husky/i;
16172
16274
  MAX_PAYLOAD_DEPTH2 = 8;
16173
16275
  MAX_ALIAS_DEPTH = 5;
@@ -16236,7 +16338,7 @@ zoo`.split("\n");
16236
16338
  visit(node, depth) {
16237
16339
  if (!node) return false;
16238
16340
  const n = node;
16239
- const type = syntax5.NodeType(n);
16341
+ const type = n.kind;
16240
16342
  if (type === "Stmt") {
16241
16343
  this.visitHeredocShell(n, depth);
16242
16344
  return true;
@@ -16244,7 +16346,7 @@ zoo`.split("\n");
16244
16346
  if (type === "ForClause") {
16245
16347
  const loop = n.Loop;
16246
16348
  const name = loop?.Name?.Value;
16247
- if (name && syntax5.NodeType(loop) === "WordIter") {
16349
+ if (name && loop.kind === "WordIter") {
16248
16350
  const items = (loop.Items || []).map((w) => resolveWordLiteral(w));
16249
16351
  const literal = items.length > 0 && items.every((v) => v !== null);
16250
16352
  this.loopVars.set(name, literal ? items.slice(0, MAX_LOOP_ITEMS) : null);
@@ -16311,7 +16413,7 @@ zoo`.split("\n");
16311
16413
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16312
16414
  visitHeredocShell(stmt, depth) {
16313
16415
  const cmd = stmt.Cmd;
16314
- if (!cmd || syntax5.NodeType(cmd) !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
16416
+ if (!cmd || cmd.kind !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
16315
16417
  const redirs = stmt.Redirs || [];
16316
16418
  const hdoc = redirs.find((r) => r?.Hdoc && (r.N == null || r.N.Value === "0"));
16317
16419
  if (!hdoc) return;
@@ -16565,7 +16667,6 @@ zoo`.split("\n");
16565
16667
  ]);
16566
16668
  SETTINGS_RE = /\/(?:\.claude\/settings(?:\.local)?\.json|\.gemini\/settings\.json|\.codex\/hooks\.json|\.cursor\/hooks\.json)$/i;
16567
16669
  HOOK_WORDS_RE = /"hooks"|\b(PreToolUse|PostToolUse|UserPromptSubmit|Notification|Stop|SubagentStop|SessionStart|SessionEnd|PreCompact|BeforeTool|AfterTool)\b|"command"\s*:/;
16568
- ({ syntax: syntax6 } = mvdanSh6);
16569
16670
  SHELLS = /* @__PURE__ */ new Set([...SHELL_INTERPRETERS, "mksh", "ash", "csh", "tcsh"]);
16570
16671
  NETCATS = /* @__PURE__ */ new Set(["nc", "ncat", "netcat", "nc.traditional", "nc.openbsd"]);
16571
16672
  NET_CLIENTS = /* @__PURE__ */ new Set([...NETCATS, "telnet", "socat"]);
@@ -16623,7 +16724,7 @@ zoo`.split("\n");
16623
16724
  const f = parseShared(command);
16624
16725
  if (!f || typeof f !== "object" || !f.Stmts) return false;
16625
16726
  try {
16626
- syntax6.Walk(f, (node) => this.visit(node, depth));
16727
+ walk(f, (node) => this.visit(node, depth));
16627
16728
  } catch {
16628
16729
  return false;
16629
16730
  }
@@ -16662,7 +16763,7 @@ zoo`.split("\n");
16662
16763
  }
16663
16764
  visit(n, depth) {
16664
16765
  if (!n) return false;
16665
- const type = syntax6.NodeType(n);
16766
+ const type = n.kind;
16666
16767
  if (type === "Stmt") {
16667
16768
  this.visitStmt(n, depth);
16668
16769
  return true;
@@ -16682,7 +16783,7 @@ zoo`.split("\n");
16682
16783
  const redirs = redirectWords(stmt);
16683
16784
  const toSocket = redirs.some((w) => w !== null && DEV_NET_RE.test(w));
16684
16785
  if (!cmd) return;
16685
- const type = syntax6.NodeType(cmd);
16786
+ const type = cmd.kind;
16686
16787
  if (type !== "CallExpr" || wordsOf(cmd).length > 0) {
16687
16788
  if (this.readsNetFd(stmt) && runsCommandsIn(stmt)) {
16688
16789
  this.reverseShell("commands are read from a network socket opened with exec");
@@ -16768,7 +16869,7 @@ zoo`.split("\n");
16768
16869
  const stages = [];
16769
16870
  const flatten = (s) => {
16770
16871
  const c = s?.Cmd;
16771
- if (c && syntax6.NodeType(c) === "BinaryCmd" && isPipeOp(c.Op)) {
16872
+ if (c && c.kind === "BinaryCmd" && isPipeOp(c.Op)) {
16772
16873
  flatten(c.X);
16773
16874
  flatten(c.Y);
16774
16875
  } else stages.push(s);
@@ -16790,8 +16891,8 @@ zoo`.split("\n");
16790
16891
  sinks.set(i, socketHosts(st));
16791
16892
  }
16792
16893
  if (!c) return;
16793
- if (syntax6.NodeType(c) === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
16794
- if (syntax6.NodeType(c) !== "CallExpr") {
16894
+ if (c.kind === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
16895
+ if (c.kind !== "CallExpr") {
16795
16896
  if (runsCommandsIn(st)) shell = i;
16796
16897
  return;
16797
16898
  }
@@ -16832,10 +16933,10 @@ zoo`.split("\n");
16832
16933
  /** A word (or assignment value) whose text includes an env dump's output. */
16833
16934
  carriesEnv(word) {
16834
16935
  let hit = false;
16835
- syntax6.Walk(word, (node) => {
16936
+ walk(word, (node) => {
16836
16937
  if (hit || !node) return false;
16837
16938
  const n = node;
16838
- const t = syntax6.NodeType(n);
16939
+ const t = n.kind;
16839
16940
  if (t === "ParamExp" && n.Param?.Value && this.envVars.has(n.Param.Value)) {
16840
16941
  hit = true;
16841
16942
  return false;
@@ -16852,11 +16953,11 @@ zoo`.split("\n");
16852
16953
  stmtsDumpEnv(stmts) {
16853
16954
  let hit = false;
16854
16955
  for (const s of stmts) {
16855
- syntax6.Walk(s, (node) => {
16956
+ walk(s, (node) => {
16856
16957
  if (hit || !node) return false;
16857
16958
  const n = node;
16858
- const t = syntax6.NodeType(n);
16859
- if (t === "Stmt" && n.Cmd && syntax6.NodeType(n.Cmd) === "CallExpr") {
16959
+ const t = n.kind;
16960
+ if (t === "Stmt" && n.Cmd && n.Cmd.kind === "CallExpr") {
16860
16961
  const words = wordsOf(n.Cmd);
16861
16962
  if (words.length > 0 && dumpsEnv(words, n)) hit = true;
16862
16963
  }
@@ -16873,7 +16974,6 @@ zoo`.split("\n");
16873
16974
  this.run(payload, depth + 1);
16874
16975
  }
16875
16976
  };
16876
- ({ syntax: syntax7 } = mvdanSh7);
16877
16977
  NPM_INSTALL_VERBS = /* @__PURE__ */ new Set([
16878
16978
  "install",
16879
16979
  "i",
@@ -17255,7 +17355,6 @@ zoo`.split("\n");
17255
17355
  SHELLS2 = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "ksh", "ash"]);
17256
17356
  MAX_NESTING = 3;
17257
17357
  SHELL_VALUE_FLAGS = /* @__PURE__ */ new Set(["--rcfile", "--init-file", "-O", "+O", "-o", "+o"]);
17258
- ({ syntax: syntax8 } = mvdanSh8);
17259
17358
  NPM_FAMILY = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "npx", "pnpx", "bunx"]);
17260
17359
  PIP_FAMILY = /* @__PURE__ */ new Set(["pip", "pip3", "uv", "uvx", "pipx", "pipenv"]);
17261
17360
  NPM_FETCH_VERBS = /* @__PURE__ */ new Set([
@@ -17787,7 +17886,6 @@ zoo`.split("\n");
17787
17886
  ACCOUNT_KEY_RE = /("(?:iban|account|account_number|accountNumber)"\s*:\s*")([A-Za-z0-9 .-]{6,40})(")/g;
17788
17887
  ACCOUNT_VALUE_RE = /"([A-Z]{2}\d{2}[A-Z0-9]{11,30})"/g;
17789
17888
  MAX_MASK_DEPTH = 64;
17790
- ({ syntax: syntax9 } = mvdanSh9);
17791
17889
  EMPTY = {
17792
17890
  fetches: false,
17793
17891
  sends: false,