@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.js CHANGED
@@ -680,6 +680,62 @@ function resolveCheckMap(settings) {
680
680
  for (const c of CHECKS) out[c.id] = checkValue(settings, c.id);
681
681
  return out;
682
682
  }
683
+ function isGoNode(v) {
684
+ return v !== null && typeof v === "object" && typeof v.Pos === "function";
685
+ }
686
+ function toPlainTree(goNode) {
687
+ const kind = syntax.NodeType(goNode);
688
+ const out = { kind, pos: goNode.Pos().Offset(), end: goNode.End().Offset() };
689
+ const spec = KINDS[kind];
690
+ if (!spec) {
691
+ unknownKinds.add(kind);
692
+ return out;
693
+ }
694
+ convertFields(goNode, spec, out, kind);
695
+ return out;
696
+ }
697
+ function convertFields(goNode, spec, out, kind) {
698
+ for (const f of spec.scalars ?? []) out[f] = goNode[f];
699
+ for (const f of spec.nodes ?? []) {
700
+ const v = goNode[f];
701
+ if (v === void 0 || v === null) {
702
+ out[f] = null;
703
+ } else if (Array.isArray(v)) {
704
+ out[f] = v.map((c) => isGoNode(c) ? toPlainTree(c) : c);
705
+ } else if (isGoNode(v)) {
706
+ out[f] = toPlainTree(v);
707
+ } else if (typeof v === "object" && STRUCTS[`${kind}.${f}`]) {
708
+ const sub = { struct: `${kind}.${f}` };
709
+ convertFields(v, STRUCTS[`${kind}.${f}`], sub, `${kind}.${f}`);
710
+ out[f] = sub;
711
+ } else {
712
+ out[f] = v;
713
+ }
714
+ }
715
+ }
716
+ function childrenOf(n) {
717
+ const spec = n.kind ? KINDS[n.kind] : STRUCTS[n.struct];
718
+ if (!spec?.nodes) return [];
719
+ const out = [];
720
+ for (const f of spec.nodes) {
721
+ if (spec.notWalked?.includes(f)) continue;
722
+ const v = n[f];
723
+ if (!v) continue;
724
+ if (Array.isArray(v)) {
725
+ for (const c of v) if (c) out.push(c);
726
+ } else if (v.kind) {
727
+ out.push(v);
728
+ } else if (v.struct) {
729
+ out.push(...childrenOf(v));
730
+ }
731
+ }
732
+ return out;
733
+ }
734
+ function walk(root, fn) {
735
+ if (!root) return;
736
+ if (!fn(root)) return;
737
+ for (const c of childrenOf(root)) walk(c, fn);
738
+ }
683
739
  function isInvisibleChar(char) {
684
740
  return INVISIBLE_ONE.test(char);
685
741
  }
@@ -835,7 +891,7 @@ function judgeInlineCode(language, code2, isProtected) {
835
891
  }
836
892
  function isCatHeredocOrLit(part) {
837
893
  if (!part) return false;
838
- const t = syntax.NodeType(part);
894
+ const t = part.kind;
839
895
  if (t === "Lit") return true;
840
896
  if (t !== "CmdSubst") return false;
841
897
  const stmts = part.Stmts || [];
@@ -845,9 +901,9 @@ function isCatHeredocOrLit(part) {
845
901
  const hasHeredoc = redirs.some((r) => r && r.Hdoc);
846
902
  if (!hasHeredoc) return false;
847
903
  const cmd = stmt.Cmd;
848
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return false;
904
+ if (!cmd || cmd.kind !== "CallExpr") return false;
849
905
  const firstArg2 = cmd.Args?.[0]?.Parts || [];
850
- if (firstArg2.length !== 1 || syntax.NodeType(firstArg2[0]) !== "Lit") return false;
906
+ if (firstArg2.length !== 1 || firstArg2[0].kind !== "Lit") return false;
851
907
  return (firstArg2[0].Value || "").toLowerCase() === "cat";
852
908
  }
853
909
  function parseShared(command) {
@@ -859,7 +915,7 @@ function parseShared(command) {
859
915
  }
860
916
  let parsed;
861
917
  try {
862
- parsed = sharedParser.Parse(command, "cmd");
918
+ parsed = toPlainTree(sharedParser.Parse(command, "cmd"));
863
919
  } catch {
864
920
  parsed = PARSE_FAIL;
865
921
  }
@@ -920,10 +976,10 @@ function fileAccessViewImpl(command) {
920
976
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
921
977
  const edits = [];
922
978
  try {
923
- syntax.Walk(f, (node) => {
979
+ walk(f, (node) => {
924
980
  if (!node) return false;
925
981
  const n = node;
926
- if (syntax.NodeType(n) !== "CallExpr") return true;
982
+ if (n.kind !== "CallExpr") return true;
927
983
  const args = n.Args || [];
928
984
  const words = args.map((a) => resolveWordLiteral(a));
929
985
  const head = unwrapCommandHead(words);
@@ -935,8 +991,8 @@ function fileAccessViewImpl(command) {
935
991
  if (!PROGRAM_DIR.test(word)) continue;
936
992
  const name = word.split(/[\\/]/).pop() ?? "";
937
993
  if (!name) continue;
938
- const s = at(args[i].Pos().Offset());
939
- const e = at(args[i].End().Offset());
994
+ const s = at(args[i].pos);
995
+ const e = at(args[i].end);
940
996
  if (s < 0 || e < 0) continue;
941
997
  edits.push([s, e, name]);
942
998
  }
@@ -964,10 +1020,10 @@ function literalPayloadsOf(command, depth) {
964
1020
  if (f === PARSE_FAIL) return [];
965
1021
  const out = [];
966
1022
  try {
967
- syntax.Walk(f, (node) => {
1023
+ walk(f, (node) => {
968
1024
  if (!node || out.length >= MAX_READING_PAYLOADS) return false;
969
1025
  const n = node;
970
- if (syntax.NodeType(n) !== "CallExpr") return true;
1026
+ if (n.kind !== "CallExpr") return true;
971
1027
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
972
1028
  if (words.length === 0) return true;
973
1029
  const payload = literalShellPayload(words, baseWord(words[0]));
@@ -987,23 +1043,23 @@ function foldCommandWords(reading) {
987
1043
  const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
988
1044
  const edits = [];
989
1045
  try {
990
- syntax.Walk(f, (node) => {
1046
+ walk(f, (node) => {
991
1047
  if (!node) return false;
992
1048
  const n = node;
993
- if (syntax.NodeType(n) !== "CallExpr") return true;
1049
+ if (n.kind !== "CallExpr") return true;
994
1050
  const args = n.Args || [];
995
1051
  const words = args.map((a) => resolveWordLiteral(a));
996
1052
  const folded = words.map((w) => w === null ? null : foldHomoglyphs(w));
997
1053
  const head = unwrapCommandHead(folded);
998
1054
  for (let i = 0; i <= head && i < args.length; i++) {
999
1055
  const parts = args[i].Parts || [];
1000
- if (parts.length !== 1 || syntax.NodeType(parts[0]) !== "Lit") continue;
1056
+ if (parts.length !== 1 || parts[0].kind !== "Lit") continue;
1001
1057
  const value = parts[0].Value ?? "";
1002
1058
  const word = folded[i];
1003
1059
  if (word === null || word === value || !/[^\x00-\x7f]/.test(value)) continue;
1004
1060
  if (!/^[A-Za-z0-9._/-]+$/.test(word)) continue;
1005
- const s = at(args[i].Pos().Offset());
1006
- const e = at(args[i].End().Offset());
1061
+ const s = at(args[i].pos);
1062
+ const e = at(args[i].end);
1007
1063
  if (s < 0 || e < 0) continue;
1008
1064
  edits.push([s, e, word]);
1009
1065
  }
@@ -1040,10 +1096,10 @@ function interpreterHeredocSpans(f, at) {
1040
1096
  const stmts = f?.Stmts || [];
1041
1097
  const candidates2 = [];
1042
1098
  let unsafe = false;
1043
- syntax.Walk(f, (node) => {
1099
+ walk(f, (node) => {
1044
1100
  if (!node || unsafe) return false;
1045
1101
  const n = node;
1046
- const t = syntax.NodeType(n);
1102
+ const t = n.kind;
1047
1103
  if (t === "FuncDecl") {
1048
1104
  unsafe = true;
1049
1105
  return false;
@@ -1063,7 +1119,7 @@ function interpreterHeredocSpans(f, at) {
1063
1119
  });
1064
1120
  if (unsafe) return [];
1065
1121
  for (const st of stmts) {
1066
- if (!st?.Cmd || syntax.NodeType(st.Cmd) !== "CallExpr") continue;
1122
+ if (!st?.Cmd || st.Cmd.kind !== "CallExpr") continue;
1067
1123
  const words = (st.Cmd.Args || []).map((a) => resolveWordLiteral(a));
1068
1124
  const name = (words[0] ?? "").toLowerCase();
1069
1125
  if (!STDIN_CODE_INTERPRETERS.test(name)) continue;
@@ -1078,8 +1134,8 @@ function interpreterHeredocSpans(f, at) {
1078
1134
  if (stdin.length !== 1 || others > 0) continue;
1079
1135
  const r = stdin[0];
1080
1136
  if (heredocText(r.Hdoc) === null) continue;
1081
- const hs = at(r.Hdoc.Pos().Offset());
1082
- const he = at(r.Hdoc.End().Offset());
1137
+ const hs = at(r.Hdoc.pos);
1138
+ const he = at(r.Hdoc.end);
1083
1139
  if (hs < 0 || he < 0 || he <= hs) continue;
1084
1140
  spans.push([hs, he]);
1085
1141
  }
@@ -1099,24 +1155,24 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1099
1155
  strips.push([hs, he]);
1100
1156
  msgSpans.add(`${hs}:${he}`);
1101
1157
  }
1102
- syntax.Walk(f, (node) => {
1158
+ walk(f, (node) => {
1103
1159
  if (!node) return false;
1104
1160
  const n = node;
1105
- if (syntax.NodeType(n) !== "CallExpr") return true;
1161
+ if (n.kind !== "CallExpr") return true;
1106
1162
  const args = n.Args || [];
1107
1163
  for (let i = 0; i < args.length - 1; i++) {
1108
1164
  const argParts = args[i].Parts || [];
1109
- if (argParts.length !== 1 || syntax.NodeType(argParts[0]) !== "Lit") continue;
1165
+ if (argParts.length !== 1 || argParts[0].kind !== "Lit") continue;
1110
1166
  const flagVal = argParts[0].Value || "";
1111
1167
  if (!MESSAGE_FLAGS.has(flagVal.toLowerCase())) continue;
1112
1168
  const next = args[i + 1];
1113
1169
  const nextParts = next.Parts || [];
1114
1170
  if (nextParts.length !== 1) continue;
1115
1171
  const quotedNode = nextParts[0];
1116
- const nt = syntax.NodeType(quotedNode);
1172
+ const nt = quotedNode.kind;
1117
1173
  const markStrip = () => {
1118
- const s = at(next.Pos().Offset());
1119
- const e = at(next.End().Offset());
1174
+ const s = at(next.pos);
1175
+ const e = at(next.end);
1120
1176
  if (s < 0 || e < 0) return;
1121
1177
  strips.push([s, e]);
1122
1178
  msgSpans.add(`${s}:${e}`);
@@ -1125,7 +1181,7 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1125
1181
  markStrip();
1126
1182
  } else if (nt === "DblQuoted") {
1127
1183
  const innerParts = quotedNode.Parts || [];
1128
- const allLit = innerParts.length === 0 || innerParts.every((p) => syntax.NodeType(p) === "Lit");
1184
+ const allLit = innerParts.length === 0 || innerParts.every((p) => p.kind === "Lit");
1129
1185
  if (allLit) {
1130
1186
  markStrip();
1131
1187
  } else if (innerParts.every((p) => isCatHeredocOrLit(p))) {
@@ -1134,8 +1190,8 @@ function normalizeCommandForPolicyImpl(command, codeBodies) {
1134
1190
  }
1135
1191
  }
1136
1192
  for (const arg of args) {
1137
- const s = at(arg.Pos().Offset());
1138
- const e = at(arg.End().Offset());
1193
+ const s = at(arg.pos);
1194
+ const e = at(arg.end);
1139
1195
  if (s < 0 || e < 0) continue;
1140
1196
  if (msgSpans.has(`${s}:${e}`)) continue;
1141
1197
  const resolved = resolveWordLiteral(arg);
@@ -1175,10 +1231,10 @@ function scanArgsForDynamicExec(args, startIdx) {
1175
1231
  let hasParamExp = false;
1176
1232
  let hasCurl = false;
1177
1233
  for (let i = startIdx; i < args.length; i++) {
1178
- syntax.Walk(args[i], (inner) => {
1234
+ walk(args[i], (inner) => {
1179
1235
  if (!inner) return false;
1180
1236
  const inn = inner;
1181
- const it = syntax.NodeType(inn);
1237
+ const it = inn.kind;
1182
1238
  if (it === "CmdSubst") hasCmdSubst = true;
1183
1239
  if (it === "ParamExp") hasParamExp = true;
1184
1240
  if (it === "Lit" && DOWNLOAD_CMDS.has(inn.Value?.toLowerCase())) hasCurl = true;
@@ -1191,15 +1247,16 @@ function scanArgsForDynamicExec(args, startIdx) {
1191
1247
  }
1192
1248
  function detectDangerousShellExec(command) {
1193
1249
  try {
1194
- const f = sharedParser.Parse(command, "cmd");
1250
+ const f = parseShared(command);
1251
+ if (f === PARSE_FAIL) return null;
1195
1252
  let result = null;
1196
1253
  const assigned = assignedNames(f);
1197
- syntax.Walk(f, (node) => {
1254
+ walk(f, (node) => {
1198
1255
  if (!node || result === "block") return false;
1199
1256
  const n = node;
1200
- if (syntax.NodeType(n) === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1257
+ if (n.kind === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1201
1258
  const call = n.Y.Cmd;
1202
- if (call && syntax.NodeType(call) === "CallExpr") {
1259
+ if (call && call.kind === "CallExpr") {
1203
1260
  const words = (call.Args || []).map((a) => resolveWordLiteral(a));
1204
1261
  const head2 = unwrapCommandHead(words);
1205
1262
  const name = (words[head2] ?? "").split("/").pop() ?? "";
@@ -1212,7 +1269,7 @@ function detectDangerousShellExec(command) {
1212
1269
  result = "review";
1213
1270
  }
1214
1271
  }
1215
- if (syntax.NodeType(n) !== "CallExpr") return true;
1272
+ if (n.kind !== "CallExpr") return true;
1216
1273
  const args = n.Args || [];
1217
1274
  if (args.length === 0) return true;
1218
1275
  const headWords = args.map(
@@ -1223,7 +1280,7 @@ function detectDangerousShellExec(command) {
1223
1280
  if (!lookup && (opaqueExecutable(args[0], assigned) || opaqueExecutable(args[head], assigned)))
1224
1281
  result = "review";
1225
1282
  const firstParts = args[0].Parts || [];
1226
- if (firstParts.length !== 1 || syntax.NodeType(firstParts[0]) !== "Lit") return true;
1283
+ if (firstParts.length !== 1 || firstParts[0].kind !== "Lit") return true;
1227
1284
  const cmdName = firstParts[0].Value?.toLowerCase() ?? "";
1228
1285
  if (cmdName === "eval") {
1229
1286
  const v = scanArgsForDynamicExec(args, 1);
@@ -1231,7 +1288,7 @@ function detectDangerousShellExec(command) {
1231
1288
  } else if (SHELL_INTERPRETERS.has(cmdName)) {
1232
1289
  for (let i = 1; i < args.length - 1; i++) {
1233
1290
  const flagParts = args[i].Parts || [];
1234
- if (flagParts.length !== 1 || syntax.NodeType(flagParts[0]) !== "Lit" || flagParts[0].Value !== "-c")
1291
+ if (flagParts.length !== 1 || flagParts[0].kind !== "Lit" || flagParts[0].Value !== "-c")
1235
1292
  continue;
1236
1293
  const v = scanArgsForDynamicExec(args, i + 1);
1237
1294
  if (v === "block" || v === "review" && result === null) result = v;
@@ -1255,8 +1312,7 @@ function isDefaultExpansion(part) {
1255
1312
  }
1256
1313
  function lookupSubstitution(part) {
1257
1314
  const stmts = part.Stmts ?? [];
1258
- if (stmts.length !== 1 || !stmts[0].Cmd || syntax.NodeType(stmts[0].Cmd) !== "CallExpr")
1259
- return null;
1315
+ if (stmts.length !== 1 || !stmts[0].Cmd || stmts[0].Cmd.kind !== "CallExpr") return null;
1260
1316
  const words = (stmts[0].Cmd.Args ?? []).map((a) => resolveWordLiteral(a));
1261
1317
  if (words.some((w) => w === null)) return null;
1262
1318
  if (words.length === 2 && words[0] === "which") return words[1];
@@ -1266,9 +1322,9 @@ function lookupSubstitution(part) {
1266
1322
  }
1267
1323
  function assignedNames(f) {
1268
1324
  const names = /* @__PURE__ */ new Set();
1269
- syntax.Walk(f, (node) => {
1325
+ walk(f, (node) => {
1270
1326
  if (!node) return false;
1271
- const kind = syntax.NodeType(node);
1327
+ const kind = node.kind;
1272
1328
  if (kind === "Assign" && node.Name?.Value) names.add(node.Name.Value);
1273
1329
  if (kind === "ForClause" && node.Loop?.Name?.Value) names.add(node.Loop.Name.Value);
1274
1330
  if (kind === "CallExpr") {
@@ -1283,7 +1339,7 @@ function assignedNames(f) {
1283
1339
  }
1284
1340
  function executableParts(word, assigned, quoted = false) {
1285
1341
  return (word?.Parts ?? []).flatMap((part) => {
1286
- const kind = syntax.NodeType(part);
1342
+ const kind = part.kind;
1287
1343
  if (kind === "DblQuoted") return executableParts(part, assigned, true);
1288
1344
  if (kind === "Lit") return [{ kind: "Lit", value: part.Value ?? "", quoted }];
1289
1345
  if (kind === "SglQuoted")
@@ -1351,10 +1407,10 @@ function chmodHasOpenPermMode(command) {
1351
1407
  if (f === PARSE_FAIL) return false;
1352
1408
  let found = false;
1353
1409
  try {
1354
- syntax.Walk(f, (node) => {
1410
+ walk(f, (node) => {
1355
1411
  if (!node || found) return false;
1356
1412
  const n = node;
1357
- if (syntax.NodeType(n) !== "CallExpr") return true;
1413
+ if (n.kind !== "CallExpr") return true;
1358
1414
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1359
1415
  if (words.length === 0) return true;
1360
1416
  const name = (words[0] ?? "").toLowerCase();
@@ -1407,11 +1463,11 @@ function redirStdinOps() {
1407
1463
  }
1408
1464
  function deriveBinaryOp(sample) {
1409
1465
  try {
1410
- const f = sharedParser.Parse(sample, "cmd");
1466
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
1411
1467
  let op = -1;
1412
- syntax.Walk(f, (node) => {
1468
+ walk(f, (node) => {
1413
1469
  const n = node;
1414
- if (n && syntax.NodeType(n) === "BinaryCmd" && op < 0) op = n.Op;
1470
+ if (n && n.kind === "BinaryCmd" && op < 0) op = n.Op;
1415
1471
  return true;
1416
1472
  });
1417
1473
  return op;
@@ -1485,7 +1541,7 @@ function heredocText(word) {
1485
1541
  const parts = word?.Parts ?? [];
1486
1542
  let out = "";
1487
1543
  for (const p of parts) {
1488
- if (syntax.NodeType(p) !== "Lit") return null;
1544
+ if (p.kind !== "Lit") return null;
1489
1545
  out += p.Value ?? "";
1490
1546
  }
1491
1547
  return out;
@@ -1521,7 +1577,7 @@ function attachedCode(interp, flag) {
1521
1577
  }
1522
1578
  function inlineExecCall(stmt, pipeFed) {
1523
1579
  const cmd = stmt?.Cmd;
1524
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return null;
1580
+ if (!cmd || cmd.kind !== "CallExpr") return null;
1525
1581
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1526
1582
  if (words.length === 0) return null;
1527
1583
  const headIdx = unwrapCommandHead(words);
@@ -1602,10 +1658,10 @@ function shellPayloadNeedsReview(payload) {
1602
1658
  let review = false;
1603
1659
  payloadNesting++;
1604
1660
  try {
1605
- syntax.Walk(f, (node) => {
1661
+ walk(f, (node) => {
1606
1662
  if (!node || review) return false;
1607
1663
  const n = node;
1608
- if (syntax.NodeType(n) !== "CallExpr") return true;
1664
+ if (n.kind !== "CallExpr") return true;
1609
1665
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1610
1666
  if (words.length === 0) return true;
1611
1667
  const h = unwrapCommandHead(words);
@@ -1639,10 +1695,10 @@ function inlineExecCalls(command) {
1639
1695
  if (f === PARSE_FAIL) return PARSE_FAIL;
1640
1696
  const calls = [];
1641
1697
  try {
1642
- syntax.Walk(f, (node) => {
1698
+ walk(f, (node) => {
1643
1699
  if (!node || calls.length >= MAX_INLINE_CALLS) return false;
1644
1700
  const n = node;
1645
- const t = syntax.NodeType(n);
1701
+ const t = n.kind;
1646
1702
  if (t === "BinaryCmd" && n.Y && !listOps().has(n.Op)) {
1647
1703
  const call = inlineExecCall(n.Y, true);
1648
1704
  if (call) calls.push(call);
@@ -1777,7 +1833,7 @@ function shellScriptOperands(command) {
1777
1833
  walkWithCalls(f, (node) => {
1778
1834
  if (!node) return false;
1779
1835
  const n = node;
1780
- if (syntax.NodeType(n) !== "CallExpr") return true;
1836
+ if (n.kind !== "CallExpr") return true;
1781
1837
  const callArgs = n.Args || [];
1782
1838
  if (callArgs.length === 0) return true;
1783
1839
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -1813,7 +1869,7 @@ function shellScriptOperands(command) {
1813
1869
  }
1814
1870
  function windowsDrivePathSpelling(word) {
1815
1871
  const parts = word?.Parts || [];
1816
- if (parts.length === 0 || !parts.every((p) => syntax.NodeType(p) === "Lit")) return null;
1872
+ if (parts.length === 0 || !parts.every((p) => p.kind === "Lit")) return null;
1817
1873
  const raw = parts.map((p) => p.Value ?? "").join("");
1818
1874
  return /^[A-Za-z]:\\[^\s'"$`]*$/.test(raw) ? raw : null;
1819
1875
  }
@@ -1851,15 +1907,15 @@ function recordTopLevelAssignments(f) {
1851
1907
  }
1852
1908
  function probeBinOp(src) {
1853
1909
  try {
1854
- const cmd = syntax.NewParser().Parse(src, "probe")?.Stmts?.[0]?.Cmd;
1855
- if (cmd && syntax.NodeType(cmd) === "BinaryCmd") return cmd.Op;
1910
+ const cmd = toPlainTree(syntax2.NewParser().Parse(src, "probe"))?.Stmts?.[0]?.Cmd;
1911
+ if (cmd && cmd.kind === "BinaryCmd") return cmd.Op;
1856
1912
  } catch {
1857
1913
  }
1858
1914
  return null;
1859
1915
  }
1860
1916
  function recordTopLevelStmt(stmt) {
1861
1917
  if (!stmt || !stmt.Cmd) return false;
1862
- const t = syntax.NodeType(stmt.Cmd);
1918
+ const t = stmt.Cmd.kind;
1863
1919
  if (t === "BinaryCmd") {
1864
1920
  if (!AND_OR_OPS.has(stmt.Cmd.Op)) return false;
1865
1921
  if (!recordTopLevelStmt(stmt.Cmd.X)) return false;
@@ -1869,7 +1925,7 @@ function recordTopLevelStmt(stmt) {
1869
1925
  if (t !== "CallExpr" && t !== "DeclClause") return false;
1870
1926
  let at = 0;
1871
1927
  try {
1872
- at = stmt.Pos().Offset();
1928
+ at = stmt.pos;
1873
1929
  } catch {
1874
1930
  at = 0;
1875
1931
  }
@@ -1880,14 +1936,14 @@ function recordTopLevelStmt(stmt) {
1880
1936
  }
1881
1937
  function recordAssignments(n, at) {
1882
1938
  if (!assignmentTable) return;
1883
- const t = syntax.NodeType(n);
1939
+ const t = n.kind;
1884
1940
  let assigns = [];
1885
1941
  if (t === "CallExpr") {
1886
1942
  if ((n.Args || []).length > 0) return;
1887
1943
  assigns = n.Assigns || [];
1888
1944
  } else if (t === "DeclClause") {
1889
1945
  if (!ASSIGNMENT_HEADS.has(n.Variant?.Value ?? "")) return;
1890
- assigns = (n.Args || []).filter((a) => syntax.NodeType(a) === "Assign");
1946
+ assigns = (n.Args || []).filter((a) => a.kind === "Assign");
1891
1947
  } else return;
1892
1948
  for (const a of assigns) {
1893
1949
  const name = a?.Name?.Value;
@@ -1896,13 +1952,13 @@ function recordAssignments(n, at) {
1896
1952
  }
1897
1953
  }
1898
1954
  function resolveTrivialSubst(part) {
1899
- if (syntax.NodeType(part) !== "CmdSubst") return void 0;
1955
+ if (part.kind !== "CmdSubst") return void 0;
1900
1956
  const stmts = part.Stmts || [];
1901
1957
  if (stmts.length !== 1) return void 0;
1902
1958
  const st = stmts[0];
1903
1959
  if ((st.Redirs || []).length > 0 || st.Negated || st.Background) return void 0;
1904
1960
  const cmd = st.Cmd;
1905
- if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return void 0;
1961
+ if (!cmd || cmd.kind !== "CallExpr") return void 0;
1906
1962
  if ((cmd.Assigns || []).length > 0) return void 0;
1907
1963
  const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
1908
1964
  if (words.length === 0 || words.some((w) => w === null)) return void 0;
@@ -1927,7 +1983,7 @@ function recordedExpansion(name) {
1927
1983
  return rec.value;
1928
1984
  }
1929
1985
  function isPlainParam(p) {
1930
- if (syntax.NodeType(p) !== "ParamExp") return false;
1986
+ if (p.kind !== "ParamExp") return false;
1931
1987
  return !(p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp);
1932
1988
  }
1933
1989
  function expandPlainParam(p) {
@@ -1939,9 +1995,9 @@ function expandPlainParam(p) {
1939
1995
  }
1940
1996
  function functionBodies(f) {
1941
1997
  const out = /* @__PURE__ */ new Map();
1942
- syntax.Walk(f, (node) => {
1998
+ walk(f, (node) => {
1943
1999
  const n = node;
1944
- if (n && syntax.NodeType(n) === "FuncDecl" && n.Name?.Value && n.Body) {
2000
+ if (n && n.kind === "FuncDecl" && n.Name?.Value && n.Body) {
1945
2001
  const list2 = out.get(n.Name.Value) ?? [];
1946
2002
  list2.push(n.Body);
1947
2003
  out.set(n.Name.Value, list2);
@@ -1952,10 +2008,10 @@ function functionBodies(f) {
1952
2008
  }
1953
2009
  function rebindsPositionals(body) {
1954
2010
  let found = false;
1955
- syntax.Walk(body, (node) => {
2011
+ walk(body, (node) => {
1956
2012
  const n = node;
1957
2013
  if (found || !n) return false;
1958
- if (syntax.NodeType(n) === "CallExpr") {
2014
+ if (n.kind === "CallExpr") {
1959
2015
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
1960
2016
  if (words[0] === "shift") found = true;
1961
2017
  else if (words[0] === "set" && words.slice(1).some((w) => w === null || w === "--" || !/^[-+]/.test(w)))
@@ -1975,7 +2031,7 @@ function tableBindings() {
1975
2031
  function walkWithCalls(f, visit2) {
1976
2032
  const bodies = functionBodies(f);
1977
2033
  if (bodies.size === 0) {
1978
- syntax.Walk(f, visit2);
2034
+ walk(f, visit2);
1979
2035
  return;
1980
2036
  }
1981
2037
  const seenCalls = /* @__PURE__ */ new Set();
@@ -2009,8 +2065,8 @@ function walkWithCalls(f, visit2) {
2009
2065
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2010
2066
  callDepth++;
2011
2067
  try {
2012
- if (body.Cmd && syntax.NodeType(body.Cmd) === "Block") recordTopLevelAssignments(body.Cmd);
2013
- syntax.Walk(body, step);
2068
+ if (body.Cmd && body.Cmd.kind === "Block") recordTopLevelAssignments(body.Cmd);
2069
+ walk(body, step);
2014
2070
  } finally {
2015
2071
  callDepth--;
2016
2072
  assignmentTable = outerTable;
@@ -2021,10 +2077,10 @@ function walkWithCalls(f, visit2) {
2021
2077
  const step = (node) => {
2022
2078
  if (!node) return false;
2023
2079
  const go = visit2(node);
2024
- if (go !== false && syntax.NodeType(node) === "CallExpr") inline(node);
2080
+ if (go !== false && node.kind === "CallExpr") inline(node);
2025
2081
  return go;
2026
2082
  };
2027
- syntax.Walk(f, step);
2083
+ walk(f, step);
2028
2084
  }
2029
2085
  function withAssignments(f, body) {
2030
2086
  const outerTable = assignmentTable;
@@ -2049,7 +2105,7 @@ function walkCommandScope(command, visit2) {
2049
2105
  if (f === PARSE_FAIL) return "parse-fail";
2050
2106
  withAssignments(f, () => {
2051
2107
  walkWithCalls(f, (node) => {
2052
- if (node && syntax.NodeType(node) === "Stmt") trackStatement(node);
2108
+ if (node && node.kind === "Stmt") trackStatement(node);
2053
2109
  return visit2(node);
2054
2110
  });
2055
2111
  });
@@ -2057,7 +2113,7 @@ function walkCommandScope(command, visit2) {
2057
2113
  }
2058
2114
  function trackStatement(n) {
2059
2115
  try {
2060
- currentStmtOffset = n.Pos().Offset();
2116
+ currentStmtOffset = n.pos;
2061
2117
  } catch {
2062
2118
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2063
2119
  }
@@ -2073,11 +2129,11 @@ function resolveWordLiteral(w) {
2073
2129
  return s;
2074
2130
  }
2075
2131
  function resolveWordPrefix(w) {
2076
- const walk2 = (parts) => {
2132
+ const walk3 = (parts) => {
2077
2133
  let s = "";
2078
2134
  for (const p of parts) {
2079
2135
  if (p && typeof p === "object" && Array.isArray(p.Parts) && p.Dollar !== void 0) {
2080
- const inner = walk2(p.Parts);
2136
+ const inner = walk3(p.Parts);
2081
2137
  s += inner.prefix;
2082
2138
  if (inner.dynamic) return { prefix: s, dynamic: true };
2083
2139
  continue;
@@ -2088,10 +2144,10 @@ function resolveWordPrefix(w) {
2088
2144
  }
2089
2145
  return { prefix: s, dynamic: false };
2090
2146
  };
2091
- return walk2(w?.Parts || []);
2147
+ return walk3(w?.Parts || []);
2092
2148
  }
2093
2149
  function resolvePart(p, inQuotes) {
2094
- const t = syntax.NodeType(p);
2150
+ const t = p.kind;
2095
2151
  if (t === "Lit") {
2096
2152
  const raw = p.Value ?? "";
2097
2153
  if (!inQuotes) return raw.replace(/\\(.)/g, "$1");
@@ -2187,7 +2243,7 @@ function extractShellDestinations(command) {
2187
2243
  () => walkWithCalls(f, (node) => {
2188
2244
  if (!node) return false;
2189
2245
  const n = node;
2190
- if (syntax.NodeType(n) === "Stmt") {
2246
+ if (n.kind === "Stmt") {
2191
2247
  trackStatement(n);
2192
2248
  for (const raw of redirectWords(n)) {
2193
2249
  const host2 = devNetRedirectHost(raw);
@@ -2199,7 +2255,7 @@ function extractShellDestinations(command) {
2199
2255
  out.push({ host: host2, binary, raw });
2200
2256
  }
2201
2257
  }
2202
- if (syntax.NodeType(n) !== "CallExpr") return true;
2258
+ if (n.kind !== "CallExpr") return true;
2203
2259
  const callArgs = n.Args || [];
2204
2260
  if (callArgs.length === 0) return true;
2205
2261
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2234,7 +2290,7 @@ function extractShellDestTokens(command) {
2234
2290
  () => walkWithCalls(f, (node) => {
2235
2291
  if (!node) return false;
2236
2292
  const n = node;
2237
- if (syntax.NodeType(n) === "Stmt") {
2293
+ if (n.kind === "Stmt") {
2238
2294
  trackStatement(n);
2239
2295
  for (const raw of redirectWords(n)) {
2240
2296
  const host2 = devNetRedirectHost(raw);
@@ -2246,7 +2302,7 @@ function extractShellDestTokens(command) {
2246
2302
  out.push({ token: host2, binary });
2247
2303
  }
2248
2304
  }
2249
- if (syntax.NodeType(n) !== "CallExpr") return true;
2305
+ if (n.kind !== "CallExpr") return true;
2250
2306
  const callArgs = n.Args || [];
2251
2307
  if (callArgs.length === 0) return true;
2252
2308
  const words = callArgs.map((a) => resolveWordLiteral(a));
@@ -2314,11 +2370,11 @@ function isWaivableCleanupTarget(p) {
2314
2370
  }
2315
2371
  function deriveRedirOp(sample) {
2316
2372
  try {
2317
- const f = sharedParser.Parse(sample, "cmd");
2373
+ const f = toPlainTree(sharedParser.Parse(sample, "cmd"));
2318
2374
  let op = -1;
2319
- syntax.Walk(f, (node) => {
2375
+ walk(f, (node) => {
2320
2376
  const n = node;
2321
- if (n && syntax.NodeType(n) === "Redirect" && op < 0) op = n.Op;
2377
+ if (n && n.kind === "Redirect" && op < 0) op = n.Op;
2322
2378
  return true;
2323
2379
  });
2324
2380
  return op;
@@ -2331,7 +2387,7 @@ function collectSameCommandCreations(f) {
2331
2387
  try {
2332
2388
  const stmts = Array.isArray(f?.Stmts) ? f.Stmts : [];
2333
2389
  for (const stmt of stmts) {
2334
- if (!stmt || !stmt.Cmd || syntax.NodeType(stmt.Cmd) !== "CallExpr") continue;
2390
+ if (!stmt || !stmt.Cmd || stmt.Cmd.kind !== "CallExpr") continue;
2335
2391
  const redirs = stmt.Redirs || [];
2336
2392
  if (!redirs.some((r) => r && REDIR_HEREDOC_OPS.has(r.Op))) continue;
2337
2393
  for (const r of redirs) {
@@ -2355,10 +2411,10 @@ function isRmCreatedInCommandCleanup(command) {
2355
2411
  let sawRm = false;
2356
2412
  let ok2 = true;
2357
2413
  try {
2358
- syntax.Walk(f, (node) => {
2414
+ walk(f, (node) => {
2359
2415
  if (!node || !ok2) return false;
2360
2416
  const n = node;
2361
- if (syntax.NodeType(n) !== "CallExpr") return true;
2417
+ if (n.kind !== "CallExpr") return true;
2362
2418
  const args = n.Args || [];
2363
2419
  const name = (resolveWordLiteral(args[0]) ?? "").toLowerCase();
2364
2420
  if (name !== "rm") return true;
@@ -2408,10 +2464,10 @@ function analyzeFsOperationImpl(command, depth = 0) {
2408
2464
  walkWithCalls(f, (node) => {
2409
2465
  if (!node || result?.verdict === "block") return false;
2410
2466
  const n = node;
2411
- const nodeType = syntax.NodeType(n);
2467
+ const nodeType = n.kind;
2412
2468
  if (nodeType === "Stmt") {
2413
2469
  try {
2414
- currentStmtOffset = n.Pos().Offset();
2470
+ currentStmtOffset = n.pos;
2415
2471
  } catch {
2416
2472
  currentStmtOffset = Number.MAX_SAFE_INTEGER;
2417
2473
  }
@@ -2924,11 +2980,12 @@ function analyzeShellCommand(command) {
2924
2980
  if (lower2.startsWith("-")) allTokens.push(lower2.replace(/^-+/, ""));
2925
2981
  };
2926
2982
  try {
2927
- const f = sharedParser.Parse(command, "cmd");
2928
- syntax.Walk(f, (node) => {
2983
+ const f = parseShared(command);
2984
+ if (f === PARSE_FAIL) throw new Error("parse failed");
2985
+ walk(f, (node) => {
2929
2986
  if (!node) return false;
2930
2987
  const n = node;
2931
- if (syntax.NodeType(n) !== "CallExpr") return true;
2988
+ if (n.kind !== "CallExpr") return true;
2932
2989
  const wordValues2 = (n.Args || []).map((arg) => {
2933
2990
  return (arg.Parts || []).map((p) => (p.Value ?? "").replace(/\\(.)/g, "$1")).join("");
2934
2991
  }).filter((s) => s.length > 0);
@@ -3200,7 +3257,7 @@ function runnablePrefix(command) {
3200
3257
  let text = command;
3201
3258
  for (let attempt = 0; attempt < 32; attempt++) {
3202
3259
  try {
3203
- return syntax2.NewParser().Parse(text, "");
3260
+ return toPlainTree(syntax3.NewParser().Parse(text, ""));
3204
3261
  } catch (error) {
3205
3262
  const message = String(typeof error?.Error === "function" ? error.Error() : error?.message);
3206
3263
  const line = Number(/^(\d+):/.exec(message)?.[1]);
@@ -3268,7 +3325,7 @@ function wordValues(word, state) {
3268
3325
  out2 = next.slice(0, MAX_ALTERNATIVES);
3269
3326
  };
3270
3327
  for (const node of nodes) {
3271
- const kind = syntax2.NodeType(node);
3328
+ const kind = node.kind;
3272
3329
  let pieces;
3273
3330
  if (kind === "ParamExp") pieces = paramValues(node, quoted);
3274
3331
  else if (kind === "DblQuoted") {
@@ -3336,9 +3393,9 @@ function collectShellFileAccesses(command, context = {}) {
3336
3393
  }
3337
3394
  function substitutions2(word, state, depth) {
3338
3395
  if (!word) return;
3339
- syntax2.Walk(word, (node) => {
3396
+ walk(word, (node) => {
3340
3397
  if (!node) return false;
3341
- if (["CmdSubst", "ProcSubst"].includes(syntax2.NodeType(node))) {
3398
+ if (["CmdSubst", "ProcSubst"].includes(node.kind)) {
3342
3399
  statements(node.Stmts ?? [], clone(state), depth + 1);
3343
3400
  return false;
3344
3401
  }
@@ -3762,7 +3819,7 @@ function collectShellFileAccesses(command, context = {}) {
3762
3819
  }
3763
3820
  function readsScriptFromStdin(stmt) {
3764
3821
  const cmd = stmt?.Cmd;
3765
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return false;
3822
+ if (!cmd || cmd.kind !== "CallExpr") return false;
3766
3823
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3767
3824
  const head = unwrapCommandHead(words);
3768
3825
  return SHELL_INTERPRETERS.has(base(words[head])) && shellConsumesPipe(words.slice(head + 1));
@@ -3776,7 +3833,7 @@ function collectShellFileAccesses(command, context = {}) {
3776
3833
  }
3777
3834
  function producedText(stmt) {
3778
3835
  const cmd = stmt?.Cmd;
3779
- if (!cmd || syntax2.NodeType(cmd) !== "CallExpr") return null;
3836
+ if (!cmd || cmd.kind !== "CallExpr") return null;
3780
3837
  const words = (cmd.Args ?? []).map((a) => resolveWordLiteral(a));
3781
3838
  if (words.some((w) => w === null)) return null;
3782
3839
  const head = unwrapCommandHead(words);
@@ -3795,7 +3852,7 @@ function collectShellFileAccesses(command, context = {}) {
3795
3852
  if (!stmt || depth > MAX_DEPTH) return;
3796
3853
  state.onSuccess = void 0;
3797
3854
  if (stmt.Background) state = clone(state);
3798
- const headWord = stmt.Cmd && syntax2.NodeType(stmt.Cmd) === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3855
+ const headWord = stmt.Cmd && stmt.Cmd.kind === "CallExpr" ? base(resolveWordLiteral(stmt.Cmd.Args?.[0])) : "";
3799
3856
  const sends = SENDING_STDIN.has(headWord);
3800
3857
  for (const redir of stmt.Redirs ?? []) {
3801
3858
  substitutions2(redir.Word, state, depth);
@@ -3811,7 +3868,7 @@ function collectShellFileAccesses(command, context = {}) {
3811
3868
  const cmd = stmt.Cmd;
3812
3869
  if (!cmd) return;
3813
3870
  stdinScript(stmt, state, depth);
3814
- switch (syntax2.NodeType(cmd)) {
3871
+ switch (cmd.kind) {
3815
3872
  case "CallExpr":
3816
3873
  call(cmd, state, depth);
3817
3874
  break;
@@ -3825,7 +3882,7 @@ function collectShellFileAccesses(command, context = {}) {
3825
3882
  for (; ; ) {
3826
3883
  segments2.unshift({ op: node.Op, part: node.Y });
3827
3884
  const left = node.X;
3828
- if (left?.Cmd && syntax2.NodeType(left.Cmd) === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3885
+ if (left?.Cmd && left.Cmd.kind === "BinaryCmd" && !left.Redirs?.length && !left.Negated && !left.Background)
3829
3886
  node = left.Cmd;
3830
3887
  else {
3831
3888
  segments2.unshift({ op: node.Op, part: left });
@@ -4121,13 +4178,13 @@ function pipelineTexts(command) {
4121
4178
  const visit2 = (stmt, depth) => {
4122
4179
  if (!stmt || depth > 64) return;
4123
4180
  const cmd = stmt.Cmd;
4124
- if (cmd && syntax3.NodeType(cmd) === "BinaryCmd" && SEQUENCE_OPS.has(cmd.Op)) {
4181
+ if (cmd && cmd.kind === "BinaryCmd" && SEQUENCE_OPS.has(cmd.Op)) {
4125
4182
  visit2(cmd.X, depth + 1);
4126
4183
  visit2(cmd.Y, depth + 1);
4127
4184
  return;
4128
4185
  }
4129
- const s = at(stmt.Pos().Offset());
4130
- const e = at(stmt.End().Offset());
4186
+ const s = at(stmt.pos);
4187
+ const e = at(stmt.end);
4131
4188
  const text = s >= 0 && e > s ? command.slice(s, e).replace(/[\s;&]+$/, "") : "";
4132
4189
  if (text) out.push(text);
4133
4190
  };
@@ -5289,11 +5346,10 @@ function shellWriteUnseen(command, target) {
5289
5346
  let unseen = false;
5290
5347
  let seen = false;
5291
5348
  try {
5292
- syntax4.Walk(f, (node) => {
5349
+ walk(f, (node) => {
5293
5350
  if (!node || unseen) return false;
5294
5351
  const n = node;
5295
- if (syntax4.NodeType(n) !== "Stmt" || !n.Cmd || syntax4.NodeType(n.Cmd) !== "CallExpr")
5296
- return true;
5352
+ if (n.kind !== "Stmt" || !n.Cmd || n.Cmd.kind !== "CallExpr") return true;
5297
5353
  const words = (n.Cmd.Args || []).map(
5298
5354
  (a) => resolveWordLiteral(a)
5299
5355
  );
@@ -5348,14 +5404,14 @@ function analyzeGitImpl(command) {
5348
5404
  seen.add(key);
5349
5405
  findings.push(f);
5350
5406
  };
5351
- const walk2 = new GitWalk((inv) => classify(inv).forEach(found), found);
5352
- const parsed = walk2.run(command, 0);
5407
+ const walk3 = new GitWalk((inv) => classify(inv).forEach(found), found);
5408
+ const parsed = walk3.run(command, 0);
5353
5409
  return { parsed, findings };
5354
5410
  }
5355
5411
  function isPositionalParam(word) {
5356
5412
  let parts = word?.Parts || [];
5357
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
5358
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return false;
5413
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
5414
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return false;
5359
5415
  return /^(\d+|@|\*)$/.test(parts[0].Param?.Value ?? "");
5360
5416
  }
5361
5417
  function boundPositionals() {
@@ -5369,11 +5425,11 @@ function boundPositionals() {
5369
5425
  function plainParamName(word) {
5370
5426
  let parts = word?.Parts || [];
5371
5427
  let quoted = false;
5372
- if (parts.length === 1 && syntax5.NodeType(parts[0]) === "DblQuoted") {
5428
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") {
5373
5429
  parts = parts[0].Parts || [];
5374
5430
  quoted = true;
5375
5431
  }
5376
- if (parts.length !== 1 || syntax5.NodeType(parts[0]) !== "ParamExp") return null;
5432
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
5377
5433
  const p = parts[0];
5378
5434
  if (p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp) return null;
5379
5435
  const name = p.Param?.Value;
@@ -5398,7 +5454,7 @@ function resolveGitWords(word) {
5398
5454
  }
5399
5455
  const parts = word?.Parts || [];
5400
5456
  const expansion = parts.some((p) => {
5401
- const t = syntax5.NodeType(p);
5457
+ const t = p.kind;
5402
5458
  return t === "ParamExp" || t === "CmdSubst";
5403
5459
  });
5404
5460
  return expansion ? splitFields(value) : [value];
@@ -5799,14 +5855,14 @@ function hookCommands(text) {
5799
5855
  const root = parsed?.hooks;
5800
5856
  if (!root || typeof root !== "object") return null;
5801
5857
  const out = [];
5802
- const walk2 = (v, depth) => {
5858
+ const walk3 = (v, depth) => {
5803
5859
  if (depth > 8 || !v || typeof v !== "object") return;
5804
5860
  for (const [k, x] of Object.entries(v)) {
5805
5861
  if (k === "command" && typeof x === "string") out.push(x);
5806
- else walk2(x, depth + 1);
5862
+ else walk3(x, depth + 1);
5807
5863
  }
5808
5864
  };
5809
- walk2(root, 0);
5865
+ walk3(root, 0);
5810
5866
  return out;
5811
5867
  }
5812
5868
  function hooksDisarmed(text) {
@@ -5973,9 +6029,9 @@ function isDupInOp(op) {
5973
6029
  if (dupInOp === null) {
5974
6030
  let found = -1;
5975
6031
  try {
5976
- syntax6.Walk(parseShared("cat <&3"), (node) => {
6032
+ walk(parseShared("cat <&3"), (node) => {
5977
6033
  const n = node;
5978
- if (found === -1 && n && syntax6.NodeType(n) === "Stmt" && n.Redirs?.[0]) {
6034
+ if (found === -1 && n && n.kind === "Stmt" && n.Redirs?.[0]) {
5979
6035
  found = n.Redirs[0].Op;
5980
6036
  }
5981
6037
  return true;
@@ -5996,10 +6052,10 @@ function analyzeOutbound(command) {
5996
6052
  return hit;
5997
6053
  }
5998
6054
  const findings = [];
5999
- const walk2 = new OutboundWalk(findings);
6000
- const parsed = walk2.run(command, 0);
6055
+ const walk3 = new OutboundWalk(findings);
6056
+ const parsed = walk3.run(command, 0);
6001
6057
  const envOut = findings.find((f) => f.checkId === "data.env-exfil");
6002
- if (envOut) envOut.destinations = walk2.envDestinations();
6058
+ if (envOut) envOut.destinations = walk3.envDestinations();
6003
6059
  const computed = { parsed, findings };
6004
6060
  if (cache2.size >= CACHE_MAX2) {
6005
6061
  const oldest = cache2.keys().next().value;
@@ -6015,7 +6071,7 @@ function wordShape(word) {
6015
6071
  const parts = word?.Parts || [];
6016
6072
  let out = "";
6017
6073
  for (const p of parts) {
6018
- const t = syntax6.NodeType(p);
6074
+ const t = p.kind;
6019
6075
  if (t === "Lit" || t === "SglQuoted") out += p.Value ?? "";
6020
6076
  else if (t === "DblQuoted") out += wordShape(p);
6021
6077
  else out += "X";
@@ -6150,16 +6206,16 @@ function declDumpsEnv(decl) {
6150
6206
  }
6151
6207
  function paramName(word) {
6152
6208
  let parts = word?.Parts || [];
6153
- if (parts.length === 1 && syntax6.NodeType(parts[0]) === "DblQuoted") parts = parts[0].Parts || [];
6154
- if (parts.length !== 1 || syntax6.NodeType(parts[0]) !== "ParamExp") return null;
6209
+ if (parts.length === 1 && parts[0].kind === "DblQuoted") parts = parts[0].Parts || [];
6210
+ if (parts.length !== 1 || parts[0].kind !== "ParamExp") return null;
6155
6211
  return parts[0].Param?.Value ?? null;
6156
6212
  }
6157
6213
  function refersTo(word, names) {
6158
6214
  let hit = false;
6159
- syntax6.Walk(word, (node) => {
6215
+ walk(word, (node) => {
6160
6216
  if (hit || !node) return false;
6161
6217
  const n = node;
6162
- if (syntax6.NodeType(n) === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6218
+ if (n.kind === "ParamExp" && names.has(n.Param?.Value)) hit = true;
6163
6219
  return !hit;
6164
6220
  });
6165
6221
  return hit;
@@ -6167,10 +6223,10 @@ function refersTo(word, names) {
6167
6223
  function runsCommandsIn(stmt) {
6168
6224
  const readVars = /* @__PURE__ */ new Set();
6169
6225
  let hit = false;
6170
- syntax6.Walk(stmt, (node) => {
6226
+ walk(stmt, (node) => {
6171
6227
  if (hit || !node) return false;
6172
6228
  const n = node;
6173
- if (syntax6.NodeType(n) !== "CallExpr") return true;
6229
+ if (n.kind !== "CallExpr") return true;
6174
6230
  const words = wordsOf(n);
6175
6231
  if (words.length === 0) return true;
6176
6232
  const { head, at } = headOf(words);
@@ -6747,7 +6803,7 @@ function localContexts(file2) {
6747
6803
  if (depth > 64) return null;
6748
6804
  if (!stmt || stmt.Background || stmt.Negated || stmt.Redirs?.length) return null;
6749
6805
  const cmd = stmt.Cmd;
6750
- const kind = syntax7.NodeType(cmd);
6806
+ const kind = cmd.kind;
6751
6807
  if (kind === "BinaryCmd" && cmd.Op === andOp) {
6752
6808
  const next = visit2(cmd.X, steps, depth + 1);
6753
6809
  return next === null ? null : visit2(cmd.Y, next, depth + 1);
@@ -6763,7 +6819,7 @@ function localContexts(file2) {
6763
6819
  )
6764
6820
  ))
6765
6821
  return null;
6766
- contexts.set(cmd.Pos().Offset(), steps);
6822
+ contexts.set(cmd.pos, steps);
6767
6823
  return null;
6768
6824
  }
6769
6825
  if (file2.Stmts?.length === 1) visit2(file2.Stmts[0], []);
@@ -6774,12 +6830,12 @@ function collect(command, out, depth) {
6774
6830
  const f = parseShared(command);
6775
6831
  if (typeof f === "symbol") return;
6776
6832
  const contexts = depth === 0 ? localContexts(f) : /* @__PURE__ */ new Map();
6777
- syntax7.Walk(f, (node) => {
6778
- if (node && syntax7.NodeType(node) === "CallExpr") {
6833
+ walk(f, (node) => {
6834
+ if (node && node.kind === "CallExpr") {
6779
6835
  const words = (node.Args || []).map((a) => resolveWordLiteral(a));
6780
6836
  const start = out.length;
6781
6837
  if (words.length > 0) fromCall(words, out, depth);
6782
- const steps = contexts.get(node.Pos().Offset());
6838
+ const steps = contexts.get(node.pos);
6783
6839
  for (let i = start; i < out.length; i++) {
6784
6840
  if (["npx", "bunx", "npm exec"].includes(out[i].manager)) {
6785
6841
  if (!steps) out[i].localCwd = null;
@@ -6826,7 +6882,7 @@ function collect2(command, out, depth) {
6826
6882
  try {
6827
6883
  walkCommandScope(command, (node) => {
6828
6884
  const n = node;
6829
- if (!n || syntax8.NodeType(n) !== "CallExpr") return true;
6885
+ if (!n || n.kind !== "CallExpr") return true;
6830
6886
  const words = (n.Args || []).map((a) => resolveWordLiteral(a));
6831
6887
  if (words.length === 0) return true;
6832
6888
  const prefix = (n.Assigns || []).filter((a) => a?.Name?.Value).map(
@@ -8256,12 +8312,12 @@ function extractContentDestinations(text) {
8256
8312
  function extractArgDestinations(args) {
8257
8313
  const out = /* @__PURE__ */ new Set();
8258
8314
  try {
8259
- walk(args, void 0, out, 0);
8315
+ walk2(args, void 0, out, 0);
8260
8316
  } catch {
8261
8317
  }
8262
8318
  return [...out];
8263
8319
  }
8264
- function walk(value, key, out, depth) {
8320
+ function walk2(value, key, out, depth) {
8265
8321
  if (out.size >= MAX_DESTINATIONS || depth > 12) return;
8266
8322
  if (typeof value === "string") {
8267
8323
  const s = value.length > MAX_SCAN_CHARS ? value.slice(0, MAX_SCAN_CHARS) : value;
@@ -8280,12 +8336,12 @@ function walk(value, key, out, depth) {
8280
8336
  return;
8281
8337
  }
8282
8338
  if (Array.isArray(value)) {
8283
- for (const v of value) walk(v, key, out, depth + 1);
8339
+ for (const v of value) walk2(v, key, out, depth + 1);
8284
8340
  return;
8285
8341
  }
8286
8342
  if (value && typeof value === "object") {
8287
8343
  for (const [k, v] of Object.entries(value))
8288
- walk(v, k, out, depth + 1);
8344
+ walk2(v, k, out, depth + 1);
8289
8345
  }
8290
8346
  }
8291
8347
  function destinationDomain(dest) {
@@ -8937,9 +8993,9 @@ function classifyCall(head, args, prefixes2, env, state, out) {
8937
8993
  function walkCalls(command, out, depth, state) {
8938
8994
  const f = parseShared(command);
8939
8995
  if (typeof f === "symbol" || !f) return;
8940
- syntax9.Walk(f, (node) => {
8996
+ walk(f, (node) => {
8941
8997
  if (!node) return false;
8942
- const type = syntax9.NodeType(node);
8998
+ const type = node.kind;
8943
8999
  if (type === "DeclClause") {
8944
9000
  for (const a of node.Args || []) if (a?.Name?.Value) state.env.add(a.Name.Value);
8945
9001
  return true;
@@ -9343,7 +9399,7 @@ function matchCanaryArgs(args, values) {
9343
9399
  if (values.length === 0) return null;
9344
9400
  const needles = prepare(values);
9345
9401
  if (needles.length === 0) return null;
9346
- const walk2 = (v, depth, fieldPath) => {
9402
+ const walk3 = (v, depth, fieldPath) => {
9347
9403
  if (depth > MAX_DEPTH4) return null;
9348
9404
  if (typeof v === "string") {
9349
9405
  const hit = matchPrepared(v, needles);
@@ -9352,31 +9408,31 @@ function matchCanaryArgs(args, values) {
9352
9408
  const trimmed = v.trim();
9353
9409
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
9354
9410
  try {
9355
- return walk2(JSON.parse(v), depth + 1, fieldPath);
9411
+ return walk3(JSON.parse(v), depth + 1, fieldPath);
9356
9412
  } catch {
9357
9413
  }
9358
9414
  }
9359
9415
  }
9360
9416
  return null;
9361
9417
  }
9362
- if (typeof v === "number" && Number.isFinite(v)) return walk2(String(v), depth, fieldPath);
9418
+ if (typeof v === "number" && Number.isFinite(v)) return walk3(String(v), depth, fieldPath);
9363
9419
  if (Array.isArray(v)) {
9364
9420
  for (let i = 0; i < v.length; i++) {
9365
- const h = walk2(v[i], depth + 1, `${fieldPath}[${i}]`);
9421
+ const h = walk3(v[i], depth + 1, `${fieldPath}[${i}]`);
9366
9422
  if (h) return h;
9367
9423
  }
9368
9424
  return null;
9369
9425
  }
9370
9426
  if (v && typeof v === "object") {
9371
9427
  for (const [k, child] of Object.entries(v)) {
9372
- const h = walk2(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
9428
+ const h = walk3(child, depth + 1, fieldPath ? `${fieldPath}.${k}` : k);
9373
9429
  if (h) return h;
9374
9430
  }
9375
9431
  }
9376
9432
  return null;
9377
9433
  };
9378
9434
  try {
9379
- return walk2(args, 0, "");
9435
+ return walk3(args, 0, "");
9380
9436
  } catch (e) {
9381
9437
  console.error(
9382
9438
  "[node9 engine] canary args walk failed:",
@@ -9809,26 +9865,20 @@ function* stringLeavesWithKeys(obj, depth = 0, key) {
9809
9865
  }
9810
9866
  for (const [k, v] of Object.entries(obj)) yield* stringLeavesWithKeys(v, depth + 1, k);
9811
9867
  }
9812
- var import_mvdan_sh, import_picomatch, import_safe_regex2, import_picomatch2, import_mvdan_sh2, import_mvdan_sh3, import_safe_regex22, import_crypto2, import_crypto3, import_mvdan_sh4, import_mvdan_sh5, import_mvdan_sh6, import_mvdan_sh7, import_mvdan_sh8, import_crypto4, import_mvdan_sh9, import_crypto5, 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;
9868
+ var import_picomatch, import_safe_regex2, import_picomatch2, import_mvdan_sh, import_mvdan_sh2, import_mvdan_sh3, import_safe_regex22, import_crypto2, import_crypto3, import_crypto4, import_crypto5, 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;
9813
9869
  var init_dist = __esm({
9814
9870
  "packages/policy-engine/dist/index.mjs"() {
9815
9871
  "use strict";
9816
- import_mvdan_sh = __toESM(require("mvdan-sh"), 1);
9817
9872
  import_picomatch = __toESM(require("picomatch"), 1);
9818
9873
  import_safe_regex2 = __toESM(require("safe-regex2"), 1);
9819
9874
  import_picomatch2 = __toESM(require("picomatch"), 1);
9875
+ import_mvdan_sh = __toESM(require("mvdan-sh"), 1);
9820
9876
  import_mvdan_sh2 = __toESM(require("mvdan-sh"), 1);
9821
9877
  import_mvdan_sh3 = __toESM(require("mvdan-sh"), 1);
9822
9878
  import_safe_regex22 = __toESM(require("safe-regex2"), 1);
9823
9879
  import_crypto2 = require("crypto");
9824
9880
  import_crypto3 = require("crypto");
9825
- import_mvdan_sh4 = __toESM(require("mvdan-sh"), 1);
9826
- import_mvdan_sh5 = __toESM(require("mvdan-sh"), 1);
9827
- import_mvdan_sh6 = __toESM(require("mvdan-sh"), 1);
9828
- import_mvdan_sh7 = __toESM(require("mvdan-sh"), 1);
9829
- import_mvdan_sh8 = __toESM(require("mvdan-sh"), 1);
9830
9881
  import_crypto4 = require("crypto");
9831
- import_mvdan_sh9 = __toESM(require("mvdan-sh"), 1);
9832
9882
  import_crypto5 = __toESM(require("crypto"), 1);
9833
9883
  MAX_REGEX_LENGTH = 256;
9834
9884
  REGEX_CACHE_MAX = 500;
@@ -12490,6 +12540,61 @@ var init_dist = __esm({
12490
12540
  return s.untrustedContent.afterExposure === "log-only" ? "log" : "review";
12491
12541
  }
12492
12542
  };
12543
+ ({ syntax } = import_mvdan_sh2.default);
12544
+ KINDS = {
12545
+ File: { nodes: ["Stmts"] },
12546
+ Stmt: { nodes: ["Cmd", "Redirs"], scalars: ["Negated", "Background", "Coprocess"] },
12547
+ CallExpr: { nodes: ["Assigns", "Args"] },
12548
+ Assign: { nodes: ["Name", "Value", "Index", "Array"], scalars: ["Append", "Naked"] },
12549
+ Word: { nodes: ["Parts"] },
12550
+ Lit: { scalars: ["Value"] },
12551
+ SglQuoted: { scalars: ["Value", "Dollar"] },
12552
+ DblQuoted: { nodes: ["Parts"], scalars: ["Dollar"] },
12553
+ ParamExp: {
12554
+ nodes: ["Param", "Index", "Slice", "Repl", "Exp"],
12555
+ scalars: ["Short", "Excl", "Length", "Width"]
12556
+ },
12557
+ CmdSubst: { nodes: ["Stmts"], scalars: ["Backquotes", "TempFile", "ReplyVar"] },
12558
+ ArithmExp: { nodes: ["X"], scalars: ["Bracket", "Unsigned"] },
12559
+ ArithmCmd: { nodes: ["X"], scalars: ["Unsigned"] },
12560
+ ProcSubst: { nodes: ["Stmts"], scalars: ["Op"] },
12561
+ ExtGlob: { nodes: ["Pattern"], scalars: ["Op"] },
12562
+ BraceExp: { nodes: ["Elems"], scalars: ["Sequence"] },
12563
+ // only with SplitBraces, unused here
12564
+ BinaryCmd: { nodes: ["X", "Y"], scalars: ["Op"] },
12565
+ BinaryArithm: { nodes: ["X", "Y"], scalars: ["Op"] },
12566
+ UnaryArithm: { nodes: ["X"], scalars: ["Op", "Post"] },
12567
+ ParenArithm: { nodes: ["X"] },
12568
+ BinaryTest: { nodes: ["X", "Y"], scalars: ["Op"] },
12569
+ UnaryTest: { nodes: ["X"], scalars: ["Op"] },
12570
+ ParenTest: { nodes: ["X"] },
12571
+ Redirect: { nodes: ["N", "Word", "Hdoc"], scalars: ["Op"] },
12572
+ Block: { nodes: ["Stmts"] },
12573
+ Subshell: { nodes: ["Stmts"] },
12574
+ IfClause: { nodes: ["Cond", "Then", "Else"] },
12575
+ WhileClause: { nodes: ["Cond", "Do"], scalars: ["Until"] },
12576
+ ForClause: { nodes: ["Loop", "Do"], scalars: ["Select"] },
12577
+ WordIter: { nodes: ["Name", "Items"] },
12578
+ CStyleLoop: { nodes: ["Init", "Cond", "Post"] },
12579
+ CaseClause: { nodes: ["Word", "Items"] },
12580
+ CaseItem: { nodes: ["Patterns", "Stmts"], scalars: ["Op"] },
12581
+ FuncDecl: { nodes: ["Name", "Body"], scalars: ["RsrvWord"] },
12582
+ DeclClause: { nodes: ["Variant", "Args"], notWalked: ["Variant"] },
12583
+ LetClause: { nodes: ["Exprs"] },
12584
+ TimeClause: { nodes: ["Stmt"], scalars: ["PosixFormat"] },
12585
+ CoprocClause: { nodes: ["Name", "Stmt"] },
12586
+ TestClause: { nodes: ["X"] },
12587
+ TestDecl: { nodes: ["Description", "Body"] },
12588
+ ArrayExpr: { nodes: ["Elems"] },
12589
+ ArrayElem: { nodes: ["Index", "Value"] },
12590
+ Comment: { scalars: ["Text"] }
12591
+ };
12592
+ STRUCTS = {
12593
+ "ParamExp.Slice": { nodes: ["Offset", "Length"], notWalked: ["Offset", "Length"] },
12594
+ "ParamExp.Repl": { nodes: ["Orig", "With"], scalars: ["All"] },
12595
+ "ParamExp.Exp": { nodes: ["Word"], scalars: ["Op"] }
12596
+ };
12597
+ unknownKinds = /* @__PURE__ */ new Set();
12493
12598
  INVISIBLE_RE = /[­͏؜᠎​-‏‪-‮⁠-⁤-︀-️]|[\u{E0000}-\u{E007F}]/gu;
12494
12599
  INVISIBLE_ONE = new RegExp(`^(?:${INVISIBLE_RE.source.split("|")[0]})$`, "u");
12495
12600
  HOMOGLYPHS = {
@@ -12775,8 +12880,8 @@ var init_dist = __esm({
12775
12880
  php: PHP
12776
12881
  };
12777
12882
  STRING_LITERAL = /(['"`])((?:\\.|(?!\1)[^\\\n]){1,4096})\1/g;
12778
- ({ syntax } = import_mvdan_sh2.default);
12779
- sharedParser = syntax.NewParser();
12883
+ ({ syntax: syntax2 } = import_mvdan_sh.default);
12884
+ sharedParser = syntax2.NewParser();
12780
12885
  MESSAGE_FLAGS = /* @__PURE__ */ new Set([
12781
12886
  "-m",
12782
12887
  "--message",
@@ -12810,7 +12915,7 @@ var init_dist = __esm({
12810
12915
  NORMALIZE_CACHE_MAX = 5e3;
12811
12916
  normalizeCache = /* @__PURE__ */ new Map();
12812
12917
  codeBodiesCache = /* @__PURE__ */ new Map();
12813
- AST_CACHE_MAX = 5e3;
12918
+ AST_CACHE_MAX = 256;
12814
12919
  astCache = /* @__PURE__ */ new Map();
12815
12920
  PARSE_FAIL = /* @__PURE__ */ Symbol("parse-fail");
12816
12921
  INTERPRETER_LINE = /^#![ \t]*[\w./+-]+(?:[ \t]+[\w./+=:-]+)*[ \t]*\r?(?=\n|$)/;
@@ -13795,7 +13900,7 @@ var init_dist = __esm({
13795
13900
  ARGV_FIELDS = ["args", "argv"];
13796
13901
  BARE_WORD = /^[A-Za-z0-9_./+:@%,-]+$/;
13797
13902
  MAX_ARGV_CHARACTERS = 262144;
13798
- ({ syntax: syntax2 } = import_mvdan_sh3.default);
13903
+ ({ syntax: syntax3 } = import_mvdan_sh3.default);
13799
13904
  MAX_ALTERNATIVES = 64;
13800
13905
  MAX_CALL_DEPTH2 = 4;
13801
13906
  MAX_CALL_WALKS2 = 256;
@@ -13887,7 +13992,6 @@ var init_dist = __esm({
13887
13992
  );
13888
13993
  exempt = (p) => SYSTEM_DIRS_EXEMPT.some((d) => within(p, d));
13889
13994
  RANK = { allow: 0, review: 1, block: 2 };
13890
- ({ syntax: syntax3 } = import_mvdan_sh.default);
13891
13995
  SEQUENCE_OPS = (() => {
13892
13996
  const ops = /* @__PURE__ */ new Set();
13893
13997
  for (const text of ["x && y", "x || y"]) {
@@ -17056,7 +17160,6 @@ zoo`.split("\n");
17056
17160
  );
17057
17161
  NEVER_NEGATED = /* @__PURE__ */ new Set([SIGNALS[1].any[0]]);
17058
17162
  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;
17059
- ({ syntax: syntax4 } = import_mvdan_sh4.default);
17060
17163
  RDR_IN = (() => {
17061
17164
  try {
17062
17165
  return parseShared("x <y").Stmts[0].Redirs[0].Op;
@@ -17085,7 +17188,6 @@ zoo`.split("\n");
17085
17188
  "tar"
17086
17189
  ]);
17087
17190
  LITERAL_VERBS = /* @__PURE__ */ new Set(["echo", "printf", ":", "true", "touch", "sed"]);
17088
- ({ syntax: syntax5 } = import_mvdan_sh5.default);
17089
17191
  GIT_PRESCREEN_RE = /git|husky/i;
17090
17192
  MAX_PAYLOAD_DEPTH2 = 8;
17091
17193
  MAX_ALIAS_DEPTH = 5;
@@ -17154,7 +17256,7 @@ zoo`.split("\n");
17154
17256
  visit(node, depth) {
17155
17257
  if (!node) return false;
17156
17258
  const n = node;
17157
- const type = syntax5.NodeType(n);
17259
+ const type = n.kind;
17158
17260
  if (type === "Stmt") {
17159
17261
  this.visitHeredocShell(n, depth);
17160
17262
  return true;
@@ -17162,7 +17264,7 @@ zoo`.split("\n");
17162
17264
  if (type === "ForClause") {
17163
17265
  const loop = n.Loop;
17164
17266
  const name = loop?.Name?.Value;
17165
- if (name && syntax5.NodeType(loop) === "WordIter") {
17267
+ if (name && loop.kind === "WordIter") {
17166
17268
  const items = (loop.Items || []).map((w) => resolveWordLiteral(w));
17167
17269
  const literal = items.length > 0 && items.every((v) => v !== null);
17168
17270
  this.loopVars.set(name, literal ? items.slice(0, MAX_LOOP_ITEMS) : null);
@@ -17229,7 +17331,7 @@ zoo`.split("\n");
17229
17331
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
17230
17332
  visitHeredocShell(stmt, depth) {
17231
17333
  const cmd = stmt.Cmd;
17232
- if (!cmd || syntax5.NodeType(cmd) !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
17334
+ if (!cmd || cmd.kind !== "CallExpr" || depth >= MAX_PAYLOAD_DEPTH2) return;
17233
17335
  const redirs = stmt.Redirs || [];
17234
17336
  const hdoc = redirs.find((r) => r?.Hdoc && (r.N == null || r.N.Value === "0"));
17235
17337
  if (!hdoc) return;
@@ -17483,7 +17585,6 @@ zoo`.split("\n");
17483
17585
  ]);
17484
17586
  SETTINGS_RE = /\/(?:\.claude\/settings(?:\.local)?\.json|\.gemini\/settings\.json|\.codex\/hooks\.json|\.cursor\/hooks\.json)$/i;
17485
17587
  HOOK_WORDS_RE = /"hooks"|\b(PreToolUse|PostToolUse|UserPromptSubmit|Notification|Stop|SubagentStop|SessionStart|SessionEnd|PreCompact|BeforeTool|AfterTool)\b|"command"\s*:/;
17486
- ({ syntax: syntax6 } = import_mvdan_sh6.default);
17487
17588
  SHELLS = /* @__PURE__ */ new Set([...SHELL_INTERPRETERS, "mksh", "ash", "csh", "tcsh"]);
17488
17589
  NETCATS = /* @__PURE__ */ new Set(["nc", "ncat", "netcat", "nc.traditional", "nc.openbsd"]);
17489
17590
  NET_CLIENTS = /* @__PURE__ */ new Set([...NETCATS, "telnet", "socat"]);
@@ -17541,7 +17642,7 @@ zoo`.split("\n");
17541
17642
  const f = parseShared(command);
17542
17643
  if (!f || typeof f !== "object" || !f.Stmts) return false;
17543
17644
  try {
17544
- syntax6.Walk(f, (node) => this.visit(node, depth));
17645
+ walk(f, (node) => this.visit(node, depth));
17545
17646
  } catch {
17546
17647
  return false;
17547
17648
  }
@@ -17580,7 +17681,7 @@ zoo`.split("\n");
17580
17681
  }
17581
17682
  visit(n, depth) {
17582
17683
  if (!n) return false;
17583
- const type = syntax6.NodeType(n);
17684
+ const type = n.kind;
17584
17685
  if (type === "Stmt") {
17585
17686
  this.visitStmt(n, depth);
17586
17687
  return true;
@@ -17600,7 +17701,7 @@ zoo`.split("\n");
17600
17701
  const redirs = redirectWords(stmt);
17601
17702
  const toSocket = redirs.some((w) => w !== null && DEV_NET_RE.test(w));
17602
17703
  if (!cmd) return;
17603
- const type = syntax6.NodeType(cmd);
17704
+ const type = cmd.kind;
17604
17705
  if (type !== "CallExpr" || wordsOf(cmd).length > 0) {
17605
17706
  if (this.readsNetFd(stmt) && runsCommandsIn(stmt)) {
17606
17707
  this.reverseShell("commands are read from a network socket opened with exec");
@@ -17686,7 +17787,7 @@ zoo`.split("\n");
17686
17787
  const stages = [];
17687
17788
  const flatten = (s) => {
17688
17789
  const c = s?.Cmd;
17689
- if (c && syntax6.NodeType(c) === "BinaryCmd" && isPipeOp(c.Op)) {
17790
+ if (c && c.kind === "BinaryCmd" && isPipeOp(c.Op)) {
17690
17791
  flatten(c.X);
17691
17792
  flatten(c.Y);
17692
17793
  } else stages.push(s);
@@ -17708,8 +17809,8 @@ zoo`.split("\n");
17708
17809
  sinks.set(i, socketHosts(st));
17709
17810
  }
17710
17811
  if (!c) return;
17711
- if (syntax6.NodeType(c) === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
17712
- if (syntax6.NodeType(c) !== "CallExpr") {
17812
+ if (c.kind === "DeclClause" && declDumpsEnv(c) && dump < 0) dump = i;
17813
+ if (c.kind !== "CallExpr") {
17713
17814
  if (runsCommandsIn(st)) shell = i;
17714
17815
  return;
17715
17816
  }
@@ -17750,10 +17851,10 @@ zoo`.split("\n");
17750
17851
  /** A word (or assignment value) whose text includes an env dump's output. */
17751
17852
  carriesEnv(word) {
17752
17853
  let hit = false;
17753
- syntax6.Walk(word, (node) => {
17854
+ walk(word, (node) => {
17754
17855
  if (hit || !node) return false;
17755
17856
  const n = node;
17756
- const t = syntax6.NodeType(n);
17857
+ const t = n.kind;
17757
17858
  if (t === "ParamExp" && n.Param?.Value && this.envVars.has(n.Param.Value)) {
17758
17859
  hit = true;
17759
17860
  return false;
@@ -17770,11 +17871,11 @@ zoo`.split("\n");
17770
17871
  stmtsDumpEnv(stmts) {
17771
17872
  let hit = false;
17772
17873
  for (const s of stmts) {
17773
- syntax6.Walk(s, (node) => {
17874
+ walk(s, (node) => {
17774
17875
  if (hit || !node) return false;
17775
17876
  const n = node;
17776
- const t = syntax6.NodeType(n);
17777
- if (t === "Stmt" && n.Cmd && syntax6.NodeType(n.Cmd) === "CallExpr") {
17877
+ const t = n.kind;
17878
+ if (t === "Stmt" && n.Cmd && n.Cmd.kind === "CallExpr") {
17778
17879
  const words = wordsOf(n.Cmd);
17779
17880
  if (words.length > 0 && dumpsEnv(words, n)) hit = true;
17780
17881
  }
@@ -17791,7 +17892,6 @@ zoo`.split("\n");
17791
17892
  this.run(payload, depth + 1);
17792
17893
  }
17793
17894
  };
17794
- ({ syntax: syntax7 } = import_mvdan_sh8.default);
17795
17895
  NPM_INSTALL_VERBS = /* @__PURE__ */ new Set([
17796
17896
  "install",
17797
17897
  "i",
@@ -18173,7 +18273,6 @@ zoo`.split("\n");
18173
18273
  SHELLS2 = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "ksh", "ash"]);
18174
18274
  MAX_NESTING = 3;
18175
18275
  SHELL_VALUE_FLAGS = /* @__PURE__ */ new Set(["--rcfile", "--init-file", "-O", "+O", "-o", "+o"]);
18176
- ({ syntax: syntax8 } = import_mvdan_sh7.default);
18177
18276
  NPM_FAMILY = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "npx", "pnpx", "bunx"]);
18178
18277
  PIP_FAMILY = /* @__PURE__ */ new Set(["pip", "pip3", "uv", "uvx", "pipx", "pipenv"]);
18179
18278
  NPM_FETCH_VERBS = /* @__PURE__ */ new Set([
@@ -18705,7 +18804,6 @@ zoo`.split("\n");
18705
18804
  ACCOUNT_KEY_RE = /("(?:iban|account|account_number|accountNumber)"\s*:\s*")([A-Za-z0-9 .-]{6,40})(")/g;
18706
18805
  ACCOUNT_VALUE_RE = /"([A-Z]{2}\d{2}[A-Z0-9]{11,30})"/g;
18707
18806
  MAX_MASK_DEPTH = 64;
18708
- ({ syntax: syntax9 } = import_mvdan_sh9.default);
18709
18807
  EMPTY = {
18710
18808
  fetches: false,
18711
18809
  sends: false,
@@ -33775,18 +33873,18 @@ function statAndFirstLine(file2) {
33775
33873
  }
33776
33874
  function listCodexSessionFiles(base2 = codexSessionsDir()) {
33777
33875
  const files = [];
33778
- const walk2 = (dir2) => {
33876
+ const walk3 = (dir2) => {
33779
33877
  try {
33780
33878
  for (const entry of import_fs45.default.readdirSync(dir2, { withFileTypes: true })) {
33781
33879
  const file2 = import_path46.default.join(dir2, entry.name);
33782
- if (entry.isDirectory()) walk2(file2);
33880
+ if (entry.isDirectory()) walk3(file2);
33783
33881
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) files.push(file2);
33784
33882
  }
33785
33883
  } catch {
33786
33884
  }
33787
33885
  };
33788
- walk2(base2);
33789
- if (import_path46.default.basename(base2) === "sessions") walk2(import_path46.default.join(import_path46.default.dirname(base2), "archived_sessions"));
33886
+ walk3(base2);
33887
+ if (import_path46.default.basename(base2) === "sessions") walk3(import_path46.default.join(import_path46.default.dirname(base2), "archived_sessions"));
33790
33888
  const sessions = /* @__PURE__ */ new Map();
33791
33889
  for (const file2 of files.sort()) {
33792
33890
  try {
@@ -34277,7 +34375,7 @@ var init_cost_copilot = __esm({
34277
34375
  // src/session-files.ts
34278
34376
  function listSessionFiles(dir2, maxDepth = 6) {
34279
34377
  const out = [];
34280
- const walk2 = (d, rel, depth) => {
34378
+ const walk3 = (d, rel, depth) => {
34281
34379
  if (depth > maxDepth) return;
34282
34380
  let entries;
34283
34381
  try {
@@ -34287,11 +34385,11 @@ function listSessionFiles(dir2, maxDepth = 6) {
34287
34385
  }
34288
34386
  for (const e of entries) {
34289
34387
  const childRel = rel ? path50.join(rel, e.name) : e.name;
34290
- if (e.isDirectory()) walk2(path50.join(d, e.name), childRel, depth + 1);
34388
+ if (e.isDirectory()) walk3(path50.join(d, e.name), childRel, depth + 1);
34291
34389
  else if (e.name.endsWith(".jsonl")) out.push(childRel);
34292
34390
  }
34293
34391
  };
34294
- walk2(dir2, "", 0);
34392
+ walk3(dir2, "", 0);
34295
34393
  return out;
34296
34394
  }
34297
34395
  function sessionIdOf(relPath) {
@@ -37594,19 +37692,19 @@ function scrubDecoys(subject, values) {
37594
37692
  for (const v of values) if (v) out = out.split(v).join("[node9-decoy]");
37595
37693
  return out;
37596
37694
  };
37597
- const walk2 = (v, depth) => {
37695
+ const walk3 = (v, depth) => {
37598
37696
  if (depth > 6) return v;
37599
37697
  if (typeof v === "string") return scrubText(v);
37600
- if (Array.isArray(v)) return v.map((x) => walk2(x, depth + 1));
37698
+ if (Array.isArray(v)) return v.map((x) => walk3(x, depth + 1));
37601
37699
  if (v && typeof v === "object") {
37602
37700
  const out = {};
37603
37701
  for (const [k, child] of Object.entries(v))
37604
- out[k] = walk2(child, depth + 1);
37702
+ out[k] = walk3(child, depth + 1);
37605
37703
  return out;
37606
37704
  }
37607
37705
  return v;
37608
37706
  };
37609
- return walk2(subject, 0);
37707
+ return walk3(subject, 0);
37610
37708
  }
37611
37709
  function isStaleFinding(timestamp2, now = Date.now()) {
37612
37710
  if (!timestamp2) return false;
@@ -75070,14 +75168,14 @@ function collectToolOutputText(toolResponse, opts = {}) {
75070
75168
  size += s.length + 1;
75071
75169
  return true;
75072
75170
  };
75073
- const walk2 = (v, depth) => {
75171
+ const walk3 = (v, depth) => {
75074
75172
  if (typeof v === "string") return push3(v);
75075
75173
  if (depth >= MAX_DEPTH5 || v === null || typeof v !== "object") return true;
75076
75174
  const children = Array.isArray(v) ? v : Object.values(v);
75077
- for (const child of children) if (!walk2(child, depth + 1)) return false;
75175
+ for (const child of children) if (!walk3(child, depth + 1)) return false;
75078
75176
  return true;
75079
75177
  };
75080
- walk2(toolResponse, 0);
75178
+ walk3(toolResponse, 0);
75081
75179
  return { text: parts.join("\n"), truncated, fields };
75082
75180
  }
75083
75181
  function shellOutputText(toolResponse) {
@@ -75090,15 +75188,15 @@ function shellOutputText(toolResponse) {
75090
75188
  return collectToolOutputText(toolResponse).text;
75091
75189
  }
75092
75190
  function mapToolOutputStrings(toolResponse, fn) {
75093
- const walk2 = (v, depth) => {
75191
+ const walk3 = (v, depth) => {
75094
75192
  if (typeof v === "string") return fn(v);
75095
75193
  if (depth >= MAX_DEPTH5 || v === null || typeof v !== "object") return v;
75096
- if (Array.isArray(v)) return v.map((x) => walk2(x, depth + 1));
75194
+ if (Array.isArray(v)) return v.map((x) => walk3(x, depth + 1));
75097
75195
  const out = {};
75098
- for (const [k, x] of Object.entries(v)) out[k] = walk2(x, depth + 1);
75196
+ for (const [k, x] of Object.entries(v)) out[k] = walk3(x, depth + 1);
75099
75197
  return out;
75100
75198
  };
75101
- return walk2(toolResponse, 0);
75199
+ return walk3(toolResponse, 0);
75102
75200
  }
75103
75201
  function frameToolOutputLeaves(toolResponse, isSuspect, frame, neutralize) {
75104
75202
  const suspect = [];