pi-codex-auto-review 0.1.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.
Files changed (1057) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +10 -0
  3. package/README.md +77 -0
  4. package/dist/approvals.d.ts +72 -0
  5. package/dist/approvals.js +167 -0
  6. package/dist/approvals.js.map +1 -0
  7. package/dist/audit.d.ts +28 -0
  8. package/dist/audit.js +40 -0
  9. package/dist/audit.js.map +1 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +70 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/context-files.d.ts +14 -0
  14. package/dist/context-files.js +113 -0
  15. package/dist/context-files.js.map +1 -0
  16. package/dist/contracts.d.ts +258 -0
  17. package/dist/contracts.js +102 -0
  18. package/dist/contracts.js.map +1 -0
  19. package/dist/index.d.ts +28 -0
  20. package/dist/index.js +106 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/native/darwin-arm64/artifact.json +5 -0
  23. package/dist/native/darwin-arm64/pi-guard-execpolicy +0 -0
  24. package/dist/native/linux-x64/artifact.json +5 -0
  25. package/dist/native/linux-x64/pi-guard-execpolicy +0 -0
  26. package/dist/policy/domains.d.ts +5 -0
  27. package/dist/policy/domains.js +18 -0
  28. package/dist/policy/domains.js.map +1 -0
  29. package/dist/policy/index.d.ts +56 -0
  30. package/dist/policy/index.js +304 -0
  31. package/dist/policy/index.js.map +1 -0
  32. package/dist/policy/paths.d.ts +5 -0
  33. package/dist/policy/paths.js +54 -0
  34. package/dist/policy/paths.js.map +1 -0
  35. package/dist/policy/rules.d.ts +36 -0
  36. package/dist/policy/rules.js +61 -0
  37. package/dist/policy/rules.js.map +1 -0
  38. package/dist/policy/shell.d.ts +14 -0
  39. package/dist/policy/shell.js +122 -0
  40. package/dist/policy/shell.js.map +1 -0
  41. package/dist/reports.d.ts +21 -0
  42. package/dist/reports.js +42 -0
  43. package/dist/reports.js.map +1 -0
  44. package/dist/review/context.d.ts +25 -0
  45. package/dist/review/context.js +108 -0
  46. package/dist/review/context.js.map +1 -0
  47. package/dist/review/investigation.d.ts +39 -0
  48. package/dist/review/investigation.js +36 -0
  49. package/dist/review/investigation.js.map +1 -0
  50. package/dist/review/lifecycle.d.ts +29 -0
  51. package/dist/review/lifecycle.js +71 -0
  52. package/dist/review/lifecycle.js.map +1 -0
  53. package/dist/review/policy.d.ts +4 -0
  54. package/dist/review/policy.js +15 -0
  55. package/dist/review/policy.js.map +1 -0
  56. package/dist/review/upstream-policy.d.ts +2 -0
  57. package/dist/review/upstream-policy.js +210 -0
  58. package/dist/review/upstream-policy.js.map +1 -0
  59. package/dist/reviewer.d.ts +45 -0
  60. package/dist/reviewer.js +148 -0
  61. package/dist/reviewer.js.map +1 -0
  62. package/dist/sandbox/broker.d.ts +1 -0
  63. package/dist/sandbox/broker.js +135 -0
  64. package/dist/sandbox/broker.js.map +1 -0
  65. package/dist/sandbox/config.d.ts +5 -0
  66. package/dist/sandbox/config.js +91 -0
  67. package/dist/sandbox/config.js.map +1 -0
  68. package/dist/sandbox/executor.d.ts +20 -0
  69. package/dist/sandbox/executor.js +144 -0
  70. package/dist/sandbox/executor.js.map +1 -0
  71. package/dist/sandbox/hard-links.d.ts +4 -0
  72. package/dist/sandbox/hard-links.js +145 -0
  73. package/dist/sandbox/hard-links.js.map +1 -0
  74. package/dist/sandbox/linux-read-paths.d.ts +7 -0
  75. package/dist/sandbox/linux-read-paths.js +47 -0
  76. package/dist/sandbox/linux-read-paths.js.map +1 -0
  77. package/dist/sandbox/paths.d.ts +3 -0
  78. package/dist/sandbox/paths.js +10 -0
  79. package/dist/sandbox/paths.js.map +1 -0
  80. package/dist/sandbox/runtime-write-paths.d.ts +2 -0
  81. package/dist/sandbox/runtime-write-paths.js +8 -0
  82. package/dist/sandbox/runtime-write-paths.js.map +1 -0
  83. package/dist/sandbox/seccomp.d.ts +5 -0
  84. package/dist/sandbox/seccomp.js +16 -0
  85. package/dist/sandbox/seccomp.js.map +1 -0
  86. package/dist/sandbox/worker.d.ts +1 -0
  87. package/dist/sandbox/worker.js +73 -0
  88. package/dist/sandbox/worker.js.map +1 -0
  89. package/dist/signals.d.ts +10 -0
  90. package/dist/signals.js +21 -0
  91. package/dist/signals.js.map +1 -0
  92. package/dist/startup.d.ts +22 -0
  93. package/dist/startup.js +100 -0
  94. package/dist/startup.js.map +1 -0
  95. package/dist/tools/controller.d.ts +63 -0
  96. package/dist/tools/controller.js +286 -0
  97. package/dist/tools/controller.js.map +1 -0
  98. package/dist/tools/external.d.ts +30 -0
  99. package/dist/tools/external.js +24 -0
  100. package/dist/tools/external.js.map +1 -0
  101. package/dist/tools/mcp.d.ts +17 -0
  102. package/dist/tools/mcp.js +186 -0
  103. package/dist/tools/mcp.js.map +1 -0
  104. package/docs/publishing.md +73 -0
  105. package/docs/security/dependencies.md +43 -0
  106. package/docs/testing/auto-review-protection.md +130 -0
  107. package/docs/usage.md +217 -0
  108. package/native/execpolicy/LICENSE +201 -0
  109. package/native/execpolicy/NOTICE +6 -0
  110. package/node_modules/@anthropic-ai/sandbox-runtime/LICENSE +201 -0
  111. package/node_modules/@anthropic-ai/sandbox-runtime/README.md +901 -0
  112. package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.d.ts +3 -0
  113. package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.d.ts.map +1 -0
  114. package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.js +472 -0
  115. package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.js.map +1 -0
  116. package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.d.ts +19 -0
  117. package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.d.ts.map +1 -0
  118. package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.js +17 -0
  119. package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.js.map +1 -0
  120. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.d.ts +52 -0
  121. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.d.ts.map +1 -0
  122. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.js +153 -0
  123. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.js.map +1 -0
  124. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.d.ts +164 -0
  125. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.d.ts.map +1 -0
  126. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.js +246 -0
  127. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.js.map +1 -0
  128. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.d.ts +58 -0
  129. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.d.ts.map +1 -0
  130. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.js +128 -0
  131. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.js.map +1 -0
  132. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.d.ts +124 -0
  133. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.d.ts.map +1 -0
  134. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.js +258 -0
  135. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.js.map +1 -0
  136. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.d.ts +87 -0
  137. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.d.ts.map +1 -0
  138. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.js +138 -0
  139. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.js.map +1 -0
  140. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.d.ts +67 -0
  141. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.d.ts.map +1 -0
  142. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.js +113 -0
  143. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.js.map +1 -0
  144. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.d.ts +70 -0
  145. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.d.ts.map +1 -0
  146. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.js +171 -0
  147. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.js.map +1 -0
  148. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.d.ts +120 -0
  149. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.d.ts.map +1 -0
  150. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.js +281 -0
  151. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.js.map +1 -0
  152. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.d.ts +108 -0
  153. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.d.ts.map +1 -0
  154. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.js +208 -0
  155. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.js.map +1 -0
  156. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.d.ts +82 -0
  157. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.d.ts.map +1 -0
  158. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.js +155 -0
  159. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.js.map +1 -0
  160. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.d.ts +44 -0
  161. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.d.ts.map +1 -0
  162. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.js +220 -0
  163. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.js.map +1 -0
  164. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.d.ts +150 -0
  165. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.d.ts.map +1 -0
  166. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.js +678 -0
  167. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.js.map +1 -0
  168. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.d.ts +32 -0
  169. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.d.ts.map +1 -0
  170. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.js +111 -0
  171. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.js.map +1 -0
  172. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.d.ts +305 -0
  173. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
  174. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.js +2605 -0
  175. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.js.map +1 -0
  176. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.d.ts +55 -0
  177. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.d.ts.map +1 -0
  178. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.js +152 -0
  179. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.js.map +1 -0
  180. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.d.ts +12 -0
  181. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.d.ts.map +1 -0
  182. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.js +43 -0
  183. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.js.map +1 -0
  184. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.d.ts +116 -0
  185. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
  186. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.js +1195 -0
  187. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.js.map +1 -0
  188. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.d.ts +200 -0
  189. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.d.ts.map +1 -0
  190. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.js +443 -0
  191. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.js.map +1 -0
  192. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.d.ts +28 -0
  193. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.d.ts.map +1 -0
  194. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.js +114 -0
  195. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.js.map +1 -0
  196. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.d.ts +59 -0
  197. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.d.ts.map +1 -0
  198. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.js +159 -0
  199. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.js.map +1 -0
  200. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.d.ts +147 -0
  201. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.d.ts.map +1 -0
  202. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.js +445 -0
  203. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.js.map +1 -0
  204. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.d.ts +17 -0
  205. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.d.ts.map +1 -0
  206. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.js +163 -0
  207. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.js.map +1 -0
  208. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.d.ts +83 -0
  209. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.d.ts.map +1 -0
  210. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.js +212 -0
  211. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.js.map +1 -0
  212. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.d.ts +76 -0
  213. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.d.ts.map +1 -0
  214. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.js +221 -0
  215. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.js.map +1 -0
  216. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.d.ts +1691 -0
  217. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.d.ts.map +1 -0
  218. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.js +1233 -0
  219. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.js.map +1 -0
  220. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.d.ts +97 -0
  221. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.d.ts.map +1 -0
  222. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.js +1937 -0
  223. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.js.map +1 -0
  224. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.d.ts +113 -0
  225. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
  226. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.js +3 -0
  227. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.js.map +1 -0
  228. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.d.ts +411 -0
  229. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.d.ts.map +1 -0
  230. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.js +1408 -0
  231. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.js.map +1 -0
  232. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.d.ts +37 -0
  233. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.d.ts.map +1 -0
  234. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.js +125 -0
  235. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.js.map +1 -0
  236. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.d.ts +57 -0
  237. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.d.ts.map +1 -0
  238. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.js +332 -0
  239. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.js.map +1 -0
  240. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.d.ts +100 -0
  241. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.d.ts.map +1 -0
  242. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.js +546 -0
  243. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.js.map +1 -0
  244. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.d.ts +923 -0
  245. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.d.ts.map +1 -0
  246. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.js +1419 -0
  247. package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.js.map +1 -0
  248. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.d.ts +31 -0
  249. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.d.ts.map +1 -0
  250. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.js +69 -0
  251. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.js.map +1 -0
  252. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.d.ts +7 -0
  253. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.d.ts.map +1 -0
  254. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.js +25 -0
  255. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.js.map +1 -0
  256. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.d.ts +15 -0
  257. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.d.ts.map +1 -0
  258. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.js +49 -0
  259. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.js.map +1 -0
  260. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.d.ts +17 -0
  261. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.d.ts.map +1 -0
  262. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.js +37 -0
  263. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.js.map +1 -0
  264. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.d.ts +27 -0
  265. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.d.ts.map +1 -0
  266. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.js +47 -0
  267. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.js.map +1 -0
  268. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.d.ts +9 -0
  269. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.d.ts.map +1 -0
  270. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.js +25 -0
  271. package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.js.map +1 -0
  272. package/node_modules/@anthropic-ai/sandbox-runtime/package.json +88 -0
  273. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/java-proxy-agent/build.ts +95 -0
  274. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/java-proxy-agent/srt-proxy-agent.jar +0 -0
  275. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/arm64/apply-seccomp +0 -0
  276. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/build.ts +69 -0
  277. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/x64/apply-seccomp +0 -0
  278. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/arm64/srt-win.exe +0 -0
  279. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/build.ts +28 -0
  280. package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/x64/srt-win.exe +0 -0
  281. package/node_modules/@pondwader/socks5-server/.github/workflows/ci.yml +27 -0
  282. package/node_modules/@pondwader/socks5-server/LICENSE +20 -0
  283. package/node_modules/@pondwader/socks5-server/README.md +151 -0
  284. package/node_modules/@pondwader/socks5-server/dist/index.d.mts +87 -0
  285. package/node_modules/@pondwader/socks5-server/dist/index.d.ts +87 -0
  286. package/node_modules/@pondwader/socks5-server/dist/index.js +346 -0
  287. package/node_modules/@pondwader/socks5-server/dist/index.mjs +307 -0
  288. package/node_modules/@pondwader/socks5-server/package.json +31 -0
  289. package/node_modules/commander/LICENSE +22 -0
  290. package/node_modules/commander/Readme.md +1157 -0
  291. package/node_modules/commander/esm.mjs +16 -0
  292. package/node_modules/commander/index.js +24 -0
  293. package/node_modules/commander/lib/argument.js +149 -0
  294. package/node_modules/commander/lib/command.js +2509 -0
  295. package/node_modules/commander/lib/error.js +39 -0
  296. package/node_modules/commander/lib/help.js +520 -0
  297. package/node_modules/commander/lib/option.js +330 -0
  298. package/node_modules/commander/lib/suggestSimilar.js +101 -0
  299. package/node_modules/commander/package-support.json +16 -0
  300. package/node_modules/commander/package.json +84 -0
  301. package/node_modules/commander/typings/esm.d.mts +3 -0
  302. package/node_modules/commander/typings/index.d.ts +969 -0
  303. package/node_modules/node-forge/.editorconfig +17 -0
  304. package/node_modules/node-forge/.eslintrc.js +24 -0
  305. package/node_modules/node-forge/.github/workflows/main.yaml +96 -0
  306. package/node_modules/node-forge/.istanbul.yml +2 -0
  307. package/node_modules/node-forge/.npmignore +15 -0
  308. package/node_modules/node-forge/CHANGELOG.md +555 -0
  309. package/node_modules/node-forge/CONTRIBUTING.md +18 -0
  310. package/node_modules/node-forge/LICENSE +331 -0
  311. package/node_modules/node-forge/README.md +2071 -0
  312. package/node_modules/node-forge/RELEASE.md +19 -0
  313. package/node_modules/node-forge/SECURITY.md +5 -0
  314. package/node_modules/node-forge/examples/create-cert.js +110 -0
  315. package/node_modules/node-forge/examples/create-csr.js +66 -0
  316. package/node_modules/node-forge/examples/create-pkcs12.js +160 -0
  317. package/node_modules/node-forge/examples/imap.js +46 -0
  318. package/node_modules/node-forge/examples/sign-p7.js +115 -0
  319. package/node_modules/node-forge/examples/tls.js +189 -0
  320. package/node_modules/node-forge/flash/PooledSocket.as +18 -0
  321. package/node_modules/node-forge/flash/README.md +48 -0
  322. package/node_modules/node-forge/flash/SocketEvent.as +36 -0
  323. package/node_modules/node-forge/flash/SocketPool.as +754 -0
  324. package/node_modules/node-forge/flash/mod_fsp/README +135 -0
  325. package/node_modules/node-forge/flash/mod_fsp/mod_fsp.c +415 -0
  326. package/node_modules/node-forge/flash/package.json +28 -0
  327. package/node_modules/node-forge/flash/policyserver.js +65 -0
  328. package/node_modules/node-forge/flash/policyserver.py +112 -0
  329. package/node_modules/node-forge/flash/swf/SocketPool.swf +0 -0
  330. package/node_modules/node-forge/karma-sauce.conf.js +79 -0
  331. package/node_modules/node-forge/karma.conf.js +133 -0
  332. package/node_modules/node-forge/lib/aes.js +1091 -0
  333. package/node_modules/node-forge/lib/aesCipherSuites.js +282 -0
  334. package/node_modules/node-forge/lib/asn1-validator.js +91 -0
  335. package/node_modules/node-forge/lib/asn1.js +1503 -0
  336. package/node_modules/node-forge/lib/baseN.js +186 -0
  337. package/node_modules/node-forge/lib/cipher.js +230 -0
  338. package/node_modules/node-forge/lib/cipherModes.js +999 -0
  339. package/node_modules/node-forge/lib/des.js +496 -0
  340. package/node_modules/node-forge/lib/ed25519.js +1091 -0
  341. package/node_modules/node-forge/lib/forge.js +13 -0
  342. package/node_modules/node-forge/lib/form.js +149 -0
  343. package/node_modules/node-forge/lib/hmac.js +146 -0
  344. package/node_modules/node-forge/lib/http.js +1346 -0
  345. package/node_modules/node-forge/lib/index.all.js +16 -0
  346. package/node_modules/node-forge/lib/index.js +33 -0
  347. package/node_modules/node-forge/lib/jsbn.js +1294 -0
  348. package/node_modules/node-forge/lib/kem.js +168 -0
  349. package/node_modules/node-forge/lib/log.js +319 -0
  350. package/node_modules/node-forge/lib/md.all.js +13 -0
  351. package/node_modules/node-forge/lib/md.js +11 -0
  352. package/node_modules/node-forge/lib/md5.js +289 -0
  353. package/node_modules/node-forge/lib/mgf.js +12 -0
  354. package/node_modules/node-forge/lib/mgf1.js +57 -0
  355. package/node_modules/node-forge/lib/oids.js +180 -0
  356. package/node_modules/node-forge/lib/pbe.js +1023 -0
  357. package/node_modules/node-forge/lib/pbkdf2.js +211 -0
  358. package/node_modules/node-forge/lib/pem.js +237 -0
  359. package/node_modules/node-forge/lib/pkcs1.js +276 -0
  360. package/node_modules/node-forge/lib/pkcs12.js +1078 -0
  361. package/node_modules/node-forge/lib/pkcs7.js +1260 -0
  362. package/node_modules/node-forge/lib/pkcs7asn1.js +410 -0
  363. package/node_modules/node-forge/lib/pki.js +102 -0
  364. package/node_modules/node-forge/lib/prime.js +297 -0
  365. package/node_modules/node-forge/lib/prime.worker.js +168 -0
  366. package/node_modules/node-forge/lib/prng.js +419 -0
  367. package/node_modules/node-forge/lib/pss.js +241 -0
  368. package/node_modules/node-forge/lib/random.js +191 -0
  369. package/node_modules/node-forge/lib/rc2.js +410 -0
  370. package/node_modules/node-forge/lib/rsa.js +1973 -0
  371. package/node_modules/node-forge/lib/sha1.js +319 -0
  372. package/node_modules/node-forge/lib/sha256.js +327 -0
  373. package/node_modules/node-forge/lib/sha512.js +561 -0
  374. package/node_modules/node-forge/lib/socket.js +287 -0
  375. package/node_modules/node-forge/lib/ssh.js +236 -0
  376. package/node_modules/node-forge/lib/tls.js +4282 -0
  377. package/node_modules/node-forge/lib/tlssocket.js +249 -0
  378. package/node_modules/node-forge/lib/util.js +2652 -0
  379. package/node_modules/node-forge/lib/x509.js +3251 -0
  380. package/node_modules/node-forge/lib/xhr.js +738 -0
  381. package/node_modules/node-forge/package.json +123 -0
  382. package/node_modules/node-forge/tests/.eslintrc.js +5 -0
  383. package/node_modules/node-forge/tests/README.md +4 -0
  384. package/node_modules/node-forge/tests/benchmarks/aes-speed.js +62 -0
  385. package/node_modules/node-forge/tests/benchmarks/so-44303784.js +246 -0
  386. package/node_modules/node-forge/tests/flash/README.md +7 -0
  387. package/node_modules/node-forge/tests/flash/Test.as +96 -0
  388. package/node_modules/node-forge/tests/flash/build-flash.xml +7 -0
  389. package/node_modules/node-forge/tests/flash/index.html +28 -0
  390. package/node_modules/node-forge/tests/index.html +33 -0
  391. package/node_modules/node-forge/tests/issues/heartbleed.js +55 -0
  392. package/node_modules/node-forge/tests/issues/issue-428.html +95 -0
  393. package/node_modules/node-forge/tests/issues/issue-428.js +375 -0
  394. package/node_modules/node-forge/tests/karma/index.js +8 -0
  395. package/node_modules/node-forge/tests/karma/testWorker.js +65 -0
  396. package/node_modules/node-forge/tests/karma/web-worker-rsa.js +55 -0
  397. package/node_modules/node-forge/tests/legacy/common.html +65 -0
  398. package/node_modules/node-forge/tests/legacy/common.js +2199 -0
  399. package/node_modules/node-forge/tests/legacy/form.html +148 -0
  400. package/node_modules/node-forge/tests/legacy/form.js +40 -0
  401. package/node_modules/node-forge/tests/legacy/http.html +235 -0
  402. package/node_modules/node-forge/tests/legacy/index.html +70 -0
  403. package/node_modules/node-forge/tests/legacy/keygen.html +113 -0
  404. package/node_modules/node-forge/tests/legacy/login.css +26 -0
  405. package/node_modules/node-forge/tests/legacy/loginDemo.html +32 -0
  406. package/node_modules/node-forge/tests/legacy/loginDemo.js +149 -0
  407. package/node_modules/node-forge/tests/legacy/performance.html +533 -0
  408. package/node_modules/node-forge/tests/legacy/result.txt +1 -0
  409. package/node_modules/node-forge/tests/legacy/socketPool.html +302 -0
  410. package/node_modules/node-forge/tests/legacy/tasks.html +54 -0
  411. package/node_modules/node-forge/tests/legacy/tasks.js +378 -0
  412. package/node_modules/node-forge/tests/legacy/tls.html +389 -0
  413. package/node_modules/node-forge/tests/legacy/webid.html +89 -0
  414. package/node_modules/node-forge/tests/legacy/webid.js +313 -0
  415. package/node_modules/node-forge/tests/legacy/ws-webid.js +120 -0
  416. package/node_modules/node-forge/tests/legacy/xhr.html +67 -0
  417. package/node_modules/node-forge/tests/legacy/xhr.js +590 -0
  418. package/node_modules/node-forge/tests/pocs/ghsa-2328-f5f3-gj25.js +85 -0
  419. package/node_modules/node-forge/tests/pocs/ghsa-ppp5-5v6c-4jwp.js +166 -0
  420. package/node_modules/node-forge/tests/pocs/ghsa-q67f-28xg-22rw.js +103 -0
  421. package/node_modules/node-forge/tests/security/cve-2025-12816.js +75 -0
  422. package/node_modules/node-forge/tests/security/ghsa-554w-wpv2-vw27.js +81 -0
  423. package/node_modules/node-forge/tests/security/index.js +3 -0
  424. package/node_modules/node-forge/tests/server.crt +26 -0
  425. package/node_modules/node-forge/tests/server.js +87 -0
  426. package/node_modules/node-forge/tests/server.key +27 -0
  427. package/node_modules/node-forge/tests/support/task.js +718 -0
  428. package/node_modules/node-forge/tests/tests.css +61 -0
  429. package/node_modules/node-forge/tests/unit/aes.js +1498 -0
  430. package/node_modules/node-forge/tests/unit/asn1.js +1337 -0
  431. package/node_modules/node-forge/tests/unit/csr.js +129 -0
  432. package/node_modules/node-forge/tests/unit/des.js +231 -0
  433. package/node_modules/node-forge/tests/unit/ed25519.js +395 -0
  434. package/node_modules/node-forge/tests/unit/forge.js +2 -0
  435. package/node_modules/node-forge/tests/unit/hmac.js +64 -0
  436. package/node_modules/node-forge/tests/unit/index.html +20 -0
  437. package/node_modules/node-forge/tests/unit/index.js +27 -0
  438. package/node_modules/node-forge/tests/unit/jsbn.js +40 -0
  439. package/node_modules/node-forge/tests/unit/kem.js +167 -0
  440. package/node_modules/node-forge/tests/unit/md5.js +114 -0
  441. package/node_modules/node-forge/tests/unit/mgf1.js +16 -0
  442. package/node_modules/node-forge/tests/unit/pbkdf2.js +182 -0
  443. package/node_modules/node-forge/tests/unit/pem.js +159 -0
  444. package/node_modules/node-forge/tests/unit/pkcs1.js +1077 -0
  445. package/node_modules/node-forge/tests/unit/pkcs12.js +739 -0
  446. package/node_modules/node-forge/tests/unit/pkcs7.js +792 -0
  447. package/node_modules/node-forge/tests/unit/random.js +48 -0
  448. package/node_modules/node-forge/tests/unit/rc2.js +88 -0
  449. package/node_modules/node-forge/tests/unit/rsa.js +1278 -0
  450. package/node_modules/node-forge/tests/unit/sha1.js +72 -0
  451. package/node_modules/node-forge/tests/unit/sha256.js +79 -0
  452. package/node_modules/node-forge/tests/unit/sha512.js +200 -0
  453. package/node_modules/node-forge/tests/unit/ssh.js +175 -0
  454. package/node_modules/node-forge/tests/unit/tls.js +175 -0
  455. package/node_modules/node-forge/tests/unit/util.js +595 -0
  456. package/node_modules/node-forge/tests/unit/x509.js +1986 -0
  457. package/node_modules/node-forge/tests/websockets/server-webid.js +495 -0
  458. package/node_modules/node-forge/tests/websockets/server-ws.js +158 -0
  459. package/node_modules/node-forge/webpack-tests.config.js +26 -0
  460. package/node_modules/node-forge/webpack.config.js +130 -0
  461. package/node_modules/zod/LICENSE +21 -0
  462. package/node_modules/zod/README.md +208 -0
  463. package/node_modules/zod/index.cjs +33 -0
  464. package/node_modules/zod/index.d.cts +4 -0
  465. package/node_modules/zod/index.d.ts +4 -0
  466. package/node_modules/zod/index.js +4 -0
  467. package/node_modules/zod/package.json +118 -0
  468. package/node_modules/zod/src/index.ts +4 -0
  469. package/node_modules/zod/src/v3/ZodError.ts +330 -0
  470. package/node_modules/zod/src/v3/benchmarks/datetime.ts +58 -0
  471. package/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts +80 -0
  472. package/node_modules/zod/src/v3/benchmarks/index.ts +59 -0
  473. package/node_modules/zod/src/v3/benchmarks/ipv4.ts +57 -0
  474. package/node_modules/zod/src/v3/benchmarks/object.ts +69 -0
  475. package/node_modules/zod/src/v3/benchmarks/primitives.ts +162 -0
  476. package/node_modules/zod/src/v3/benchmarks/realworld.ts +63 -0
  477. package/node_modules/zod/src/v3/benchmarks/string.ts +55 -0
  478. package/node_modules/zod/src/v3/benchmarks/union.ts +80 -0
  479. package/node_modules/zod/src/v3/errors.ts +13 -0
  480. package/node_modules/zod/src/v3/external.ts +6 -0
  481. package/node_modules/zod/src/v3/helpers/enumUtil.ts +17 -0
  482. package/node_modules/zod/src/v3/helpers/errorUtil.ts +8 -0
  483. package/node_modules/zod/src/v3/helpers/parseUtil.ts +176 -0
  484. package/node_modules/zod/src/v3/helpers/partialUtil.ts +34 -0
  485. package/node_modules/zod/src/v3/helpers/typeAliases.ts +2 -0
  486. package/node_modules/zod/src/v3/helpers/util.ts +224 -0
  487. package/node_modules/zod/src/v3/index.ts +4 -0
  488. package/node_modules/zod/src/v3/locales/en.ts +124 -0
  489. package/node_modules/zod/src/v3/standard-schema.ts +113 -0
  490. package/node_modules/zod/src/v3/tests/Mocker.ts +54 -0
  491. package/node_modules/zod/src/v3/tests/all-errors.test.ts +157 -0
  492. package/node_modules/zod/src/v3/tests/anyunknown.test.ts +28 -0
  493. package/node_modules/zod/src/v3/tests/array.test.ts +71 -0
  494. package/node_modules/zod/src/v3/tests/async-parsing.test.ts +388 -0
  495. package/node_modules/zod/src/v3/tests/async-refinements.test.ts +46 -0
  496. package/node_modules/zod/src/v3/tests/base.test.ts +29 -0
  497. package/node_modules/zod/src/v3/tests/bigint.test.ts +55 -0
  498. package/node_modules/zod/src/v3/tests/branded.test.ts +53 -0
  499. package/node_modules/zod/src/v3/tests/catch.test.ts +220 -0
  500. package/node_modules/zod/src/v3/tests/coerce.test.ts +133 -0
  501. package/node_modules/zod/src/v3/tests/complex.test.ts +56 -0
  502. package/node_modules/zod/src/v3/tests/custom.test.ts +31 -0
  503. package/node_modules/zod/src/v3/tests/date.test.ts +32 -0
  504. package/node_modules/zod/src/v3/tests/deepmasking.test.ts +186 -0
  505. package/node_modules/zod/src/v3/tests/default.test.ts +112 -0
  506. package/node_modules/zod/src/v3/tests/description.test.ts +33 -0
  507. package/node_modules/zod/src/v3/tests/discriminated-unions.test.ts +315 -0
  508. package/node_modules/zod/src/v3/tests/enum.test.ts +80 -0
  509. package/node_modules/zod/src/v3/tests/error.test.ts +551 -0
  510. package/node_modules/zod/src/v3/tests/firstparty.test.ts +87 -0
  511. package/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts +21 -0
  512. package/node_modules/zod/src/v3/tests/function.test.ts +257 -0
  513. package/node_modules/zod/src/v3/tests/generics.test.ts +48 -0
  514. package/node_modules/zod/src/v3/tests/instanceof.test.ts +37 -0
  515. package/node_modules/zod/src/v3/tests/intersection.test.ts +110 -0
  516. package/node_modules/zod/src/v3/tests/language-server.source.ts +76 -0
  517. package/node_modules/zod/src/v3/tests/language-server.test.ts +207 -0
  518. package/node_modules/zod/src/v3/tests/literal.test.ts +36 -0
  519. package/node_modules/zod/src/v3/tests/map.test.ts +110 -0
  520. package/node_modules/zod/src/v3/tests/masking.test.ts +4 -0
  521. package/node_modules/zod/src/v3/tests/mocker.test.ts +19 -0
  522. package/node_modules/zod/src/v3/tests/nan.test.ts +21 -0
  523. package/node_modules/zod/src/v3/tests/nativeEnum.test.ts +87 -0
  524. package/node_modules/zod/src/v3/tests/nullable.test.ts +42 -0
  525. package/node_modules/zod/src/v3/tests/number.test.ts +176 -0
  526. package/node_modules/zod/src/v3/tests/object-augmentation.test.ts +29 -0
  527. package/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts +29 -0
  528. package/node_modules/zod/src/v3/tests/object.test.ts +434 -0
  529. package/node_modules/zod/src/v3/tests/optional.test.ts +42 -0
  530. package/node_modules/zod/src/v3/tests/parseUtil.test.ts +23 -0
  531. package/node_modules/zod/src/v3/tests/parser.test.ts +41 -0
  532. package/node_modules/zod/src/v3/tests/partials.test.ts +243 -0
  533. package/node_modules/zod/src/v3/tests/pickomit.test.ts +111 -0
  534. package/node_modules/zod/src/v3/tests/pipeline.test.ts +29 -0
  535. package/node_modules/zod/src/v3/tests/preprocess.test.ts +186 -0
  536. package/node_modules/zod/src/v3/tests/primitive.test.ts +440 -0
  537. package/node_modules/zod/src/v3/tests/promise.test.ts +90 -0
  538. package/node_modules/zod/src/v3/tests/readonly.test.ts +194 -0
  539. package/node_modules/zod/src/v3/tests/record.test.ts +171 -0
  540. package/node_modules/zod/src/v3/tests/recursive.test.ts +197 -0
  541. package/node_modules/zod/src/v3/tests/refine.test.ts +313 -0
  542. package/node_modules/zod/src/v3/tests/safeparse.test.ts +27 -0
  543. package/node_modules/zod/src/v3/tests/set.test.ts +142 -0
  544. package/node_modules/zod/src/v3/tests/standard-schema.test.ts +83 -0
  545. package/node_modules/zod/src/v3/tests/string.test.ts +916 -0
  546. package/node_modules/zod/src/v3/tests/transformer.test.ts +233 -0
  547. package/node_modules/zod/src/v3/tests/tuple.test.ts +90 -0
  548. package/node_modules/zod/src/v3/tests/unions.test.ts +57 -0
  549. package/node_modules/zod/src/v3/tests/validations.test.ts +133 -0
  550. package/node_modules/zod/src/v3/tests/void.test.ts +15 -0
  551. package/node_modules/zod/src/v3/types.ts +5136 -0
  552. package/node_modules/zod/src/v4/classic/checks.ts +30 -0
  553. package/node_modules/zod/src/v4/classic/coerce.ts +27 -0
  554. package/node_modules/zod/src/v4/classic/compat.ts +66 -0
  555. package/node_modules/zod/src/v4/classic/errors.ts +75 -0
  556. package/node_modules/zod/src/v4/classic/external.ts +50 -0
  557. package/node_modules/zod/src/v4/classic/index.ts +5 -0
  558. package/node_modules/zod/src/v4/classic/iso.ts +90 -0
  559. package/node_modules/zod/src/v4/classic/parse.ts +33 -0
  560. package/node_modules/zod/src/v4/classic/schemas.ts +2054 -0
  561. package/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts +26 -0
  562. package/node_modules/zod/src/v4/classic/tests/array.test.ts +264 -0
  563. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +210 -0
  564. package/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts +381 -0
  565. package/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts +68 -0
  566. package/node_modules/zod/src/v4/classic/tests/base.test.ts +7 -0
  567. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +54 -0
  568. package/node_modules/zod/src/v4/classic/tests/brand.test.ts +63 -0
  569. package/node_modules/zod/src/v4/classic/tests/catch.test.ts +252 -0
  570. package/node_modules/zod/src/v4/classic/tests/coalesce.test.ts +20 -0
  571. package/node_modules/zod/src/v4/classic/tests/coerce.test.ts +160 -0
  572. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +352 -0
  573. package/node_modules/zod/src/v4/classic/tests/custom.test.ts +40 -0
  574. package/node_modules/zod/src/v4/classic/tests/date.test.ts +31 -0
  575. package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +296 -0
  576. package/node_modules/zod/src/v4/classic/tests/default.test.ts +313 -0
  577. package/node_modules/zod/src/v4/classic/tests/description.test.ts +32 -0
  578. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +619 -0
  579. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +285 -0
  580. package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +527 -0
  581. package/node_modules/zod/src/v4/classic/tests/error.test.ts +711 -0
  582. package/node_modules/zod/src/v4/classic/tests/file.test.ts +91 -0
  583. package/node_modules/zod/src/v4/classic/tests/firstparty.test.ts +175 -0
  584. package/node_modules/zod/src/v4/classic/tests/function.test.ts +268 -0
  585. package/node_modules/zod/src/v4/classic/tests/generics.test.ts +72 -0
  586. package/node_modules/zod/src/v4/classic/tests/index.test.ts +829 -0
  587. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +34 -0
  588. package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +171 -0
  589. package/node_modules/zod/src/v4/classic/tests/json.test.ts +108 -0
  590. package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +227 -0
  591. package/node_modules/zod/src/v4/classic/tests/literal.test.ts +92 -0
  592. package/node_modules/zod/src/v4/classic/tests/map.test.ts +196 -0
  593. package/node_modules/zod/src/v4/classic/tests/nan.test.ts +21 -0
  594. package/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts +168 -0
  595. package/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts +86 -0
  596. package/node_modules/zod/src/v4/classic/tests/nullable.test.ts +22 -0
  597. package/node_modules/zod/src/v4/classic/tests/number.test.ts +247 -0
  598. package/node_modules/zod/src/v4/classic/tests/object.test.ts +563 -0
  599. package/node_modules/zod/src/v4/classic/tests/optional.test.ts +123 -0
  600. package/node_modules/zod/src/v4/classic/tests/partial.test.ts +147 -0
  601. package/node_modules/zod/src/v4/classic/tests/pickomit.test.ts +127 -0
  602. package/node_modules/zod/src/v4/classic/tests/pipe.test.ts +81 -0
  603. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +37 -0
  604. package/node_modules/zod/src/v4/classic/tests/preprocess.test.ts +298 -0
  605. package/node_modules/zod/src/v4/classic/tests/primitive.test.ts +175 -0
  606. package/node_modules/zod/src/v4/classic/tests/promise.test.ts +81 -0
  607. package/node_modules/zod/src/v4/classic/tests/prototypes.test.ts +23 -0
  608. package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +252 -0
  609. package/node_modules/zod/src/v4/classic/tests/record.test.ts +342 -0
  610. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +356 -0
  611. package/node_modules/zod/src/v4/classic/tests/refine.test.ts +532 -0
  612. package/node_modules/zod/src/v4/classic/tests/registries.test.ts +204 -0
  613. package/node_modules/zod/src/v4/classic/tests/set.test.ts +179 -0
  614. package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +57 -0
  615. package/node_modules/zod/src/v4/classic/tests/string-formats.test.ts +109 -0
  616. package/node_modules/zod/src/v4/classic/tests/string.test.ts +881 -0
  617. package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +66 -0
  618. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +758 -0
  619. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +2314 -0
  620. package/node_modules/zod/src/v4/classic/tests/transform.test.ts +250 -0
  621. package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +163 -0
  622. package/node_modules/zod/src/v4/classic/tests/union.test.ts +94 -0
  623. package/node_modules/zod/src/v4/classic/tests/validations.test.ts +283 -0
  624. package/node_modules/zod/src/v4/classic/tests/void.test.ts +12 -0
  625. package/node_modules/zod/src/v4/core/api.ts +1594 -0
  626. package/node_modules/zod/src/v4/core/checks.ts +1283 -0
  627. package/node_modules/zod/src/v4/core/config.ts +15 -0
  628. package/node_modules/zod/src/v4/core/core.ts +134 -0
  629. package/node_modules/zod/src/v4/core/doc.ts +44 -0
  630. package/node_modules/zod/src/v4/core/errors.ts +424 -0
  631. package/node_modules/zod/src/v4/core/function.ts +176 -0
  632. package/node_modules/zod/src/v4/core/index.ts +15 -0
  633. package/node_modules/zod/src/v4/core/json-schema.ts +143 -0
  634. package/node_modules/zod/src/v4/core/parse.ts +94 -0
  635. package/node_modules/zod/src/v4/core/regexes.ts +135 -0
  636. package/node_modules/zod/src/v4/core/registries.ts +96 -0
  637. package/node_modules/zod/src/v4/core/schemas.ts +3842 -0
  638. package/node_modules/zod/src/v4/core/standard-schema.ts +64 -0
  639. package/node_modules/zod/src/v4/core/tests/index.test.ts +46 -0
  640. package/node_modules/zod/src/v4/core/tests/locales/be.test.ts +124 -0
  641. package/node_modules/zod/src/v4/core/tests/locales/en.test.ts +22 -0
  642. package/node_modules/zod/src/v4/core/tests/locales/ru.test.ts +128 -0
  643. package/node_modules/zod/src/v4/core/tests/locales/tr.test.ts +69 -0
  644. package/node_modules/zod/src/v4/core/to-json-schema.ts +977 -0
  645. package/node_modules/zod/src/v4/core/util.ts +775 -0
  646. package/node_modules/zod/src/v4/core/versions.ts +5 -0
  647. package/node_modules/zod/src/v4/core/zsf.ts +323 -0
  648. package/node_modules/zod/src/v4/index.ts +4 -0
  649. package/node_modules/zod/src/v4/locales/ar.ts +125 -0
  650. package/node_modules/zod/src/v4/locales/az.ts +121 -0
  651. package/node_modules/zod/src/v4/locales/be.ts +184 -0
  652. package/node_modules/zod/src/v4/locales/ca.ts +127 -0
  653. package/node_modules/zod/src/v4/locales/cs.ts +142 -0
  654. package/node_modules/zod/src/v4/locales/de.ts +124 -0
  655. package/node_modules/zod/src/v4/locales/en.ts +127 -0
  656. package/node_modules/zod/src/v4/locales/eo.ts +125 -0
  657. package/node_modules/zod/src/v4/locales/es.ts +125 -0
  658. package/node_modules/zod/src/v4/locales/fa.ts +134 -0
  659. package/node_modules/zod/src/v4/locales/fi.ts +131 -0
  660. package/node_modules/zod/src/v4/locales/fr-CA.ts +126 -0
  661. package/node_modules/zod/src/v4/locales/fr.ts +124 -0
  662. package/node_modules/zod/src/v4/locales/he.ts +125 -0
  663. package/node_modules/zod/src/v4/locales/hu.ts +126 -0
  664. package/node_modules/zod/src/v4/locales/id.ts +125 -0
  665. package/node_modules/zod/src/v4/locales/index.ts +39 -0
  666. package/node_modules/zod/src/v4/locales/it.ts +125 -0
  667. package/node_modules/zod/src/v4/locales/ja.ts +122 -0
  668. package/node_modules/zod/src/v4/locales/kh.ts +126 -0
  669. package/node_modules/zod/src/v4/locales/ko.ts +131 -0
  670. package/node_modules/zod/src/v4/locales/mk.ts +127 -0
  671. package/node_modules/zod/src/v4/locales/ms.ts +124 -0
  672. package/node_modules/zod/src/v4/locales/nl.ts +126 -0
  673. package/node_modules/zod/src/v4/locales/no.ts +124 -0
  674. package/node_modules/zod/src/v4/locales/ota.ts +125 -0
  675. package/node_modules/zod/src/v4/locales/pl.ts +126 -0
  676. package/node_modules/zod/src/v4/locales/ps.ts +133 -0
  677. package/node_modules/zod/src/v4/locales/pt.ts +123 -0
  678. package/node_modules/zod/src/v4/locales/ru.ts +184 -0
  679. package/node_modules/zod/src/v4/locales/sl.ts +126 -0
  680. package/node_modules/zod/src/v4/locales/sv.ts +127 -0
  681. package/node_modules/zod/src/v4/locales/ta.ts +125 -0
  682. package/node_modules/zod/src/v4/locales/th.ts +126 -0
  683. package/node_modules/zod/src/v4/locales/tr.ts +121 -0
  684. package/node_modules/zod/src/v4/locales/ua.ts +126 -0
  685. package/node_modules/zod/src/v4/locales/ur.ts +126 -0
  686. package/node_modules/zod/src/v4/locales/vi.ts +125 -0
  687. package/node_modules/zod/src/v4/locales/zh-CN.ts +123 -0
  688. package/node_modules/zod/src/v4/locales/zh-TW.ts +125 -0
  689. package/node_modules/zod/src/v4/mini/checks.ts +32 -0
  690. package/node_modules/zod/src/v4/mini/coerce.ts +22 -0
  691. package/node_modules/zod/src/v4/mini/external.ts +40 -0
  692. package/node_modules/zod/src/v4/mini/index.ts +3 -0
  693. package/node_modules/zod/src/v4/mini/iso.ts +62 -0
  694. package/node_modules/zod/src/v4/mini/parse.ts +1 -0
  695. package/node_modules/zod/src/v4/mini/schemas.ts +1579 -0
  696. package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +129 -0
  697. package/node_modules/zod/src/v4/mini/tests/brand.test.ts +51 -0
  698. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +144 -0
  699. package/node_modules/zod/src/v4/mini/tests/computed.test.ts +36 -0
  700. package/node_modules/zod/src/v4/mini/tests/error.test.ts +22 -0
  701. package/node_modules/zod/src/v4/mini/tests/functions.test.ts +43 -0
  702. package/node_modules/zod/src/v4/mini/tests/index.test.ts +871 -0
  703. package/node_modules/zod/src/v4/mini/tests/number.test.ts +95 -0
  704. package/node_modules/zod/src/v4/mini/tests/object.test.ts +185 -0
  705. package/node_modules/zod/src/v4/mini/tests/prototypes.test.ts +43 -0
  706. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +275 -0
  707. package/node_modules/zod/src/v4/mini/tests/string.test.ts +299 -0
  708. package/node_modules/zod/src/v4-mini/index.ts +1 -0
  709. package/node_modules/zod/v3/ZodError.cjs +138 -0
  710. package/node_modules/zod/v3/ZodError.d.cts +164 -0
  711. package/node_modules/zod/v3/ZodError.d.ts +164 -0
  712. package/node_modules/zod/v3/ZodError.js +133 -0
  713. package/node_modules/zod/v3/errors.cjs +17 -0
  714. package/node_modules/zod/v3/errors.d.cts +5 -0
  715. package/node_modules/zod/v3/errors.d.ts +5 -0
  716. package/node_modules/zod/v3/errors.js +9 -0
  717. package/node_modules/zod/v3/external.cjs +22 -0
  718. package/node_modules/zod/v3/external.d.cts +6 -0
  719. package/node_modules/zod/v3/external.d.ts +6 -0
  720. package/node_modules/zod/v3/external.js +6 -0
  721. package/node_modules/zod/v3/helpers/enumUtil.cjs +2 -0
  722. package/node_modules/zod/v3/helpers/enumUtil.d.cts +8 -0
  723. package/node_modules/zod/v3/helpers/enumUtil.d.ts +8 -0
  724. package/node_modules/zod/v3/helpers/enumUtil.js +1 -0
  725. package/node_modules/zod/v3/helpers/errorUtil.cjs +9 -0
  726. package/node_modules/zod/v3/helpers/errorUtil.d.cts +9 -0
  727. package/node_modules/zod/v3/helpers/errorUtil.d.ts +9 -0
  728. package/node_modules/zod/v3/helpers/errorUtil.js +6 -0
  729. package/node_modules/zod/v3/helpers/parseUtil.cjs +124 -0
  730. package/node_modules/zod/v3/helpers/parseUtil.d.cts +78 -0
  731. package/node_modules/zod/v3/helpers/parseUtil.d.ts +78 -0
  732. package/node_modules/zod/v3/helpers/parseUtil.js +109 -0
  733. package/node_modules/zod/v3/helpers/partialUtil.cjs +2 -0
  734. package/node_modules/zod/v3/helpers/partialUtil.d.cts +8 -0
  735. package/node_modules/zod/v3/helpers/partialUtil.d.ts +8 -0
  736. package/node_modules/zod/v3/helpers/partialUtil.js +1 -0
  737. package/node_modules/zod/v3/helpers/typeAliases.cjs +2 -0
  738. package/node_modules/zod/v3/helpers/typeAliases.d.cts +2 -0
  739. package/node_modules/zod/v3/helpers/typeAliases.d.ts +2 -0
  740. package/node_modules/zod/v3/helpers/typeAliases.js +1 -0
  741. package/node_modules/zod/v3/helpers/util.cjs +137 -0
  742. package/node_modules/zod/v3/helpers/util.d.cts +85 -0
  743. package/node_modules/zod/v3/helpers/util.d.ts +85 -0
  744. package/node_modules/zod/v3/helpers/util.js +133 -0
  745. package/node_modules/zod/v3/index.cjs +33 -0
  746. package/node_modules/zod/v3/index.d.cts +4 -0
  747. package/node_modules/zod/v3/index.d.ts +4 -0
  748. package/node_modules/zod/v3/index.js +4 -0
  749. package/node_modules/zod/v3/locales/en.cjs +111 -0
  750. package/node_modules/zod/v3/locales/en.d.cts +3 -0
  751. package/node_modules/zod/v3/locales/en.d.ts +3 -0
  752. package/node_modules/zod/v3/locales/en.js +109 -0
  753. package/node_modules/zod/v3/standard-schema.cjs +2 -0
  754. package/node_modules/zod/v3/standard-schema.d.cts +102 -0
  755. package/node_modules/zod/v3/standard-schema.d.ts +102 -0
  756. package/node_modules/zod/v3/standard-schema.js +1 -0
  757. package/node_modules/zod/v3/types.cjs +3775 -0
  758. package/node_modules/zod/v3/types.d.cts +1031 -0
  759. package/node_modules/zod/v3/types.d.ts +1031 -0
  760. package/node_modules/zod/v3/types.js +3693 -0
  761. package/node_modules/zod/v4/classic/checks.cjs +32 -0
  762. package/node_modules/zod/v4/classic/checks.d.cts +1 -0
  763. package/node_modules/zod/v4/classic/checks.d.ts +1 -0
  764. package/node_modules/zod/v4/classic/checks.js +1 -0
  765. package/node_modules/zod/v4/classic/coerce.cjs +47 -0
  766. package/node_modules/zod/v4/classic/coerce.d.cts +17 -0
  767. package/node_modules/zod/v4/classic/coerce.d.ts +17 -0
  768. package/node_modules/zod/v4/classic/coerce.js +17 -0
  769. package/node_modules/zod/v4/classic/compat.cjs +57 -0
  770. package/node_modules/zod/v4/classic/compat.d.cts +46 -0
  771. package/node_modules/zod/v4/classic/compat.d.ts +46 -0
  772. package/node_modules/zod/v4/classic/compat.js +27 -0
  773. package/node_modules/zod/v4/classic/errors.cjs +67 -0
  774. package/node_modules/zod/v4/classic/errors.d.cts +30 -0
  775. package/node_modules/zod/v4/classic/errors.d.ts +30 -0
  776. package/node_modules/zod/v4/classic/errors.js +41 -0
  777. package/node_modules/zod/v4/classic/external.cjs +70 -0
  778. package/node_modules/zod/v4/classic/external.d.cts +13 -0
  779. package/node_modules/zod/v4/classic/external.d.ts +13 -0
  780. package/node_modules/zod/v4/classic/external.js +18 -0
  781. package/node_modules/zod/v4/classic/index.cjs +33 -0
  782. package/node_modules/zod/v4/classic/index.d.cts +4 -0
  783. package/node_modules/zod/v4/classic/index.d.ts +4 -0
  784. package/node_modules/zod/v4/classic/index.js +4 -0
  785. package/node_modules/zod/v4/classic/iso.cjs +60 -0
  786. package/node_modules/zod/v4/classic/iso.d.cts +22 -0
  787. package/node_modules/zod/v4/classic/iso.d.ts +22 -0
  788. package/node_modules/zod/v4/classic/iso.js +30 -0
  789. package/node_modules/zod/v4/classic/parse.cjs +32 -0
  790. package/node_modules/zod/v4/classic/parse.d.cts +23 -0
  791. package/node_modules/zod/v4/classic/parse.d.ts +23 -0
  792. package/node_modules/zod/v4/classic/parse.js +6 -0
  793. package/node_modules/zod/v4/classic/schemas.cjs +1109 -0
  794. package/node_modules/zod/v4/classic/schemas.d.cts +630 -0
  795. package/node_modules/zod/v4/classic/schemas.d.ts +630 -0
  796. package/node_modules/zod/v4/classic/schemas.js +1006 -0
  797. package/node_modules/zod/v4/core/api.cjs +1039 -0
  798. package/node_modules/zod/v4/core/api.d.cts +284 -0
  799. package/node_modules/zod/v4/core/api.d.ts +284 -0
  800. package/node_modules/zod/v4/core/api.js +906 -0
  801. package/node_modules/zod/v4/core/checks.cjs +591 -0
  802. package/node_modules/zod/v4/core/checks.d.cts +278 -0
  803. package/node_modules/zod/v4/core/checks.d.ts +278 -0
  804. package/node_modules/zod/v4/core/checks.js +565 -0
  805. package/node_modules/zod/v4/core/core.cjs +67 -0
  806. package/node_modules/zod/v4/core/core.d.cts +49 -0
  807. package/node_modules/zod/v4/core/core.d.ts +49 -0
  808. package/node_modules/zod/v4/core/core.js +61 -0
  809. package/node_modules/zod/v4/core/doc.cjs +39 -0
  810. package/node_modules/zod/v4/core/doc.d.cts +14 -0
  811. package/node_modules/zod/v4/core/doc.d.ts +14 -0
  812. package/node_modules/zod/v4/core/doc.js +35 -0
  813. package/node_modules/zod/v4/core/errors.cjs +226 -0
  814. package/node_modules/zod/v4/core/errors.d.cts +208 -0
  815. package/node_modules/zod/v4/core/errors.d.ts +208 -0
  816. package/node_modules/zod/v4/core/errors.js +195 -0
  817. package/node_modules/zod/v4/core/function.cjs +102 -0
  818. package/node_modules/zod/v4/core/function.d.cts +52 -0
  819. package/node_modules/zod/v4/core/function.d.ts +52 -0
  820. package/node_modules/zod/v4/core/function.js +75 -0
  821. package/node_modules/zod/v4/core/index.cjs +44 -0
  822. package/node_modules/zod/v4/core/index.d.cts +15 -0
  823. package/node_modules/zod/v4/core/index.d.ts +15 -0
  824. package/node_modules/zod/v4/core/index.js +15 -0
  825. package/node_modules/zod/v4/core/json-schema.cjs +2 -0
  826. package/node_modules/zod/v4/core/json-schema.d.cts +87 -0
  827. package/node_modules/zod/v4/core/json-schema.d.ts +87 -0
  828. package/node_modules/zod/v4/core/json-schema.js +1 -0
  829. package/node_modules/zod/v4/core/parse.cjs +87 -0
  830. package/node_modules/zod/v4/core/parse.d.cts +25 -0
  831. package/node_modules/zod/v4/core/parse.d.ts +25 -0
  832. package/node_modules/zod/v4/core/parse.js +57 -0
  833. package/node_modules/zod/v4/core/regexes.cjs +103 -0
  834. package/node_modules/zod/v4/core/regexes.d.cts +62 -0
  835. package/node_modules/zod/v4/core/regexes.d.ts +62 -0
  836. package/node_modules/zod/v4/core/regexes.js +95 -0
  837. package/node_modules/zod/v4/core/registries.cjs +56 -0
  838. package/node_modules/zod/v4/core/registries.d.cts +35 -0
  839. package/node_modules/zod/v4/core/registries.d.ts +35 -0
  840. package/node_modules/zod/v4/core/registries.js +51 -0
  841. package/node_modules/zod/v4/core/schemas.cjs +1748 -0
  842. package/node_modules/zod/v4/core/schemas.d.cts +1041 -0
  843. package/node_modules/zod/v4/core/schemas.d.ts +1041 -0
  844. package/node_modules/zod/v4/core/schemas.js +1717 -0
  845. package/node_modules/zod/v4/core/standard-schema.cjs +2 -0
  846. package/node_modules/zod/v4/core/standard-schema.d.cts +55 -0
  847. package/node_modules/zod/v4/core/standard-schema.d.ts +55 -0
  848. package/node_modules/zod/v4/core/standard-schema.js +1 -0
  849. package/node_modules/zod/v4/core/to-json-schema.cjs +854 -0
  850. package/node_modules/zod/v4/core/to-json-schema.d.cts +88 -0
  851. package/node_modules/zod/v4/core/to-json-schema.d.ts +88 -0
  852. package/node_modules/zod/v4/core/to-json-schema.js +849 -0
  853. package/node_modules/zod/v4/core/util.cjs +539 -0
  854. package/node_modules/zod/v4/core/util.d.cts +183 -0
  855. package/node_modules/zod/v4/core/util.d.ts +183 -0
  856. package/node_modules/zod/v4/core/util.js +493 -0
  857. package/node_modules/zod/v4/core/versions.cjs +8 -0
  858. package/node_modules/zod/v4/core/versions.d.cts +5 -0
  859. package/node_modules/zod/v4/core/versions.d.ts +5 -0
  860. package/node_modules/zod/v4/core/versions.js +5 -0
  861. package/node_modules/zod/v4/index.cjs +22 -0
  862. package/node_modules/zod/v4/index.d.cts +3 -0
  863. package/node_modules/zod/v4/index.d.ts +3 -0
  864. package/node_modules/zod/v4/index.js +3 -0
  865. package/node_modules/zod/v4/locales/ar.cjs +142 -0
  866. package/node_modules/zod/v4/locales/ar.d.cts +4 -0
  867. package/node_modules/zod/v4/locales/ar.d.ts +4 -0
  868. package/node_modules/zod/v4/locales/ar.js +116 -0
  869. package/node_modules/zod/v4/locales/az.cjs +141 -0
  870. package/node_modules/zod/v4/locales/az.d.cts +4 -0
  871. package/node_modules/zod/v4/locales/az.d.ts +4 -0
  872. package/node_modules/zod/v4/locales/az.js +115 -0
  873. package/node_modules/zod/v4/locales/be.cjs +190 -0
  874. package/node_modules/zod/v4/locales/be.d.cts +4 -0
  875. package/node_modules/zod/v4/locales/be.d.ts +4 -0
  876. package/node_modules/zod/v4/locales/be.js +164 -0
  877. package/node_modules/zod/v4/locales/ca.cjs +144 -0
  878. package/node_modules/zod/v4/locales/ca.d.cts +4 -0
  879. package/node_modules/zod/v4/locales/ca.d.ts +4 -0
  880. package/node_modules/zod/v4/locales/ca.js +118 -0
  881. package/node_modules/zod/v4/locales/cs.cjs +161 -0
  882. package/node_modules/zod/v4/locales/cs.d.cts +4 -0
  883. package/node_modules/zod/v4/locales/cs.d.ts +4 -0
  884. package/node_modules/zod/v4/locales/cs.js +135 -0
  885. package/node_modules/zod/v4/locales/de.cjs +142 -0
  886. package/node_modules/zod/v4/locales/de.d.cts +4 -0
  887. package/node_modules/zod/v4/locales/de.d.ts +4 -0
  888. package/node_modules/zod/v4/locales/de.js +116 -0
  889. package/node_modules/zod/v4/locales/en.cjs +145 -0
  890. package/node_modules/zod/v4/locales/en.d.cts +5 -0
  891. package/node_modules/zod/v4/locales/en.d.ts +5 -0
  892. package/node_modules/zod/v4/locales/en.js +117 -0
  893. package/node_modules/zod/v4/locales/eo.cjs +144 -0
  894. package/node_modules/zod/v4/locales/eo.d.cts +5 -0
  895. package/node_modules/zod/v4/locales/eo.d.ts +5 -0
  896. package/node_modules/zod/v4/locales/eo.js +116 -0
  897. package/node_modules/zod/v4/locales/es.cjs +143 -0
  898. package/node_modules/zod/v4/locales/es.d.cts +4 -0
  899. package/node_modules/zod/v4/locales/es.d.ts +4 -0
  900. package/node_modules/zod/v4/locales/es.js +117 -0
  901. package/node_modules/zod/v4/locales/fa.cjs +148 -0
  902. package/node_modules/zod/v4/locales/fa.d.cts +4 -0
  903. package/node_modules/zod/v4/locales/fa.d.ts +4 -0
  904. package/node_modules/zod/v4/locales/fa.js +122 -0
  905. package/node_modules/zod/v4/locales/fi.cjs +148 -0
  906. package/node_modules/zod/v4/locales/fi.d.cts +4 -0
  907. package/node_modules/zod/v4/locales/fi.d.ts +4 -0
  908. package/node_modules/zod/v4/locales/fi.js +122 -0
  909. package/node_modules/zod/v4/locales/fr-CA.cjs +143 -0
  910. package/node_modules/zod/v4/locales/fr-CA.d.cts +4 -0
  911. package/node_modules/zod/v4/locales/fr-CA.d.ts +4 -0
  912. package/node_modules/zod/v4/locales/fr-CA.js +117 -0
  913. package/node_modules/zod/v4/locales/fr.cjs +142 -0
  914. package/node_modules/zod/v4/locales/fr.d.cts +4 -0
  915. package/node_modules/zod/v4/locales/fr.d.ts +4 -0
  916. package/node_modules/zod/v4/locales/fr.js +116 -0
  917. package/node_modules/zod/v4/locales/he.cjs +143 -0
  918. package/node_modules/zod/v4/locales/he.d.cts +4 -0
  919. package/node_modules/zod/v4/locales/he.d.ts +4 -0
  920. package/node_modules/zod/v4/locales/he.js +117 -0
  921. package/node_modules/zod/v4/locales/hu.cjs +143 -0
  922. package/node_modules/zod/v4/locales/hu.d.cts +4 -0
  923. package/node_modules/zod/v4/locales/hu.d.ts +4 -0
  924. package/node_modules/zod/v4/locales/hu.js +117 -0
  925. package/node_modules/zod/v4/locales/id.cjs +142 -0
  926. package/node_modules/zod/v4/locales/id.d.cts +4 -0
  927. package/node_modules/zod/v4/locales/id.d.ts +4 -0
  928. package/node_modules/zod/v4/locales/id.js +116 -0
  929. package/node_modules/zod/v4/locales/index.cjs +84 -0
  930. package/node_modules/zod/v4/locales/index.d.cts +39 -0
  931. package/node_modules/zod/v4/locales/index.d.ts +39 -0
  932. package/node_modules/zod/v4/locales/index.js +39 -0
  933. package/node_modules/zod/v4/locales/it.cjs +143 -0
  934. package/node_modules/zod/v4/locales/it.d.cts +4 -0
  935. package/node_modules/zod/v4/locales/it.d.ts +4 -0
  936. package/node_modules/zod/v4/locales/it.js +117 -0
  937. package/node_modules/zod/v4/locales/ja.cjs +141 -0
  938. package/node_modules/zod/v4/locales/ja.d.cts +4 -0
  939. package/node_modules/zod/v4/locales/ja.d.ts +4 -0
  940. package/node_modules/zod/v4/locales/ja.js +115 -0
  941. package/node_modules/zod/v4/locales/kh.cjs +143 -0
  942. package/node_modules/zod/v4/locales/kh.d.cts +4 -0
  943. package/node_modules/zod/v4/locales/kh.d.ts +4 -0
  944. package/node_modules/zod/v4/locales/kh.js +117 -0
  945. package/node_modules/zod/v4/locales/ko.cjs +147 -0
  946. package/node_modules/zod/v4/locales/ko.d.cts +4 -0
  947. package/node_modules/zod/v4/locales/ko.d.ts +4 -0
  948. package/node_modules/zod/v4/locales/ko.js +121 -0
  949. package/node_modules/zod/v4/locales/mk.cjs +144 -0
  950. package/node_modules/zod/v4/locales/mk.d.cts +4 -0
  951. package/node_modules/zod/v4/locales/mk.d.ts +4 -0
  952. package/node_modules/zod/v4/locales/mk.js +118 -0
  953. package/node_modules/zod/v4/locales/ms.cjs +142 -0
  954. package/node_modules/zod/v4/locales/ms.d.cts +4 -0
  955. package/node_modules/zod/v4/locales/ms.d.ts +4 -0
  956. package/node_modules/zod/v4/locales/ms.js +116 -0
  957. package/node_modules/zod/v4/locales/nl.cjs +143 -0
  958. package/node_modules/zod/v4/locales/nl.d.cts +4 -0
  959. package/node_modules/zod/v4/locales/nl.d.ts +4 -0
  960. package/node_modules/zod/v4/locales/nl.js +117 -0
  961. package/node_modules/zod/v4/locales/no.cjs +142 -0
  962. package/node_modules/zod/v4/locales/no.d.cts +4 -0
  963. package/node_modules/zod/v4/locales/no.d.ts +4 -0
  964. package/node_modules/zod/v4/locales/no.js +116 -0
  965. package/node_modules/zod/v4/locales/ota.cjs +143 -0
  966. package/node_modules/zod/v4/locales/ota.d.cts +4 -0
  967. package/node_modules/zod/v4/locales/ota.d.ts +4 -0
  968. package/node_modules/zod/v4/locales/ota.js +117 -0
  969. package/node_modules/zod/v4/locales/pl.cjs +143 -0
  970. package/node_modules/zod/v4/locales/pl.d.cts +4 -0
  971. package/node_modules/zod/v4/locales/pl.d.ts +4 -0
  972. package/node_modules/zod/v4/locales/pl.js +117 -0
  973. package/node_modules/zod/v4/locales/ps.cjs +148 -0
  974. package/node_modules/zod/v4/locales/ps.d.cts +4 -0
  975. package/node_modules/zod/v4/locales/ps.d.ts +4 -0
  976. package/node_modules/zod/v4/locales/ps.js +122 -0
  977. package/node_modules/zod/v4/locales/pt.cjs +142 -0
  978. package/node_modules/zod/v4/locales/pt.d.cts +4 -0
  979. package/node_modules/zod/v4/locales/pt.d.ts +4 -0
  980. package/node_modules/zod/v4/locales/pt.js +116 -0
  981. package/node_modules/zod/v4/locales/ru.cjs +190 -0
  982. package/node_modules/zod/v4/locales/ru.d.cts +4 -0
  983. package/node_modules/zod/v4/locales/ru.d.ts +4 -0
  984. package/node_modules/zod/v4/locales/ru.js +164 -0
  985. package/node_modules/zod/v4/locales/sl.cjs +143 -0
  986. package/node_modules/zod/v4/locales/sl.d.cts +4 -0
  987. package/node_modules/zod/v4/locales/sl.d.ts +4 -0
  988. package/node_modules/zod/v4/locales/sl.js +117 -0
  989. package/node_modules/zod/v4/locales/sv.cjs +144 -0
  990. package/node_modules/zod/v4/locales/sv.d.cts +4 -0
  991. package/node_modules/zod/v4/locales/sv.d.ts +4 -0
  992. package/node_modules/zod/v4/locales/sv.js +118 -0
  993. package/node_modules/zod/v4/locales/ta.cjs +143 -0
  994. package/node_modules/zod/v4/locales/ta.d.cts +4 -0
  995. package/node_modules/zod/v4/locales/ta.d.ts +4 -0
  996. package/node_modules/zod/v4/locales/ta.js +117 -0
  997. package/node_modules/zod/v4/locales/th.cjs +143 -0
  998. package/node_modules/zod/v4/locales/th.d.cts +4 -0
  999. package/node_modules/zod/v4/locales/th.d.ts +4 -0
  1000. package/node_modules/zod/v4/locales/th.js +117 -0
  1001. package/node_modules/zod/v4/locales/tr.cjs +143 -0
  1002. package/node_modules/zod/v4/locales/tr.d.cts +5 -0
  1003. package/node_modules/zod/v4/locales/tr.d.ts +5 -0
  1004. package/node_modules/zod/v4/locales/tr.js +115 -0
  1005. package/node_modules/zod/v4/locales/ua.cjs +143 -0
  1006. package/node_modules/zod/v4/locales/ua.d.cts +4 -0
  1007. package/node_modules/zod/v4/locales/ua.d.ts +4 -0
  1008. package/node_modules/zod/v4/locales/ua.js +117 -0
  1009. package/node_modules/zod/v4/locales/ur.cjs +143 -0
  1010. package/node_modules/zod/v4/locales/ur.d.cts +4 -0
  1011. package/node_modules/zod/v4/locales/ur.d.ts +4 -0
  1012. package/node_modules/zod/v4/locales/ur.js +117 -0
  1013. package/node_modules/zod/v4/locales/vi.cjs +142 -0
  1014. package/node_modules/zod/v4/locales/vi.d.cts +4 -0
  1015. package/node_modules/zod/v4/locales/vi.d.ts +4 -0
  1016. package/node_modules/zod/v4/locales/vi.js +116 -0
  1017. package/node_modules/zod/v4/locales/zh-CN.cjs +142 -0
  1018. package/node_modules/zod/v4/locales/zh-CN.d.cts +4 -0
  1019. package/node_modules/zod/v4/locales/zh-CN.d.ts +4 -0
  1020. package/node_modules/zod/v4/locales/zh-CN.js +116 -0
  1021. package/node_modules/zod/v4/locales/zh-TW.cjs +143 -0
  1022. package/node_modules/zod/v4/locales/zh-TW.d.cts +4 -0
  1023. package/node_modules/zod/v4/locales/zh-TW.d.ts +4 -0
  1024. package/node_modules/zod/v4/locales/zh-TW.js +117 -0
  1025. package/node_modules/zod/v4/mini/checks.cjs +34 -0
  1026. package/node_modules/zod/v4/mini/checks.d.cts +1 -0
  1027. package/node_modules/zod/v4/mini/checks.d.ts +1 -0
  1028. package/node_modules/zod/v4/mini/checks.js +1 -0
  1029. package/node_modules/zod/v4/mini/coerce.cjs +47 -0
  1030. package/node_modules/zod/v4/mini/coerce.d.cts +7 -0
  1031. package/node_modules/zod/v4/mini/coerce.d.ts +7 -0
  1032. package/node_modules/zod/v4/mini/coerce.js +17 -0
  1033. package/node_modules/zod/v4/mini/external.cjs +62 -0
  1034. package/node_modules/zod/v4/mini/external.d.cts +11 -0
  1035. package/node_modules/zod/v4/mini/external.d.ts +11 -0
  1036. package/node_modules/zod/v4/mini/external.js +13 -0
  1037. package/node_modules/zod/v4/mini/index.cjs +32 -0
  1038. package/node_modules/zod/v4/mini/index.d.cts +3 -0
  1039. package/node_modules/zod/v4/mini/index.d.ts +3 -0
  1040. package/node_modules/zod/v4/mini/index.js +3 -0
  1041. package/node_modules/zod/v4/mini/iso.cjs +60 -0
  1042. package/node_modules/zod/v4/mini/iso.d.cts +22 -0
  1043. package/node_modules/zod/v4/mini/iso.d.ts +22 -0
  1044. package/node_modules/zod/v4/mini/iso.js +30 -0
  1045. package/node_modules/zod/v4/mini/parse.cjs +8 -0
  1046. package/node_modules/zod/v4/mini/parse.d.cts +1 -0
  1047. package/node_modules/zod/v4/mini/parse.d.ts +1 -0
  1048. package/node_modules/zod/v4/mini/parse.js +1 -0
  1049. package/node_modules/zod/v4/mini/schemas.cjs +839 -0
  1050. package/node_modules/zod/v4/mini/schemas.d.cts +356 -0
  1051. package/node_modules/zod/v4/mini/schemas.d.ts +356 -0
  1052. package/node_modules/zod/v4/mini/schemas.js +732 -0
  1053. package/node_modules/zod/v4-mini/index.cjs +17 -0
  1054. package/node_modules/zod/v4-mini/index.d.cts +1 -0
  1055. package/node_modules/zod/v4-mini/index.d.ts +1 -0
  1056. package/node_modules/zod/v4-mini/index.js +1 -0
  1057. package/package.json +97 -0
@@ -0,0 +1,1937 @@
1
+ import { createHttpProxyServer } from './http-proxy.js';
2
+ import { createSocksProxyServer } from './socks-proxy.js';
3
+ import { createMuxProxyServer } from './mux-proxy.js';
4
+ import { listenInRange } from './listen-in-range.js';
5
+ import { SentinelRegistry } from './credential-sentinel.js';
6
+ import { MaskedFileStore, buildMaskedFileBinds, } from './credential-mask-files.js';
7
+ import { buildMaskedEnvVars } from './credential-mask-env.js';
8
+ import { AwsPairRegistry, createSigv4Planner, registerAwsPairs, } from './credential-aws-pairs.js';
9
+ import { certThumbprint, createMitmCA, CRL_PATH, disposeMitmCA, } from './mitm-ca.js';
10
+ import { logForDebugging } from '../utils/debug.js';
11
+ import { whichSync } from '../utils/which.js';
12
+ import { getPlatform, getWslVersion } from '../utils/platform.js';
13
+ import * as fs from 'fs';
14
+ import { randomBytes } from 'node:crypto';
15
+ import { wrapCommandWithSandboxLinux, initializeLinuxNetworkBridge, checkLinuxDependencies, cleanupBwrapMountPoints, linuxGetCwdMandatoryDenyPaths, } from './linux-sandbox-utils.js';
16
+ import { expandReadDenyGlobLinux } from './read-deny-glob.js';
17
+ import { wrapCommandWithSandboxMacOS, startMacOSSandboxLogMonitor, } from './macos-sandbox-utils.js';
18
+ import { startLinuxSandboxViolationMonitor, } from './linux-violation-monitor.js';
19
+ import { checkWindowsDependencies, checkWindowsDependenciesAsync, wrapCommandWithSandboxWindows, parseWindowsBinShell, expandWindowsFsPaths, stampWindowsAcl, restoreWindowsAcl, grantWindowsAcl, revokeWindowsAcl, getWindowsSandboxUserStatusAsync, getWindowsSandboxCaCert, ensurePersistentWindowsCa, verifyWindowsWfpEgress, resolveSrtWin, WindowsSandboxError, DEFAULT_WINDOWS_PROXY_PORT_RANGE, } from './windows-sandbox-utils.js';
20
+ import { getDefaultWritePaths, containsGlobChars, globPatternBaseDir, normalizePathForSandbox, removeTrailingGlobSuffix, expandGlobPattern, attributionKeyFor, decodeSandboxedCommand, encodeSandboxedCommand, } from './sandbox-utils.js';
21
+ import { SandboxViolationStore, sanitizeUnregisteredCommandKey, shouldIgnoreViolation, } from './sandbox-violation-store.js';
22
+ import { canonicalizeHost, isValidHost, redactUrl, resolveParentProxy, } from './parent-proxy.js';
23
+ import { matchesDomainPattern, matchesDomainPatternWithPort, stripDomainPatternPort, } from './domain-pattern.js';
24
+ import { createResolvedAddressGuard, isResolvedAddressDenied, } from './resolved-address-guard.js';
25
+ import { EOL } from 'node:os';
26
+ import { dirname } from 'node:path';
27
+ import { getJavaProxyAgentJarPathAsync } from './java-proxy-agent.js';
28
+ import { getApplySeccompBinaryPathAsync } from './generate-seccomp-filter.js';
29
+ // ============================================================================
30
+ // Private Module State
31
+ // ============================================================================
32
+ let config;
33
+ let httpProxyServer;
34
+ let socksProxyServer;
35
+ let muxProxyServer;
36
+ let managerContext;
37
+ let initializationPromise;
38
+ let cleanupRegistered = false;
39
+ let logMonitorShutdown;
40
+ let linuxMonitor;
41
+ let parentProxy;
42
+ /** Read live through {@link directLookup}, so a config update applies to the next dial. */
43
+ let resolvedAddressGuard = createResolvedAddressGuard();
44
+ let mitmCA;
45
+ /**
46
+ * Resolved path of the JVM proxy agent jar (see java-proxy-agent.ts); set
47
+ * while a proxy is advertised to the sandbox, undefined if the jar is not
48
+ * shipped/found (JVMs then just aren't proxy-aware, as before).
49
+ */
50
+ let javaAgentJarPath;
51
+ // Per-session proxy auth token. Generated at proxy start, exported only into
52
+ // the sandbox child env, checked on every CONNECT/request — so a host process
53
+ // dialing 127.0.0.1:<proxyPort> can't reach the filter callback.
54
+ let proxyAuthToken;
55
+ // Windows: the resolved access set that was actually applied at
56
+ // initialize(). `undefined` means no stamp/grant was applied
57
+ // (gates running `acl restore`/`acl revoke` at reset()).
58
+ let windowsFsStampedSet;
59
+ // The sandbox user SID captured at initialize(). reset() uses this
60
+ // so a config change between init and reset can't strand ACEs
61
+ // under a different SID.
62
+ let windowsFsSbUserSid;
63
+ // The RAW config inputs that produced `windowsFsStampedSet`.
64
+ // updateConfig() compares these (not the resolved set) so it never
65
+ // re-expands globs — see `sameWindowsStampSet`.
66
+ let windowsFsRawInputs;
67
+ // `verifyWindowsWfpEgress()` is once per PROCESS (it spawns a
68
+ // CreateProcessWithLogonW runner; first call may create the sandbox
69
+ // user's profile). The WFP fence is install-scoped, not config- or
70
+ // session-scoped — reset() does NOT clear this, so updateConfig()'s
71
+ // reset+reinit and the test suite's per-test reset() don't re-verify.
72
+ let windowsWfpVerified = false;
73
+ // Resolved once at initialize() (`resolveSrtWin` stats the disk).
74
+ // Captured so wrapWithSandboxArgv/reset() don't re-resolve per call
75
+ // and so reset()'s revoke/restore addresses the SAME binary the
76
+ // grants/stamps were applied with even if `config` mutated between.
77
+ let srtWinSpawn;
78
+ const sandboxViolationStore = new SandboxViolationStore();
79
+ // Per-session sentinel↔real-value map for masked credentials. Lives only in
80
+ // process memory; never written to disk or logged. Cleared on reset().
81
+ const sentinelRegistry = new SentinelRegistry();
82
+ // Per-session linked AWS credential pairs for SigV4 re-signing, keyed by
83
+ // the fake access key id. Same lifecycle and secrecy posture as the
84
+ // sentinel registry.
85
+ const awsPairRegistry = new AwsPairRegistry();
86
+ // Temp dir holding the sentinel-content fake files for masked credential
87
+ // files. Created lazily on first masked file; removed on reset().
88
+ const maskedFileStore = new MaskedFileStore();
89
+ // ============================================================================
90
+ // Private Helper Functions (not exported)
91
+ // ============================================================================
92
+ function registerCleanup() {
93
+ if (cleanupRegistered) {
94
+ return;
95
+ }
96
+ const cleanupHandler = () => reset().catch(e => {
97
+ logForDebugging(`Cleanup failed in registerCleanup ${e}`, {
98
+ level: 'error',
99
+ });
100
+ });
101
+ process.once('exit', cleanupHandler);
102
+ process.once('SIGINT', cleanupHandler);
103
+ process.once('SIGTERM', cleanupHandler);
104
+ cleanupRegistered = true;
105
+ }
106
+ /**
107
+ * Attribution key to command text for every wrapped invocation, so each
108
+ * producer can report (and ignoreViolations can match) the command an event
109
+ * belongs to rather than the opaque key. Keys are held decoded because that
110
+ * is the form the carriers deliver. Bounded FIFO: the violation store itself
111
+ * only retains the last 100 events, so long-gone invocations need no entry.
112
+ */
113
+ const MAX_COMMAND_TEXTS = 1024;
114
+ const commandTextsByKey = new Map();
115
+ /** Exported for testing. */
116
+ export function registerCommandText(command, options) {
117
+ const key = decodeSandboxedCommand(encodeSandboxedCommand(attributionKeyFor(command, options?.commandId)));
118
+ const text = options?.commandText ?? command;
119
+ commandTextsByKey.delete(key);
120
+ commandTextsByKey.set(key, text);
121
+ while (commandTextsByKey.size > MAX_COMMAND_TEXTS) {
122
+ const oldest = commandTextsByKey.keys().next().value;
123
+ if (oldest === undefined)
124
+ break;
125
+ commandTextsByKey.delete(oldest);
126
+ }
127
+ }
128
+ /**
129
+ * The command text for a decoded attribution key. Keys arrive over carriers
130
+ * the sandboxed process can write (the observe socket's event field, the
131
+ * macOS log tag, the proxy username), so only a key this process registered
132
+ * carries the embedder's own text; anything else is untrusted bytes.
133
+ * Exported for testing.
134
+ */
135
+ export function resolveCommandText(decodedKey) {
136
+ return (commandTextsByKey.get(decodedKey) ??
137
+ sanitizeUnregisteredCommandKey(decodedKey));
138
+ }
139
+ /**
140
+ * Record a proxy-side denial in the violation store so the model sees a
141
+ * structured <sandbox_violations> block alongside the raw 403 / SOCKS
142
+ * failure in stderr — parity with the macOS seatbelt log monitor and the
143
+ * Linux seccomp observer. The proxy is the only component that knows the
144
+ * destination host of a network deny, so neither of those can produce
145
+ * this line. `encodedCommand` (from the proxy username) attributes it to
146
+ * the invocation; without one the event is stored unattributed.
147
+ */
148
+ function recordProxyViolation(line, encodedCommand) {
149
+ const command = encodedCommand
150
+ ? resolveCommandText(decodeSandboxedCommand(encodedCommand))
151
+ : undefined;
152
+ // Same suppression the seatbelt / seccomp monitors apply, so a
153
+ // configured ignoreViolations pattern silences the event no matter
154
+ // which producer saw it.
155
+ if (shouldIgnoreViolation(line, command, config?.ignoreViolations)) {
156
+ return;
157
+ }
158
+ sandboxViolationStore.addViolation({
159
+ line,
160
+ encodedCommand,
161
+ command,
162
+ timestamp: new Date(),
163
+ });
164
+ }
165
+ function recordOutboundDeny(host, port, reason, encodedCommand) {
166
+ recordProxyViolation(`deny network-outbound ${host}:${port} (${reason})`, encodedCommand);
167
+ }
168
+ /** Direct-dial `lookup` for the proxies: the current guard's, with a refusal recorded as a violation. */
169
+ const directLookup = (port, encodedCommand) => (hostname, options, callback) => resolvedAddressGuard.lookupFor(port)(hostname, options, (err, address, family) => {
170
+ if (isResolvedAddressDenied(err)) {
171
+ recordOutboundDeny(hostname, port, err.reason, encodedCommand);
172
+ }
173
+ callback(err, address, family);
174
+ });
175
+ /**
176
+ * The request URL as it should appear in a model-visible violation line:
177
+ * origin + path, with any query string reduced to a `?…` marker (origin
178
+ * carries no userinfo, so an embedded `name:pass@` is dropped too). Query
179
+ * strings routinely carry credentials (api_key=, access_token=, signed
180
+ * URLs) that the sandboxed client interpolated at runtime and that were
181
+ * never in the model's context, so they must not enter the transcript via
182
+ * the <sandbox_violations> block. The full URL still reaches the embedder's
183
+ * filterRequest callback and its own debug logging.
184
+ */
185
+ function redactUrlForViolation(url) {
186
+ try {
187
+ const u = new URL(url);
188
+ return `${u.origin}${u.pathname}${u.search ? '?…' : ''}`;
189
+ }
190
+ catch {
191
+ // Not an absolute URL (shouldn't happen for proxy requests) — drop
192
+ // anything after '?' rather than risk leaking it.
193
+ const q = url.indexOf('?');
194
+ return q === -1 ? url : `${url.slice(0, q)}?…`;
195
+ }
196
+ }
197
+ async function filterNetworkRequest(port, host, sandboxAskCallback, encodedCommand) {
198
+ const denied = (reason) => {
199
+ recordOutboundDeny(host, port, reason, encodedCommand);
200
+ return false;
201
+ };
202
+ if (!config) {
203
+ logForDebugging('No config available, denying network request');
204
+ return denied('sandbox policy unavailable');
205
+ }
206
+ // Reject hosts containing control characters before pattern matching.
207
+ // `matchesDomainPattern` uses string suffix matching which is trivially
208
+ // fooled by e.g. `evil.com\x00.allowed.com` — the null byte passes
209
+ // `.endsWith()` but truncates at the libc DNS layer. The SOCKS path is the
210
+ // main exposure (DOMAINNAME is unvalidated bytes); HTTP is protected by
211
+ // llhttp/URL parsing, but we check here for defence in depth.
212
+ if (!isValidHost(host)) {
213
+ logForDebugging(`Denying malformed host: ${JSON.stringify(host)}:${port}`, {
214
+ level: 'error',
215
+ });
216
+ return denied('malformed host');
217
+ }
218
+ // Canonicalize so string comparisons match what getaddrinfo() will dial.
219
+ // Without this, inet_aton shorthand like `2852039166` (= 169.254.169.254)
220
+ // or `127.1` slips past a denylist entry for the dotted-decimal form.
221
+ const canonicalHost = canonicalizeHost(host) ?? host;
222
+ // Check denied domains first
223
+ for (const deniedDomain of config.network.deniedDomains) {
224
+ if (matchesDomainPatternWithPort(canonicalHost, port, deniedDomain)) {
225
+ logForDebugging(`Denied by config rule: ${host}:${port}`);
226
+ // The matched entry's own reason when the caller supplied one, so the
227
+ // model reads why this destination is off-limits (and the sanctioned
228
+ // alternative) instead of a generic deny; keyed by the exact entry.
229
+ return denied(config.network.deniedDomainReasons?.[deniedDomain] ??
230
+ 'host is on the deny list');
231
+ }
232
+ }
233
+ // Check allowed domains
234
+ for (const allowedDomain of config.network.allowedDomains) {
235
+ if (matchesDomainPatternWithPort(canonicalHost, port, allowedDomain)) {
236
+ logForDebugging(`Allowed by config rule: ${host}:${port}`);
237
+ return true;
238
+ }
239
+ }
240
+ // No matching rules - ask user or deny. strictAllowlist makes the
241
+ // allowlist deterministic enforcement: never fall through to the callback.
242
+ if (!sandboxAskCallback || config.network.strictAllowlist) {
243
+ logForDebugging(`No matching config rule, denying: ${host}:${port}`);
244
+ return denied('host is not on the allow list');
245
+ }
246
+ logForDebugging(`No matching config rule, asking user: ${host}:${port}`);
247
+ try {
248
+ const userAllowed = await sandboxAskCallback({ host, port });
249
+ if (userAllowed) {
250
+ logForDebugging(`User allowed: ${host}:${port}`);
251
+ return true;
252
+ }
253
+ logForDebugging(`User denied: ${host}:${port}`);
254
+ return denied('user denied');
255
+ }
256
+ catch (error) {
257
+ logForDebugging(`Error in permission callback: ${error}`, {
258
+ level: 'error',
259
+ });
260
+ return denied('permission prompt failed');
261
+ }
262
+ }
263
+ /**
264
+ * Build the header-mutation callback that substitutes sentinel→real for
265
+ * masked credentials. Returns undefined when no `credentials` block is
266
+ * configured — wiring the seam at all is unnecessary then.
267
+ *
268
+ * Per-host gating happens inside the registry: each sentinel carries its
269
+ * own injectHosts list and substitutes independently, so credential A's
270
+ * sentinel cannot be laundered through credential B's allowed host. The
271
+ * returned closure does not log header values; the registry holds the only
272
+ * copy of the real value.
273
+ */
274
+ function buildCredentialInjector() {
275
+ if (!config?.credentials)
276
+ return undefined;
277
+ return (headers, destHost) => {
278
+ sentinelRegistry.substituteInHeaders(headers, destHost, matchesDomainPattern);
279
+ };
280
+ }
281
+ /**
282
+ * Body counterpart of {@link buildCredentialInjector}: per-destination
283
+ * sentinel→real pairs for streaming substitution in request bodies, with
284
+ * the same per-credential injectHosts gating applied inside the registry.
285
+ */
286
+ function buildBodyCredentialInjector() {
287
+ if (!config?.credentials)
288
+ return undefined;
289
+ return destHost => sentinelRegistry.sentinelsForHost(destHost, matchesDomainPattern);
290
+ }
291
+ /**
292
+ * Build the per-request SigV4 hook for the TLS-terminating proxy.
293
+ * Returns undefined when no `credentials` block is configured. The hook
294
+ * consults {@link awsPairRegistry} at request time, so pairs registered
295
+ * later (wrapWithSandbox runs after the proxy starts) are picked up.
296
+ */
297
+ function buildSigv4Planner() {
298
+ if (!config?.credentials)
299
+ return undefined;
300
+ // Re-read the policies per request (not captured at proxy start) so an
301
+ // updateConfig() that changes credentials.sigv4 takes effect without a
302
+ // proxy restart, matching how the injector sees live registry state.
303
+ return (method, requestTarget, headers, destHost) => createSigv4Planner(awsPairRegistry, config?.credentials?.sigv4, matchesDomainPattern)(method, requestTarget, headers, destHost);
304
+ }
305
+ /**
306
+ * Get the MITM proxy socket path for a given host, if configured.
307
+ * Returns the socket path if the host matches any MITM domain pattern,
308
+ * otherwise returns undefined.
309
+ *
310
+ * Matches the canonicalized hostname, like the allow/deny filter
311
+ * (filterNetworkRequest) and the tlsTerminate exclusion below. This site
312
+ * fails OPEN on a miss — a host that matches no MITM pattern is dialed
313
+ * directly — so it must accept exactly the set of spellings the allowlist
314
+ * accepts: otherwise `api.example.com.` (trailing-dot FQDN, same name to
315
+ * DNS) passes the allowlist as `api.example.com` but misses every MITM
316
+ * pattern and skips the MITM proxy entirely. The proxies already hand this
317
+ * hook the canonical spelling; canonicalizing again here is defence in
318
+ * depth for any other caller.
319
+ */
320
+ function getMitmSocketPath(host) {
321
+ if (!config?.network.mitmProxy) {
322
+ return undefined;
323
+ }
324
+ const { socketPath, domains } = config.network.mitmProxy;
325
+ const canonicalHost = canonicalizeHost(host) ?? host;
326
+ for (const pattern of domains) {
327
+ if (matchesDomainPattern(canonicalHost, pattern)) {
328
+ logForDebugging(`Host ${host} matches MITM pattern ${pattern}`);
329
+ return socketPath;
330
+ }
331
+ }
332
+ return undefined;
333
+ }
334
+ /**
335
+ * Per-host TLS-termination opt-out from network.tlsTerminate.excludeDomains.
336
+ * Only consulted by the HTTP proxy when tlsTerminate is enabled; exempted
337
+ * hosts fall back to the opaque CONNECT tunnel (still allowlist-filtered),
338
+ * so mTLS / cert-pinning clients can complete their own handshake.
339
+ *
340
+ * Matches the canonicalized hostname, like the allow/deny filter
341
+ * (filterNetworkRequest) — otherwise a spelling the allowlist accepts after
342
+ * canonicalization (`127.1`, a trailing-dot FQDN) would dodge the exclusion
343
+ * and get terminated anyway.
344
+ */
345
+ function shouldTerminateTLSForHost(host) {
346
+ const excludeDomains = config?.network.tlsTerminate?.excludeDomains;
347
+ if (!excludeDomains?.length)
348
+ return true;
349
+ const canonicalHost = canonicalizeHost(host) ?? host;
350
+ for (const pattern of excludeDomains) {
351
+ if (!matchesDomainPattern(canonicalHost, pattern))
352
+ continue;
353
+ logForDebugging(`Host ${host} matches tlsTerminate.excludeDomains pattern ${pattern}; skipping TLS termination`);
354
+ // Masked-credential substitution only happens on the terminated path,
355
+ // so a credential whose injectHosts cover this host can never be
356
+ // injected here — the upstream gets the placeholder. Config validation
357
+ // rejects the fully-contradictory spellings; this flags the partial
358
+ // ones (e.g. default injectHosts = allowedDomains) at the moment they
359
+ // actually bite.
360
+ const masked = sentinelRegistry.namesInjectableAt(canonicalHost, matchesDomainPattern);
361
+ if (masked.length > 0) {
362
+ logForDebugging(`tlsTerminate.excludeDomains: masked credential(s) ${masked.join(', ')} ` +
363
+ `are configured for injection at ${host}, but its connections are ` +
364
+ `not terminated, so the upstream will receive the placeholder`, { level: 'error' });
365
+ }
366
+ return false;
367
+ }
368
+ return true;
369
+ }
370
+ async function startMuxProxyServer(sandboxAskCallback, portRange) {
371
+ const injectCredentials = buildCredentialInjector();
372
+ const injectBodyCredentials = buildBodyCredentialInjector();
373
+ httpProxyServer = createHttpProxyServer({
374
+ filter: (port, host, _socket, encodedCommand) => filterNetworkRequest(port, host, sandboxAskCallback, encodedCommand),
375
+ getMitmSocketPath,
376
+ mitmCA,
377
+ shouldTerminateTLS: shouldTerminateTLSForHost,
378
+ filterRequest: config?.network.filterRequest,
379
+ onFilterRequestDenied: ({ method, url, reason, encodedCommand }) => {
380
+ recordProxyViolation(`deny http-request ${method} ${redactUrlForViolation(url)} (${reason})`, encodedCommand);
381
+ },
382
+ // TLS-terminated path always gets the injector; the plain-HTTP path
383
+ // only when explicitly opted in. Without the opt-in, a sentinel sent
384
+ // over plain HTTP reaches the upstream unchanged (fails closed).
385
+ mutateHeaders: injectCredentials,
386
+ mutateHeadersPlaintext: config?.credentials?.allowPlaintextInject
387
+ ? injectCredentials
388
+ : undefined,
389
+ getBodySubstitutions: injectBodyCredentials,
390
+ getBodySubstitutionsPlaintext: config?.credentials?.allowPlaintextInject
391
+ ? injectBodyCredentials
392
+ : undefined,
393
+ // SigV4 re-signing is TLS-terminated-path only, like credential
394
+ // injection: the real signature must not travel over plaintext.
395
+ planSigv4: buildSigv4Planner(),
396
+ parentProxy,
397
+ lookupFor: directLookup,
398
+ proxyAuthToken,
399
+ });
400
+ socksProxyServer = createSocksProxyServer({
401
+ filter: (port, host, encodedCommand) => filterNetworkRequest(port, host, sandboxAskCallback, encodedCommand),
402
+ parentProxy,
403
+ lookupFor: directLookup,
404
+ proxyAuthToken,
405
+ probeUnauthenticated: async (port, host) => {
406
+ // Explicit deny rules only: an unauthenticated peer must never reach
407
+ // the ask callback, and a merely off-list host gets the generic
408
+ // cannot-authenticate refusal rather than a policy claim.
409
+ if (!config)
410
+ return {};
411
+ const canonical = canonicalizeHost(host) ?? host;
412
+ for (const entry of config.network.deniedDomains) {
413
+ if (matchesDomainPatternWithPort(canonical, port, entry)) {
414
+ const reason = config.network.deniedDomainReasons?.[entry] ??
415
+ 'host is on the deny list';
416
+ recordOutboundDeny(host, port, reason);
417
+ return { deniedReason: reason };
418
+ }
419
+ }
420
+ return {};
421
+ },
422
+ });
423
+ muxProxyServer = createMuxProxyServer({
424
+ httpServer: httpProxyServer,
425
+ handleSocksConnection: s => socksProxyServer.handleConnection(s),
426
+ httpBackendPortRange: portRange,
427
+ });
428
+ const mux = muxProxyServer;
429
+ // Backend first so the front-end never accepts a connection that would
430
+ // dispatch to an unbound backend. On Windows the backend's port is
431
+ // excluded when binding the front-end in the same WFP range.
432
+ const backendPort = await mux.listenHttpBackend();
433
+ await listenInRange(mux.server, p => mux.server.listen(p, '127.0.0.1'), portRange, backendPort !== undefined ? new Set([backendPort]) : new Set());
434
+ const muxPort = mux.getPort();
435
+ if (muxPort === undefined) {
436
+ throw new Error('Failed to get mux proxy server port');
437
+ }
438
+ mux.unref();
439
+ logForDebugging(`Mux proxy (HTTP+SOCKS) listening on localhost:${muxPort}`);
440
+ return muxPort;
441
+ }
442
+ // ============================================================================
443
+ // Public Module Functions (will be exported via namespace)
444
+ // ============================================================================
445
+ async function initialize(runtimeConfig, sandboxAskCallback, enableLogMonitor = false) {
446
+ // Return if already initializing
447
+ if (initializationPromise) {
448
+ await initializationPromise;
449
+ return;
450
+ }
451
+ // Store config for use by other functions
452
+ config = runtimeConfig;
453
+ // Resolve parent/upstream proxy from config or HTTP_PROXY env before we
454
+ // start our own listeners (which will later shadow those vars in the child).
455
+ parentProxy = resolveParentProxy(runtimeConfig.network.parentProxy);
456
+ if (parentProxy) {
457
+ logForDebugging(`Parent proxy configured: http=${redactUrl(parentProxy.httpUrl)} ` +
458
+ `https=${redactUrl(parentProxy.httpsUrl)}`);
459
+ }
460
+ resolvedAddressGuard = createResolvedAddressGuard(runtimeConfig.network);
461
+ // Load TLS-termination CA if configured. Throws on unreadable/non-PEM —
462
+ // tlsTerminate is explicit opt-in, so a bad config is a hard error.
463
+ if (runtimeConfig.network.tlsTerminate && runtimeConfig.network.mitmProxy) {
464
+ throw new Error('network.tlsTerminate and network.mitmProxy are mutually exclusive');
465
+ }
466
+ // On Windows with tlsTerminate and no explicit caCertPath/caKeyPath,
467
+ // defer CA creation until the Windows block below has resolved
468
+ // srt-win and fetched user status — the persistent CA is
469
+ // generated-if-absent under windowsStateDir()/ca and
470
+ // trusted in the sandbox user's Root store, then loaded here.
471
+ // Explicit paths (or non-Windows) go straight to createMitmCA.
472
+ const tlsTerminate = runtimeConfig.network.tlsTerminate;
473
+ const useWindowsPersistentCa = getPlatform() === 'windows' &&
474
+ tlsTerminate !== undefined &&
475
+ !tlsTerminate.caCertPath &&
476
+ !tlsTerminate.caKeyPath;
477
+ mitmCA =
478
+ tlsTerminate && !useWindowsPersistentCa
479
+ ? createMitmCA(tlsTerminate)
480
+ : undefined;
481
+ // Check dependencies
482
+ const deps = await checkDependenciesAsync();
483
+ if (deps.errors.length > 0) {
484
+ throw new Error(`Sandbox dependencies not available: ${deps.errors.join(', ')}`);
485
+ }
486
+ // Start log monitor for macOS if enabled
487
+ if (enableLogMonitor && getPlatform() === 'macos') {
488
+ logMonitorShutdown = startMacOSSandboxLogMonitor(sandboxViolationStore.addViolation.bind(sandboxViolationStore), config.ignoreViolations, resolveCommandText);
489
+ logForDebugging('Started macOS sandbox log monitor');
490
+ }
491
+ if (enableLogMonitor && getPlatform() === 'linux') {
492
+ // The monitor compares paths the kernel reported, so its lists are
493
+ // expanded the way the wrapper expands them (getFsWriteConfig folds in
494
+ // the default write paths and drops the globs bwrap cannot take;
495
+ // normalizePathForSandbox resolves `~`, relative spellings and symlinks),
496
+ // plus the built-in write denies the wrapper always applies.
497
+ // It does not reproduce the wrapper's existence and boundary-symlink
498
+ // filters, nor the ripgrep scan for nested dangerous paths; and it still
499
+ // reports writes bwrap permits through `--dev`, `--proc` and the tmpfs
500
+ // over each read-denied directory. Started once, so both lists are fixed
501
+ // at the cwd and configuration of this call.
502
+ const monitoredWrites = getFsWriteConfig();
503
+ linuxMonitor = startLinuxSandboxViolationMonitor(sandboxViolationStore.addViolation.bind(sandboxViolationStore), {
504
+ // apply-seccomp's observer reports every write-intent syscall
505
+ // (allowed or not). Only paths bwrap would actually refuse — outside
506
+ // allowWrite or inside a denyWrite carve-out — go to the store. With
507
+ // the policy on, the default write paths are listed in full rather
508
+ // than as getFsWriteConfig() narrowed them: a home directory it leaves
509
+ // out because it is read-denied sits under that deny's writable
510
+ // tmpfs, so a write there is permitted and is not a violation.
511
+ allowWritePaths: [
512
+ ...monitoredWrites.allowOnly,
513
+ ...(config.filesystem.disabled ? [] : getDefaultWritePaths()),
514
+ ].map(p => normalizePathForSandbox(p)),
515
+ denyWritePaths: [
516
+ ...monitoredWrites.denyWithinAllow.map(p => normalizePathForSandbox(p)),
517
+ // filesystem.disabled reaches the wrapper as `writeConfig ===
518
+ // undefined`, which skips every bind and the built-in denies with
519
+ // them, so the monitor must not judge by them either.
520
+ ...(config.filesystem.disabled
521
+ ? []
522
+ : linuxGetCwdMandatoryDenyPaths(getAllowGitConfig())),
523
+ ],
524
+ ignoreViolations: config.ignoreViolations,
525
+ resolveCommandText,
526
+ });
527
+ // Don't block initialization on listen() — wrap-time checks
528
+ // fs.existsSync(observeSocketPath) and degrades gracefully.
529
+ void linuxMonitor.ready;
530
+ logForDebugging('Started Linux seccomp violation monitor');
531
+ }
532
+ // Register cleanup handlers first time
533
+ registerCleanup();
534
+ // Windows: validate provisioning + filesystem config BEFORE any
535
+ // sandboxed child can be spawned. Doing this at initialize() (not
536
+ // wrap-time) means the host gets a single actionable error before
537
+ // any per-exec work happens, instead of exit-15 on every command.
538
+ if (getPlatform() === 'windows') {
539
+ // Resolve once (stats disk); captured module-level for wrap/reset.
540
+ srtWinSpawn = resolveSrtWin(runtimeConfig.windows?.srtWin);
541
+ const srtWin = srtWinSpawn;
542
+ const u = await getWindowsSandboxUserStatusAsync({ srtWin });
543
+ if (!u.provisioned || !u.credPresent) {
544
+ config = undefined;
545
+ throw new WindowsSandboxError('not_provisioned', `Windows sandbox user is not provisioned (user=` +
546
+ `${u.provisioned}, cred=${u.credPresent}). Run \`npx ` +
547
+ `sandbox-runtime windows-install\` (one UAC prompt) to ` +
548
+ `provision it.`);
549
+ }
550
+ // Behavioral proof the WFP egress fence is active for the
551
+ // sandbox user — BFE enumeration (`wfp status`) is admin-gated,
552
+ // so this is the non-elevated readiness check. Fails closed: a
553
+ // stale install (user provisioned but filters since removed)
554
+ // throws here instead of running every exec with full egress.
555
+ // After the user-status check so the not-provisioned message is
556
+ // the actionable one. Once per process — the fence is install-
557
+ // scoped, not session-scoped.
558
+ if (!windowsWfpVerified) {
559
+ try {
560
+ await verifyWindowsWfpEgress({
561
+ proxyPortRange: runtimeConfig.windows?.proxyPortRange,
562
+ srtWin,
563
+ });
564
+ }
565
+ catch (e) {
566
+ config = undefined;
567
+ throw e;
568
+ }
569
+ windowsWfpVerified = true;
570
+ }
571
+ // Persistent-CA branch (see the deferral comment above).
572
+ // `ensurePersistentWindowsCa` reconciles the registry thumb
573
+ // itself (so initialize() after uninstall→reinstall repairs
574
+ // trust) and may make `u.caCertThumb` stale — hence the
575
+ // explicit-path thumb check below skips this branch.
576
+ if (useWindowsPersistentCa && tlsTerminate) {
577
+ try {
578
+ const p = await ensurePersistentWindowsCa({ status: u, srtWin });
579
+ mitmCA = createMitmCA({
580
+ caCertPem: p.certPem,
581
+ caKeyPem: p.keyPem,
582
+ caCertPath: p.certPath,
583
+ caKeyPath: p.keyPath,
584
+ extraCaCertPaths: tlsTerminate.extraCaCertPaths,
585
+ });
586
+ }
587
+ catch (e) {
588
+ config = undefined;
589
+ throw e;
590
+ }
591
+ }
592
+ // Explicit-path branch: schannel clients (System32 curl, IWR,
593
+ // .NET, default-backend git) only trust what's in the sandbox
594
+ // user's `CurrentUser\Root` — which `srt-win exec` does not (and
595
+ // must not) write. Compare thumbprints so a stale install-time
596
+ // CA doesn't pass the gate while schannel rejects the session's
597
+ // proxy-minted leaves.
598
+ if (tlsTerminate && mitmCA && !useWindowsPersistentCa) {
599
+ const installed = getWindowsSandboxCaCert(u);
600
+ const sessionThumb = certThumbprint(mitmCA.certPem);
601
+ if (!installed) {
602
+ config = undefined;
603
+ throw new WindowsSandboxError('trust_ca_not_installed', `tlsTerminate on Windows requires the sandbox to be ` +
604
+ `installed with this CA (thumb=${sessionThumb}): run ` +
605
+ `\`srt-win user trust-ca ${mitmCA.certPath}\`. Per-exec ` +
606
+ `installs into the sandbox user's Root store are not ` +
607
+ `supported.`);
608
+ }
609
+ if (installed.thumb !== sessionThumb) {
610
+ config = undefined;
611
+ throw new WindowsSandboxError('trust_ca_thumbprint_mismatch', `tlsTerminate on Windows: the sandbox's installed CA ` +
612
+ `(thumb=${installed.thumb}) doesn't match this ` +
613
+ `session's CA (thumb=${sessionThumb}). Run \`srt-win ` +
614
+ `user trust-ca ${mitmCA.certPath}\` to update it.`);
615
+ }
616
+ }
617
+ // Filesystem grants/denies — additive sandbox-user ACEs.
618
+ try {
619
+ const acc = computeWindowsFsAccessSet(runtimeConfig);
620
+ // The trust bundle the CA-trust env vars point at
621
+ // (NODE_EXTRA_CA_CERTS etc.) must be readable by the
622
+ // srt-sandbox child. It's written into the broker's %TEMP%,
623
+ // which the sandbox user has no inherent rights on, so it
624
+ // rides the same session-level `acl grant` read-set as the
625
+ // working tree. Granted on the mkdtemp DIR (not the file)
626
+ // so the (OI)(CI) ACE covers both the file open AND the
627
+ // parent-directory list that cmd's `type`/`FindFirstFile`
628
+ // does before opening. Mirrors the mac/linux
629
+ // `expandedAllowRead` push in wrapWithSandbox.
630
+ if (mitmCA) {
631
+ acc.grantRead.push(dirname(mitmCA.trustBundlePath));
632
+ }
633
+ // `u` was fetched once above for the provisioning gate; the
634
+ // same status carries the SID — don't re-spawn `srt-win user
635
+ // status` here.
636
+ if (!u.sid) {
637
+ throw new Error('sandbox user SID missing from `srt-win user status` ' +
638
+ '(provisioned but in an inconsistent state)');
639
+ }
640
+ const sb = u.sid;
641
+ // Record module-level state BEFORE the first acl call so the
642
+ // catch's best-effort revoke/restore can address whatever
643
+ // partially landed.
644
+ windowsFsSbUserSid = sb;
645
+ // Grant FIRST so the sandbox user has working-tree access by
646
+ // the time the deny stamp runs. The two are independent
647
+ // refcounted state-DB sets keyed on the same holder PID.
648
+ if (acc.grantRead.length > 0 || acc.grantWrite.length > 0) {
649
+ grantWindowsAcl({
650
+ sandboxUserSid: sb,
651
+ read: acc.grantRead,
652
+ write: acc.grantWrite,
653
+ srtWin,
654
+ });
655
+ }
656
+ if (acc.denyRead.length > 0 || acc.denyWrite.length > 0) {
657
+ stampWindowsAcl({
658
+ sandboxUserSid: sb,
659
+ denyRead: acc.denyRead,
660
+ denyWrite: acc.denyWrite,
661
+ srtWin,
662
+ });
663
+ }
664
+ // Only record when something was actually applied — gates
665
+ // running revoke/restore at reset(). Recorded AFTER success —
666
+ // the catch below clears `config`, and a non-undefined
667
+ // stampedSet would leave reset()/updateConfig() seeing state
668
+ // that never landed.
669
+ const anyApplied = acc.grantRead.length > 0 ||
670
+ acc.grantWrite.length > 0 ||
671
+ acc.denyRead.length > 0 ||
672
+ acc.denyWrite.length > 0;
673
+ if (anyApplied) {
674
+ windowsFsStampedSet = acc;
675
+ logForDebugging(`[Sandbox Windows] fs applied: ` +
676
+ `${acc.grantWrite.length} grantWrite, ` +
677
+ `${acc.grantRead.length} grantRead, ` +
678
+ `${acc.denyRead.length} denyRead, ` +
679
+ `${acc.denyWrite.length} denyWrite`);
680
+ }
681
+ windowsFsRawInputs = rawWindowsFsInputs(runtimeConfig);
682
+ }
683
+ catch (e) {
684
+ // Best-effort release of whatever WAS applied before the
685
+ // failure (exit-2 partial stamps/grants the resolvable
686
+ // inputs; harmless if nothing was — no holds for this PID).
687
+ if (windowsFsSbUserSid) {
688
+ revokeWindowsAcl({ sandboxUserSid: windowsFsSbUserSid, srtWin });
689
+ restoreWindowsAcl({ sandboxUserSid: windowsFsSbUserSid, srtWin });
690
+ }
691
+ windowsFsSbUserSid = undefined;
692
+ config = undefined;
693
+ throw e;
694
+ }
695
+ }
696
+ // Initialize network infrastructure
697
+ initializationPromise = (async () => {
698
+ try {
699
+ // On Windows the WFP loopback permit covers a fixed port
700
+ // range, so the proxies must bind inside it. Other platforms
701
+ // bake the actual ephemeral port into the sandbox profile, so
702
+ // they keep using port 0.
703
+ const portRange = getPlatform() === 'windows'
704
+ ? (config.windows?.proxyPortRange ?? DEFAULT_WINDOWS_PROXY_PORT_RANGE)
705
+ : undefined;
706
+ // The auth token is only set when this process owns the proxy; an
707
+ // external proxy (config.network.httpProxyPort) handles its own auth,
708
+ // and embedding our token in its URL would be wrong.
709
+ proxyAuthToken =
710
+ config.network.httpProxyPort !== undefined
711
+ ? undefined
712
+ : randomBytes(16).toString('hex');
713
+ // The mux front-end serves both protocols on one port. Each side's
714
+ // reported port is the external override if configured, else the mux
715
+ // port — so the public config.network.{http,socks}ProxyPort contract
716
+ // is unchanged. The mux is skipped only when BOTH are external.
717
+ const needLocalProxy = config.network.httpProxyPort === undefined ||
718
+ config.network.socksProxyPort === undefined;
719
+ const muxPort = needLocalProxy
720
+ ? await startMuxProxyServer(sandboxAskCallback, portRange)
721
+ : undefined;
722
+ const httpProxyPort = config.network.httpProxyPort ?? muxPort;
723
+ const socksProxyPort = config.network.socksProxyPort ?? muxPort;
724
+ // JVMs read neither HTTPS_PROXY nor its credential; the agent bridges
725
+ // both. Resolved once here, advertised via JAVA_TOOL_OPTIONS per command.
726
+ // Async: the global-npm fallback spawns `npm root -g`.
727
+ javaAgentJarPath =
728
+ (await getJavaProxyAgentJarPathAsync(config.javaAgentJarPath)) ??
729
+ undefined;
730
+ // Leaves are minted lazily per-CONNECT (after this point), so setting
731
+ // the CDP URL now means every leaf carries it. See MitmCA.crlUrl.
732
+ // Windows-only: on Linux the child runs under bwrap --unshare-net and
733
+ // reaches the proxy via a socat bridge on a fixed netns port, so a
734
+ // host-namespace mux port would be unreachable — worse than no CDP,
735
+ // since a Schannel-analog client (Java, OpenSSL with CRL_CHECK) then
736
+ // hard-fails "CRL fetch error" instead of soft-passing "no CDP". macOS
737
+ // has no in-tree Schannel-analog client. Also gated on `muxPort`: an
738
+ // external `network.httpProxyPort` doesn't answer /srt.crl.
739
+ if (mitmCA && muxPort !== undefined && getPlatform() === 'windows') {
740
+ mitmCA.crlUrl = `http://127.0.0.1:${muxPort}${CRL_PATH}`;
741
+ }
742
+ if (config.network.httpProxyPort !== undefined) {
743
+ logForDebugging(`Using external HTTP proxy on port ${httpProxyPort}`);
744
+ }
745
+ if (config.network.socksProxyPort !== undefined) {
746
+ logForDebugging(`Using external SOCKS proxy on port ${socksProxyPort}`);
747
+ }
748
+ // Initialize platform-specific infrastructure
749
+ let linuxBridge;
750
+ if (getPlatform() === 'linux') {
751
+ linuxBridge = await initializeLinuxNetworkBridge(httpProxyPort, socksProxyPort, config.socatPath);
752
+ }
753
+ const context = {
754
+ httpProxyPort,
755
+ socksProxyPort,
756
+ linuxBridge,
757
+ };
758
+ managerContext = context;
759
+ logForDebugging('Network infrastructure initialized');
760
+ return context;
761
+ }
762
+ catch (error) {
763
+ // Clear state on error so initialization can be retried
764
+ initializationPromise = undefined;
765
+ managerContext = undefined;
766
+ reset().catch(e => {
767
+ logForDebugging(`Cleanup failed in initializationPromise ${e}`, {
768
+ level: 'error',
769
+ });
770
+ });
771
+ throw error;
772
+ }
773
+ })();
774
+ await initializationPromise;
775
+ }
776
+ function isSupportedPlatform() {
777
+ const platform = getPlatform();
778
+ if (platform === 'linux') {
779
+ // WSL1 doesn't support bubblewrap
780
+ return getWslVersion() !== '1';
781
+ }
782
+ return platform === 'macos' || platform === 'windows';
783
+ }
784
+ function isSandboxingEnabled() {
785
+ // Sandboxing is enabled if config has been set (via initialize())
786
+ return config !== undefined;
787
+ }
788
+ /**
789
+ * Platform-independent part of the dependency check. Returns either
790
+ * a finished result (POSIX, unsupported platform, or a Windows
791
+ * srt-win resolution failure) or the inputs for the Windows probe —
792
+ * the only platform where the sync and async variants differ.
793
+ */
794
+ function checkDependenciesCommon(ripgrepConfig) {
795
+ if (!isSupportedPlatform()) {
796
+ return { done: { errors: ['Unsupported platform'], warnings: [] } };
797
+ }
798
+ const errors = [];
799
+ const warnings = [];
800
+ const platform = getPlatform();
801
+ if (platform === 'linux') {
802
+ // ripgrep is Linux-only: it's used by linuxGetMandatoryDenyPaths() to
803
+ // expand glob deny-patterns to concrete paths for bwrap. macOS seatbelt
804
+ // profiles take regex patterns directly, so rg is never invoked there.
805
+ const rgToCheck = ripgrepConfig ?? config?.ripgrep ?? { command: 'rg' };
806
+ if (whichSync(rgToCheck.command) === null) {
807
+ errors.push(`ripgrep (${rgToCheck.command}) not found`);
808
+ }
809
+ const linuxDeps = checkLinuxDependencies({
810
+ seccompConfig: config?.seccomp,
811
+ bwrapPath: config?.bwrapPath,
812
+ socatPath: config?.socatPath,
813
+ });
814
+ errors.push(...linuxDeps.errors);
815
+ warnings.push(...linuxDeps.warnings);
816
+ }
817
+ else if (platform === 'windows') {
818
+ let srtWin;
819
+ try {
820
+ srtWin = resolveSrtWin(config?.windows?.srtWin);
821
+ }
822
+ catch (e) {
823
+ errors.push(e.message);
824
+ return { done: { errors, warnings } };
825
+ }
826
+ return {
827
+ windows: {
828
+ sublayerGuid: config?.windows?.sublayerGuid ?? config?.windows?.wfpSublayerGuid,
829
+ srtWin,
830
+ },
831
+ };
832
+ }
833
+ return { done: { errors, warnings } };
834
+ }
835
+ /**
836
+ * Check sandbox dependencies for the current platform
837
+ * @param ripgrepConfig - Ripgrep command to check. If not provided, uses config from initialization or defaults to 'rg'
838
+ * @returns { warnings, errors } - errors mean sandbox cannot run, warnings mean degraded functionality
839
+ */
840
+ function checkDependencies(ripgrepConfig) {
841
+ const common = checkDependenciesCommon(ripgrepConfig);
842
+ if ('done' in common)
843
+ return common.done;
844
+ return checkWindowsDependencies(common.windows);
845
+ }
846
+ /**
847
+ * Async variant of {@link checkDependencies} — same result for the
848
+ * same underlying state. On Windows the srt-win probes run via
849
+ * `spawn` (never blocking the event loop) and concurrently; on other
850
+ * platforms the checks are native and this simply wraps the sync
851
+ * result. Windows callers should prefer this variant.
852
+ */
853
+ async function checkDependenciesAsync(ripgrepConfig) {
854
+ // Linux: resolve apply-seccomp first so its global-npm fallback
855
+ // (`npm root -g`) runs off the event loop; the sync check below then
856
+ // hits the shared path cache.
857
+ if (getPlatform() === 'linux' && !config?.seccomp?.argv0) {
858
+ await getApplySeccompBinaryPathAsync(config?.seccomp?.applyPath);
859
+ }
860
+ const common = checkDependenciesCommon(ripgrepConfig);
861
+ if ('done' in common)
862
+ return common.done;
863
+ return checkWindowsDependenciesAsync(common.windows);
864
+ }
865
+ /**
866
+ * Build the read-deny / env-unset / env-set maps implied by the
867
+ * `credentials` config.
868
+ *
869
+ * Only explicitly declared sources are restricted: `mode: 'deny'` file
870
+ * entries join the read-deny set, `mode: 'deny'` env vars are unset, and
871
+ * `mode: 'mask'` env vars are set to a fake value (whole-value sentinel,
872
+ * the real value with extract-captured spans swapped for sentinels, or a
873
+ * JWT-shaped fake for `decode: 'jwt'` / `maskClaims` entries) registered
874
+ * in {@link sentinelRegistry} — see {@link buildMaskedEnvVars}.
875
+ */
876
+ function getCredentialRestrictions(credentials, allowedDomains) {
877
+ if (!credentials) {
878
+ return {
879
+ denyReadPaths: [],
880
+ unsetEnvVars: [],
881
+ setEnvVars: {},
882
+ maskedFileBinds: [],
883
+ maskedFileStoreDir: undefined,
884
+ degradeToDenyPaths: [],
885
+ };
886
+ }
887
+ const denyReadPaths = getCredentialDenyReadPaths(credentials);
888
+ // Default injectHosts (= allowedDomains) is host-scoped: drop any
889
+ // `:port` suffixes, otherwise the sentinel would carry an entry no bare
890
+ // destination host can ever match and the credential would never inject.
891
+ const defaultInjectHosts = [
892
+ ...new Set((allowedDomains ?? []).map(stripDomainPatternPort)),
893
+ ];
894
+ const unsetEnvVars = [];
895
+ for (const v of credentials.envVars ?? []) {
896
+ if (v.mode === 'deny')
897
+ unsetEnvVars.push(v.name);
898
+ }
899
+ // Masked env vars: read the real value from the host environment,
900
+ // register sentinel(s), and set the variable to the fake value inside
901
+ // the sandbox. degradeToUnsetNames carries variables whose extract
902
+ // pattern matched nothing with onExtractNoMatch: "deny" — merged into
903
+ // unsetEnvVars below so the value is withheld rather than exposed.
904
+ const { setEnvVars, degradeToUnsetNames } = buildMaskedEnvVars(credentials.envVars ?? [], defaultInjectHosts, sentinelRegistry);
905
+ unsetEnvVars.push(...degradeToUnsetNames);
906
+ // Link masked AWS credentials into pairs so the proxy can re-sign
907
+ // SigV4 requests (the signature is derived from the secret; header
908
+ // substitution alone cannot fix it).
909
+ registerAwsPairs(credentials.envVars ?? [], credentials.awsPairs, defaultInjectHosts, setEnvVars, awsPairRegistry);
910
+ // Masked files: read the real bytes on the host, register a sentinel,
911
+ // write it to a fake file in the manager-owned temp dir. Missing/unreadable
912
+ // entries are skipped (same posture as an unset masked env var).
913
+ // degradeToDenyPaths carries paths whose extract pattern matched
914
+ // nothing with onExtractNoMatch: "deny" — merged into denyReadPaths
915
+ // below so both the read-deny config and the platform builders see
916
+ // them, and carried separately so they stay literal on the way there.
917
+ const files = credentials.files ?? [];
918
+ const { binds: maskedFileBinds, degradeToDenyPaths } = buildMaskedFileBinds(files, defaultInjectHosts, sentinelRegistry, maskedFileStore);
919
+ return {
920
+ denyReadPaths: [...new Set([...denyReadPaths, ...degradeToDenyPaths])],
921
+ unsetEnvVars: [...new Set(unsetEnvVars)],
922
+ setEnvVars,
923
+ maskedFileBinds,
924
+ maskedFileStoreDir: maskedFileStore.dirPath,
925
+ degradeToDenyPaths,
926
+ };
927
+ }
928
+ /**
929
+ * Pure (side-effect-free) chokepoint for credential file-deny
930
+ * paths — `credentials.files` entries with `mode: 'deny'`. Any
931
+ * code that needs the credential→denyRead contribution routes
932
+ * through here so a comparison predicate can read it without
933
+ * touching {@link sentinelRegistry}.
934
+ */
935
+ function getCredentialDenyReadPaths(credentials) {
936
+ const files = credentials?.files ?? [];
937
+ return [...new Set(files.filter(f => f.mode === 'deny').map(f => f.path))];
938
+ }
939
+ /**
940
+ * The default write paths under a filesystem policy's read rules, for
941
+ * getFsWriteConfig() and wrapWithSandbox() alike. Fed the entries as
942
+ * configured, through the pure {@link getCredentialDenyReadPaths}: no glob
943
+ * expansion and no credential masking, because getFsWriteConfig() is a
944
+ * getter callers reach from permission checks and render paths. A mask entry
945
+ * that degrades to a deny is a file and cannot cover a directory, so
946
+ * leaving those out changes nothing.
947
+ */
948
+ function defaultWritePathsUnder({ denyRead, allowRead, credentials, }) {
949
+ return getDefaultWritePaths({
950
+ denyRead: [...denyRead, ...getCredentialDenyReadPaths(credentials)],
951
+ allowRead,
952
+ });
953
+ }
954
+ /**
955
+ * Union the explicit `filesystem.denyRead` with credential-derived
956
+ * deny paths. The single source of "what files does this config
957
+ * want read-denied" — all platforms route through here so a new
958
+ * credential kind that contributes deny paths reaches every
959
+ * backend.
960
+ */
961
+ function unionDenyReadPaths(denyRead, credentialRestrictions) {
962
+ return [...new Set([...denyRead, ...credentialRestrictions.denyReadPaths])];
963
+ }
964
+ /**
965
+ * Strip a trailing `/**` from each read-path entry and, on Linux, replace
966
+ * any remaining glob with what `expandGlob` returns for it (bubblewrap takes
967
+ * concrete paths only). Other platforms match globs natively.
968
+ *
969
+ * `literalPaths` are the ones the library resolved itself (a masked
970
+ * credential file that degraded to deny) — each names one file on disk, so
971
+ * it is passed through whatever characters it contains. Expanded as a
972
+ * pattern, a name holding `[` matches nothing and the deny is lost.
973
+ */
974
+ function resolveReadPathEntries(paths, expandGlob, literalPaths = []) {
975
+ const literal = new Set(literalPaths);
976
+ return paths.flatMap(p => {
977
+ const stripped = removeTrailingGlobSuffix(p);
978
+ return getPlatform() === 'linux' &&
979
+ !literal.has(p) &&
980
+ containsGlobChars(stripped)
981
+ ? expandGlob(p)
982
+ : [stripped];
983
+ });
984
+ }
985
+ /**
986
+ * Strip a trailing `/**` and drop what is still a glob on Linux: bwrap needs
987
+ * real paths. macOS subpath matching is recursive, so the strip is harmless
988
+ * there and the filter never fires.
989
+ */
990
+ function stripWriteGlobs(paths) {
991
+ return paths
992
+ .map(p => removeTrailingGlobSuffix(p))
993
+ .filter(p => {
994
+ if (getPlatform() === 'linux' && containsGlobChars(p)) {
995
+ logForDebugging(`[Sandbox] Skipping glob write pattern on Linux: ${p}`);
996
+ return false;
997
+ }
998
+ return true;
999
+ });
1000
+ }
1001
+ function expandAllowReadGlob(pattern) {
1002
+ const expanded = expandGlobPattern(pattern);
1003
+ logForDebugging(`[Sandbox] Expanded allowRead glob pattern "${pattern}" to ${expanded.length} paths on Linux`);
1004
+ return expanded;
1005
+ }
1006
+ /**
1007
+ * The read policy of the initialized config, for inspection and display.
1008
+ * On Linux, denyRead globs are collapsed to covering directory mounts against
1009
+ * this config's allowRead and {@link getFsWriteConfig}'s allowOnly, so
1010
+ * `denyOnly` is only sound alongside that write config and must not be handed
1011
+ * to wrapCommandWithSandboxLinux with a different one.
1012
+ */
1013
+ function getFsReadConfig() {
1014
+ if (!config || config.filesystem.disabled) {
1015
+ return { denyOnly: [], allowWithinDeny: [] };
1016
+ }
1017
+ // Credential deny paths are unioned with the caller's denyRead — never
1018
+ // replacing it — so explicit filesystem restrictions always survive.
1019
+ const credentialRestrictions = getCredentialRestrictions(config.credentials, config.network.allowedDomains);
1020
+ // allowRead (re-allow within denied regions) is resolved first: the
1021
+ // denyRead glob expansion collapses against it.
1022
+ const allowPaths = resolveReadPathEntries(config.filesystem.allowRead ?? [], expandAllowReadGlob);
1023
+ const reExposedPaths = [...allowPaths, ...getFsWriteConfig().allowOnly];
1024
+ const unlistableDenyDirs = new Set();
1025
+ const denyPaths = resolveReadPathEntries(unionDenyReadPaths(config.filesystem.denyRead, credentialRestrictions), pattern => expandReadDenyGlobLinux(pattern, reExposedPaths, unlistableDenyDirs), credentialRestrictions.degradeToDenyPaths);
1026
+ return {
1027
+ denyOnly: denyPaths,
1028
+ allowWithinDeny: allowPaths,
1029
+ unlistableDenyDirs: [...unlistableDenyDirs],
1030
+ };
1031
+ }
1032
+ function getFsWriteConfig() {
1033
+ if (!config) {
1034
+ return { allowOnly: getDefaultWritePaths(), denyWithinAllow: [] };
1035
+ }
1036
+ if (config.filesystem.disabled) {
1037
+ return { allowOnly: ['/'], denyWithinAllow: [] };
1038
+ }
1039
+ const allowPaths = stripWriteGlobs(config.filesystem.allowWrite);
1040
+ const denyPaths = stripWriteGlobs(config.filesystem.denyWrite);
1041
+ const allowOnly = [
1042
+ ...defaultWritePathsUnder({
1043
+ denyRead: config.filesystem.denyRead,
1044
+ allowRead: config.filesystem.allowRead,
1045
+ credentials: config.credentials,
1046
+ }),
1047
+ ...allowPaths,
1048
+ ];
1049
+ return {
1050
+ allowOnly,
1051
+ denyWithinAllow: denyPaths,
1052
+ };
1053
+ }
1054
+ /**
1055
+ * Build the Windows file-access set (deny stamps + sandbox-user
1056
+ * grants) from `runtimeConfig`. Globs are expanded to concrete
1057
+ * paths (point-in-time — a path appearing after this returns is NOT
1058
+ * covered). Directory targets are accepted (the `(OI)(CI)` ACEs
1059
+ * cover the subtree).
1060
+ *
1061
+ * The sandbox user has no inherent rights on real-user-owned files,
1062
+ * so `allowWrite` (the working-tree roots) becomes a per-session
1063
+ * `MODIFY_NO_FDC` ALLOW ACE for `<sb-SID>`, `allowRead` a
1064
+ * `READ|EXECUTE` ALLOW ACE, and `denyRead`/`denyWrite` become an
1065
+ * explicit DENY ACE for `<sb-SID>` on the target plus a
1066
+ * `(OI)(CI) FILE_DELETE_CHILD` DENY on its parent.
1067
+ */
1068
+ function computeWindowsFsAccessSet(c) {
1069
+ const fs = c.filesystem;
1070
+ // filesystem.disabled bypasses ALL filesystem rule generation —
1071
+ // same as the macOS/Linux wrapWithSandbox path (readConfig /
1072
+ // writeConfig left undefined). On Windows this means no ACL
1073
+ // stamp/grant; credential FILE denies are dropped along with the
1074
+ // rest (credential ENV: mode:'deny' is structural under the
1075
+ // fresh srt-sandbox env; mode:'mask' sentinels are passed via
1076
+ // the --env overlay).
1077
+ if (fs?.disabled) {
1078
+ return { grantRead: [], grantWrite: [], denyRead: [], denyWrite: [] };
1079
+ }
1080
+ const expand = expandWindowsFsPaths;
1081
+ // `mode: 'deny'` — non-existent literals reach srt-win, which
1082
+ // creates a placeholder chain and stamps it (deny lands on the
1083
+ // exact target path). `mode: 'grant'` drops them (a grant on
1084
+ // nothing is meaningless).
1085
+ const denyRead = expand([
1086
+ ...new Set([
1087
+ ...(fs?.denyRead ?? []),
1088
+ ...getCredentialDenyReadPaths(c.credentials),
1089
+ ]),
1090
+ ], { mode: 'deny' });
1091
+ const denyWrite = expand(fs?.denyWrite ?? [], { mode: 'deny' });
1092
+ return {
1093
+ // `allowRead` also serves as `allowWithinDeny`: a file under a
1094
+ // denied dir gets an explicit ALLOW ACE for the sandbox user,
1095
+ // and explicit DENY on the parent doesn't override it because
1096
+ // the recompose chokepoint orders deny-before-allow per-path.
1097
+ grantRead: expand(fs?.allowRead ?? [], { mode: 'grant' }),
1098
+ grantWrite: expand(fs?.allowWrite ?? [], { mode: 'grant' }),
1099
+ denyRead,
1100
+ denyWrite,
1101
+ };
1102
+ }
1103
+ /**
1104
+ * Snapshot the raw config fields that feed
1105
+ * {@link computeWindowsFsAccessSet}. Used by updateConfig() to
1106
+ * short-circuit the resolved-set diff (which re-runs glob
1107
+ * expansion) when nothing relevant changed.
1108
+ */
1109
+ function rawWindowsFsInputs(c) {
1110
+ // Keyed exactly on what {@link computeWindowsFsAccessSet} reads.
1111
+ // `network.allowedDomains` does NOT feed file-deny (only mask
1112
+ // injectHosts), so a network-only updateConfig hits the cache.
1113
+ return {
1114
+ disabled: c.filesystem.disabled ?? false,
1115
+ denyRead: [...c.filesystem.denyRead],
1116
+ denyWrite: [...c.filesystem.denyWrite],
1117
+ allowRead: [...(c.filesystem.allowRead ?? [])],
1118
+ allowWrite: [...c.filesystem.allowWrite],
1119
+ credFiles: getCredentialDenyReadPaths(c.credentials),
1120
+ };
1121
+ }
1122
+ function setEq(a, b) {
1123
+ if (a.length !== b.length)
1124
+ return false;
1125
+ const s = new Set(a);
1126
+ return b.every(x => s.has(x));
1127
+ }
1128
+ function sameRawWindowsFsInputs(a, b) {
1129
+ return (a.disabled === b.disabled &&
1130
+ setEq(a.denyRead, b.denyRead) &&
1131
+ setEq(a.denyWrite, b.denyWrite) &&
1132
+ setEq(a.allowRead, b.allowRead) &&
1133
+ setEq(a.allowWrite, b.allowWrite) &&
1134
+ setEq(a.credFiles, b.credFiles));
1135
+ }
1136
+ /**
1137
+ * True when `newConfig`'s file-deny inputs match what was
1138
+ * stamped at initialize(). Compares raw inputs only (cheap,
1139
+ * order-insensitive); never re-expands globs — updateConfig is
1140
+ * warn-only on Windows and the resolved set wouldn't be used.
1141
+ */
1142
+ function sameWindowsStampSet(newConfig) {
1143
+ return (windowsFsRawInputs !== undefined &&
1144
+ sameRawWindowsFsInputs(windowsFsRawInputs, rawWindowsFsInputs(newConfig)));
1145
+ }
1146
+ function getNetworkRestrictionConfig() {
1147
+ if (!config) {
1148
+ return {};
1149
+ }
1150
+ // Preserve an explicitly-empty allowlist: consumers need to distinguish
1151
+ // "no network restriction configured" (absent) from "allowlist configured
1152
+ // with zero entries" (block-all / ask-only). Stripping the empty array
1153
+ // made a host app's restriction-status UI report an airgapped config as
1154
+ // unrestricted. deniedHosts keeps the strip — an empty denylist and an
1155
+ // absent one are semantically identical.
1156
+ const allowedHosts = config.network.allowedDomains;
1157
+ const deniedHosts = config.network.deniedDomains;
1158
+ return {
1159
+ allowedHosts,
1160
+ ...(deniedHosts.length > 0 && { deniedHosts }),
1161
+ };
1162
+ }
1163
+ function getAllowUnixSockets() {
1164
+ return config?.network?.allowUnixSockets;
1165
+ }
1166
+ function getAllowAllUnixSockets() {
1167
+ return config?.network?.allowAllUnixSockets;
1168
+ }
1169
+ function getAllowLocalBinding() {
1170
+ return config?.network?.allowLocalBinding;
1171
+ }
1172
+ function getAllowMachLookup() {
1173
+ return config?.network?.allowMachLookup;
1174
+ }
1175
+ function getIgnoreViolations() {
1176
+ return config?.ignoreViolations;
1177
+ }
1178
+ function getEnableWeakerNestedSandbox() {
1179
+ return config?.enableWeakerNestedSandbox;
1180
+ }
1181
+ function getEnableWeakerNetworkIsolation() {
1182
+ return config?.enableWeakerNetworkIsolation;
1183
+ }
1184
+ function getAllowAppleEvents() {
1185
+ return config?.allowAppleEvents;
1186
+ }
1187
+ function getRipgrepConfig() {
1188
+ return config?.ripgrep ?? { command: 'rg' };
1189
+ }
1190
+ function getMandatoryDenySearchDepth() {
1191
+ return config?.mandatoryDenySearchDepth ?? 3;
1192
+ }
1193
+ function getAllowGitConfig() {
1194
+ return config?.filesystem?.allowGitConfig ?? false;
1195
+ }
1196
+ /**
1197
+ * Union of session-level and per-call `git.safeDirectories`. Marks
1198
+ * paths as `safe.directory` (dubious-ownership bypass) WITHOUT
1199
+ * touching the write grant — the repo top-level for a subdirectory
1200
+ * launch must NOT go in `filesystem.allowWrite`.
1201
+ */
1202
+ function getGitSafeDirectories(customConfig) {
1203
+ return [
1204
+ ...(config?.git?.safeDirectories ?? []),
1205
+ ...(customConfig?.git?.safeDirectories ?? []),
1206
+ ];
1207
+ }
1208
+ function getSeccompConfig() {
1209
+ return config?.seccomp;
1210
+ }
1211
+ function getProxyAuthToken() {
1212
+ return proxyAuthToken;
1213
+ }
1214
+ function getProxyPort() {
1215
+ return managerContext?.httpProxyPort;
1216
+ }
1217
+ function getSocksProxyPort() {
1218
+ return managerContext?.socksProxyPort;
1219
+ }
1220
+ function getLinuxHttpSocketPath() {
1221
+ return managerContext?.linuxBridge?.httpSocketPath;
1222
+ }
1223
+ function getLinuxSocksSocketPath() {
1224
+ return managerContext?.linuxBridge?.socksSocketPath;
1225
+ }
1226
+ /**
1227
+ * Wait for network initialization to complete if already in progress
1228
+ * Returns true if initialized successfully, false otherwise
1229
+ */
1230
+ async function waitForNetworkInitialization() {
1231
+ if (!config) {
1232
+ return false;
1233
+ }
1234
+ if (initializationPromise) {
1235
+ try {
1236
+ await initializationPromise;
1237
+ return true;
1238
+ }
1239
+ catch {
1240
+ return false;
1241
+ }
1242
+ }
1243
+ return managerContext !== undefined;
1244
+ }
1245
+ async function wrapWithSandbox(command, binShell, customConfig, abortSignal, options) {
1246
+ const platform = getPlatform();
1247
+ const commandId = options?.commandId;
1248
+ registerCommandText(command, options);
1249
+ // filesystem.disabled bypasses ALL filesystem rule generation. Both
1250
+ // platform wrappers treat readConfig/writeConfig === undefined as "no
1251
+ // filesystem restrictions" (seatbelt emits `(allow file-write*)`; bwrap
1252
+ // skips the `--ro-bind / /` root and all path binds).
1253
+ //
1254
+ // Precedence: when a caller passes a per-call filesystem override at all,
1255
+ // its `disabled` (defaulting to false) wins outright. A global
1256
+ // disabled=true must not silently discard a per-call tightening that
1257
+ // omits the new key.
1258
+ const fsDisabled = customConfig?.filesystem !== undefined
1259
+ ? (customConfig.filesystem.disabled ?? false)
1260
+ : (config?.filesystem.disabled ?? false);
1261
+ // Credential env handling is independent of filesystem policy: unsetEnvVars /
1262
+ // setEnvVars must be applied even when fsDisabled (the credential file
1263
+ // deny-reads are dropped, but env scrubbing still happens).
1264
+ const credentialRestrictions = getCredentialRestrictions(customConfig?.credentials ?? config?.credentials, customConfig?.network?.allowedDomains ?? config?.network?.allowedDomains);
1265
+ // Get configs - use custom if provided, otherwise fall back to main config
1266
+ // If neither exists, defaults to empty arrays (most restrictive)
1267
+ // Always include default system write paths (like /dev/null, /tmp/claude)
1268
+ let writeConfig;
1269
+ let readConfig;
1270
+ if (!fsDisabled) {
1271
+ const userAllowWrite = stripWriteGlobs(customConfig?.filesystem?.allowWrite ??
1272
+ config?.filesystem.allowWrite ??
1273
+ []);
1274
+ writeConfig = {
1275
+ allowOnly: [
1276
+ ...defaultWritePathsUnder({
1277
+ denyRead: customConfig?.filesystem?.denyRead ??
1278
+ config?.filesystem.denyRead ??
1279
+ [],
1280
+ allowRead: customConfig?.filesystem?.allowRead ?? config?.filesystem.allowRead,
1281
+ credentials: customConfig?.credentials ?? config?.credentials,
1282
+ }),
1283
+ ...userAllowWrite,
1284
+ ],
1285
+ denyWithinAllow: stripWriteGlobs(customConfig?.filesystem?.denyWrite ??
1286
+ config?.filesystem.denyWrite ??
1287
+ []),
1288
+ };
1289
+ // Credential deny paths are unioned with the caller's denyRead — never
1290
+ // replacing it — so explicit filesystem restrictions always survive.
1291
+ // allowRead is resolved first: on Linux a denyRead glob's expansion is
1292
+ // collapsed against the paths that re-expose contents under a denied
1293
+ // directory (allowRead + allowWrite), so both must be final here.
1294
+ const expandedAllowRead = resolveReadPathEntries(customConfig?.filesystem?.allowRead ?? config?.filesystem.allowRead ?? [], expandAllowReadGlob);
1295
+ // The TLS-termination CA cert and the trust bundle the env vars point at
1296
+ // (NODE_EXTRA_CA_CERTS etc.) must be readable by the child, even if their
1297
+ // paths fall under a user-configured denyRead.
1298
+ if (mitmCA) {
1299
+ expandedAllowRead.push(mitmCA.certPath, mitmCA.trustBundlePath);
1300
+ }
1301
+ // Likewise the JVM proxy agent jar JAVA_TOOL_OPTIONS points at.
1302
+ if (javaAgentJarPath) {
1303
+ expandedAllowRead.push(javaAgentJarPath);
1304
+ }
1305
+ const reExposedPaths = [...expandedAllowRead, ...writeConfig.allowOnly];
1306
+ const unlistableDenyDirs = new Set();
1307
+ const expandedDenyRead = resolveReadPathEntries(unionDenyReadPaths(customConfig?.filesystem?.denyRead ?? config?.filesystem.denyRead ?? [], credentialRestrictions), pattern => expandReadDenyGlobLinux(pattern, reExposedPaths, unlistableDenyDirs), credentialRestrictions.degradeToDenyPaths);
1308
+ readConfig = {
1309
+ denyOnly: expandedDenyRead,
1310
+ allowWithinDeny: expandedAllowRead,
1311
+ unlistableDenyDirs: [...unlistableDenyDirs],
1312
+ };
1313
+ }
1314
+ // Check if network config is specified - this determines if we need network restrictions
1315
+ // Network restriction is needed when:
1316
+ // 1. customConfig has network.allowedDomains defined (even if empty array = block all)
1317
+ // 2. OR config has network.allowedDomains defined (even if empty array = block all)
1318
+ // An empty allowedDomains array means "no domains allowed" = block all network access
1319
+ const hasNetworkConfig = customConfig?.network?.allowedDomains !== undefined ||
1320
+ config?.network?.allowedDomains !== undefined;
1321
+ // Network RESTRICTION is needed whenever network config is specified
1322
+ // This includes empty allowedDomains which means "block all network"
1323
+ const needsNetworkRestriction = hasNetworkConfig;
1324
+ // Network PROXY is needed whenever network config is specified
1325
+ // Even with empty allowedDomains, we route through proxy so that:
1326
+ // 1. updateConfig() can enable network access for already-running processes
1327
+ // 2. The proxy blocks all requests when allowlist is empty
1328
+ const needsNetworkProxy = hasNetworkConfig;
1329
+ // Wait for network initialization only if proxy is actually needed
1330
+ if (needsNetworkProxy) {
1331
+ await waitForNetworkInitialization();
1332
+ }
1333
+ // Check custom config to allow pseudo-terminal (can be applied dynamically)
1334
+ const allowPty = customConfig?.allowPty ?? config?.allowPty;
1335
+ const gitSafeDirectories = getGitSafeDirectories(customConfig);
1336
+ switch (platform) {
1337
+ case 'macos':
1338
+ // macOS sandbox profile supports glob patterns directly, no ripgrep needed
1339
+ return wrapCommandWithSandboxMacOS({
1340
+ command,
1341
+ commandId,
1342
+ needsNetworkRestriction,
1343
+ // Only pass proxy ports if proxy is running (when there are domains to filter)
1344
+ httpProxyPort: needsNetworkProxy ? getProxyPort() : undefined,
1345
+ socksProxyPort: needsNetworkProxy ? getSocksProxyPort() : undefined,
1346
+ proxyAuthToken: needsNetworkProxy ? proxyAuthToken : undefined,
1347
+ caCertPath: mitmCA?.trustBundlePath,
1348
+ javaAgentJarPath: needsNetworkProxy ? javaAgentJarPath : undefined,
1349
+ readConfig,
1350
+ writeConfig,
1351
+ unsetEnvVars: credentialRestrictions.unsetEnvVars,
1352
+ setEnvVars: credentialRestrictions.setEnvVars,
1353
+ maskedFileBinds: credentialRestrictions.maskedFileBinds,
1354
+ degradeToDenyPaths: credentialRestrictions.degradeToDenyPaths,
1355
+ allowUnixSockets: getAllowUnixSockets(),
1356
+ allowAllUnixSockets: getAllowAllUnixSockets(),
1357
+ allowLocalBinding: getAllowLocalBinding(),
1358
+ allowMachLookup: getAllowMachLookup(),
1359
+ ignoreViolations: getIgnoreViolations(),
1360
+ allowPty,
1361
+ allowGitConfig: getAllowGitConfig(),
1362
+ gitSafeDirectories,
1363
+ enableWeakerNetworkIsolation: getEnableWeakerNetworkIsolation(),
1364
+ allowAppleEvents: getAllowAppleEvents(),
1365
+ binShell,
1366
+ });
1367
+ case 'linux':
1368
+ return wrapCommandWithSandboxLinux({
1369
+ command,
1370
+ commandId,
1371
+ needsNetworkRestriction,
1372
+ // Only pass socket paths if proxy is running (when there are domains to filter)
1373
+ httpSocketPath: needsNetworkProxy
1374
+ ? getLinuxHttpSocketPath()
1375
+ : undefined,
1376
+ socksSocketPath: needsNetworkProxy
1377
+ ? getLinuxSocksSocketPath()
1378
+ : undefined,
1379
+ httpProxyPort: needsNetworkProxy
1380
+ ? managerContext?.httpProxyPort
1381
+ : undefined,
1382
+ socksProxyPort: needsNetworkProxy
1383
+ ? managerContext?.socksProxyPort
1384
+ : undefined,
1385
+ proxyAuthToken: needsNetworkProxy ? proxyAuthToken : undefined,
1386
+ caCertPath: mitmCA?.trustBundlePath,
1387
+ javaAgentJarPath: needsNetworkProxy ? javaAgentJarPath : undefined,
1388
+ readConfig,
1389
+ writeConfig,
1390
+ unsetEnvVars: credentialRestrictions.unsetEnvVars,
1391
+ setEnvVars: credentialRestrictions.setEnvVars,
1392
+ maskedFileBinds: credentialRestrictions.maskedFileBinds,
1393
+ maskedFileStoreDir: credentialRestrictions.maskedFileStoreDir,
1394
+ enableWeakerNestedSandbox: getEnableWeakerNestedSandbox(),
1395
+ allowAllUnixSockets: getAllowAllUnixSockets(),
1396
+ binShell,
1397
+ ripgrepConfig: getRipgrepConfig(),
1398
+ mandatoryDenySearchDepth: getMandatoryDenySearchDepth(),
1399
+ allowGitConfig: getAllowGitConfig(),
1400
+ gitSafeDirectories,
1401
+ seccompConfig: getSeccompConfig(),
1402
+ bwrapPath: config?.bwrapPath,
1403
+ socatPath: config?.socatPath,
1404
+ observeSocketPath: linuxMonitor?.observeSocketPath,
1405
+ abortSignal,
1406
+ });
1407
+ case 'windows':
1408
+ // Windows wraps to an argv array, not a shell string. Forcing
1409
+ // callers through wrapWithSandboxArgv() means they spawn with
1410
+ // {shell:false}, which is the security boundary that keeps the
1411
+ // user's command bytes off the HOST shell.
1412
+ throw new Error('wrapWithSandbox() returns a shell string and is not supported ' +
1413
+ 'on Windows. Use SandboxManager.wrapWithSandboxArgv() and ' +
1414
+ 'spawn the result with {shell: false}.');
1415
+ default:
1416
+ // Unsupported platform - this should not happen since isSandboxingEnabled() checks platform support
1417
+ throw new Error(`Sandbox configuration is not supported on platform: ${platform}`);
1418
+ }
1419
+ }
1420
+ /**
1421
+ * Wrap `command` for the sandbox and return a spawn descriptor:
1422
+ * `{ argv, env }`, suitable for
1423
+ * `spawn(argv[0], argv.slice(1), {shell: false, env})`.
1424
+ *
1425
+ * On Windows this is the ONLY supported wrap method (see
1426
+ * {@link wrapWithSandbox}); `env` is the broker process's spawn env
1427
+ * — the sandboxed child gets a fresh `srt-sandbox` profile env with
1428
+ * only the `--env` overlay baked into `argv` (see
1429
+ * {@link wrapCommandWithSandboxWindows}). On
1430
+ * macOS/Linux `argv` is `[binShell, '-c', <wrapWithSandbox result>]`
1431
+ * (proxy env is baked into that command) and `env` is the unchanged
1432
+ * `process.env`, so callers can spawn uniformly across platforms.
1433
+ *
1434
+ * @param cwd the working directory the caller will spawn the result
1435
+ * with. On Windows the child's cwd is whatever the caller passes
1436
+ * as the spawn `{cwd:}` option (there is no `--cwd` flag), and
1437
+ * the `safe.directory` git-config injection derives from this — so
1438
+ * pass the same value here as to `spawn({cwd})`. Defaults to
1439
+ * `process.cwd()`. Currently unused on macOS/Linux.
1440
+ */
1441
+ async function wrapWithSandboxArgv(command, binShell, customConfig, abortSignal, cwd, options) {
1442
+ const platform = getPlatform();
1443
+ if (platform === 'windows') {
1444
+ const hasNetworkConfig = customConfig?.network?.allowedDomains !== undefined ||
1445
+ config?.network?.allowedDomains !== undefined;
1446
+ if (hasNetworkConfig) {
1447
+ await waitForNetworkInitialization();
1448
+ }
1449
+ const credentialRestrictions = getCredentialRestrictions(customConfig?.credentials ?? config?.credentials, customConfig?.network?.allowedDomains ?? config?.network?.allowedDomains);
1450
+ // Per-exec FILE denies (customConfig only — the session-level
1451
+ // config's denies were already stamped at initialize()).
1452
+ // Paths go through `expandWindowsFsPaths` — the SAME
1453
+ // chokepoint the session-level set uses (point-in-time glob
1454
+ // expand, normalize, missing→drop) — so a per-exec entry
1455
+ // resolves identically to its session-level equivalent.
1456
+ // macOS/Linux per-exec already reuses session-level expansion;
1457
+ // Windows now matches.
1458
+ //
1459
+ // The dedup against `windowsFsStampedSet` is an OPTIMIZATION,
1460
+ // not a correctness gate: re-stamping a session-held path
1461
+ // under the exec's distinct holder is refcount-safe but wastes
1462
+ // a SetSecurityInfo round-trip.
1463
+ //
1464
+ // filesystem.disabled bypasses ALL filesystem rule generation
1465
+ // — including credential-derived file denies — same ordering
1466
+ // as session-level `computeWindowsFsAccessSet` (credential
1467
+ // ENV: mode:'deny' is structural under the fresh srt-sandbox
1468
+ // env; mode:'mask' sentinels are passed via the --env
1469
+ // overlay).
1470
+ // Per-exec allowRead/allowWrite throw — `srt-win exec` only
1471
+ // exposes `--deny-*`; per-exec grants are not implemented.
1472
+ const fsCfg = customConfig?.filesystem;
1473
+ let perExecDenyRead = [];
1474
+ let perExecDenyWrite = [];
1475
+ if (!fsCfg?.disabled) {
1476
+ if (fsCfg?.allowRead?.length || fsCfg?.allowWrite?.length) {
1477
+ throw new Error(`Per-exec filesystem.allowRead/allowWrite is not supported ` +
1478
+ `on Windows — \`srt-win exec\` only exposes per-exec ` +
1479
+ `denies. Set them at the session level (initialize()).`);
1480
+ }
1481
+ const rawRead = [
1482
+ ...(fsCfg?.denyRead ?? []),
1483
+ ...getCredentialDenyReadPaths(customConfig?.credentials),
1484
+ ];
1485
+ const rawWrite = fsCfg?.denyWrite ?? [];
1486
+ // Skip on the dominant path (no per-exec fs or
1487
+ // credential-file deny).
1488
+ if (rawRead.length > 0 || rawWrite.length > 0) {
1489
+ const sessRead = new Set(windowsFsStampedSet?.denyRead ?? []);
1490
+ const sessWrite = new Set(windowsFsStampedSet?.denyWrite ?? []);
1491
+ const expand = expandWindowsFsPaths;
1492
+ perExecDenyRead = expand(rawRead, { mode: 'deny' }).filter(p => !sessRead.has(p));
1493
+ perExecDenyWrite = expand(rawWrite, { mode: 'deny' }).filter(p => !sessRead.has(p) && !sessWrite.has(p));
1494
+ }
1495
+ }
1496
+ // Per-exec deny rides on argv (`acl stamp` reads stdin, but
1497
+ // exec's stdin belongs to the child). The CreateProcessW
1498
+ // length check lives in `wrapCommandWithSandboxWindows`
1499
+ // where the full argv (incl. shell + user command) is known.
1500
+ //
1501
+ // The `denyReadPaths` half of the SESSION-level credentials
1502
+ // is already unioned into the stamp set at initialize() time
1503
+ // via `computeWindowsFsAccessSet`.
1504
+ registerCommandText(command, options);
1505
+ return wrapCommandWithSandboxWindows({
1506
+ command,
1507
+ commandId: options?.commandId,
1508
+ httpProxyPort: hasNetworkConfig ? getProxyPort() : undefined,
1509
+ socksProxyPort: hasNetworkConfig ? getSocksProxyPort() : undefined,
1510
+ proxyAuthToken: hasNetworkConfig ? proxyAuthToken : undefined,
1511
+ // mode:'deny' env vars are structurally absent (fresh
1512
+ // srt-sandbox profile env). mode:'mask' sentinels are
1513
+ // passed via the --env overlay so the sandboxed child sees
1514
+ // the sentinel value, same as macOS/Linux.
1515
+ setEnvVars: credentialRestrictions.setEnvVars,
1516
+ denyRead: perExecDenyRead,
1517
+ denyWrite: perExecDenyWrite,
1518
+ // safe.directory: cwd + the resolved session-level write
1519
+ // grants + explicit git.safeDirectories — the working-tree
1520
+ // roots the sandbox user has MODIFY on plus any repo top-level
1521
+ // the caller marks as safe without granting write.
1522
+ cwd,
1523
+ allowWrite: windowsFsStampedSet?.grantWrite,
1524
+ gitSafeDirectories: getGitSafeDirectories(customConfig),
1525
+ caCertPath: mitmCA?.trustBundlePath,
1526
+ binShell: parseWindowsBinShell(binShell),
1527
+ srtWin: customConfig?.windows?.srtWin
1528
+ ? resolveSrtWin(customConfig.windows.srtWin)
1529
+ : (srtWinSpawn ?? resolveSrtWin(config?.windows?.srtWin)),
1530
+ });
1531
+ }
1532
+ // macOS/Linux: delegate to the existing string wrapper, then put
1533
+ // the result behind `<shell> -c` so the caller's argv-spawn works.
1534
+ if (typeof binShell === 'object') {
1535
+ throw new Error('binShell object form is Windows-only; pass a shell path string ' +
1536
+ 'on macOS/Linux');
1537
+ }
1538
+ const wrapped = await wrapWithSandbox(command, binShell, customConfig, abortSignal, options);
1539
+ const shell = binShell ?? '/bin/bash';
1540
+ return { argv: [shell, '-c', wrapped], env: process.env };
1541
+ }
1542
+ /**
1543
+ * Get the current sandbox configuration
1544
+ * @returns The current configuration, or undefined if not initialized
1545
+ */
1546
+ function getConfig() {
1547
+ return config;
1548
+ }
1549
+ /**
1550
+ * Update the sandbox configuration in place.
1551
+ *
1552
+ * **Network/allowlist changes are a live swap**: the running
1553
+ * mux proxy reads `config.network.allowedDomains` /
1554
+ * `deniedDomains` per-request (via `filterNetworkRequest`), so
1555
+ * reassigning `config` here takes effect on the next connection
1556
+ * with no proxy rebind and no port change — on every platform,
1557
+ * including Windows. This is what lets a host enable/deny domains
1558
+ * for already-running sandboxed children.
1559
+ *
1560
+ * Filesystem changes (denyRead/denyWrite) are NOT applied live:
1561
+ * macOS bakes them into the seatbelt profile at wrap time, and
1562
+ * Linux/Windows bake them into the bwrap argv / DENY-ACE set at
1563
+ * wrap time. Call reset() + initialize() to apply a new
1564
+ * filesystem config.
1565
+ *
1566
+ * @param newConfig - The new configuration to use
1567
+ */
1568
+ function updateConfig(newConfig) {
1569
+ if (getPlatform() === 'windows' &&
1570
+ config &&
1571
+ !sameWindowsStampSet(newConfig)) {
1572
+ logForDebugging(`[Sandbox Windows] updateConfig: the resolved file-access set ` +
1573
+ `(filesystem.* ∪ credentials.files) changed but the ACL ` +
1574
+ `stamp/grant is session-wide — call reset() then initialize() ` +
1575
+ `to apply. The previously-applied set stays in effect.`, { level: 'warn' });
1576
+ }
1577
+ // Built before anything is swapped, so a malformed range leaves the
1578
+ // previous config fully in effect.
1579
+ const nextGuard = createResolvedAddressGuard(newConfig.network);
1580
+ // Deep clone the config to avoid mutations. structuredClone cannot clone
1581
+ // functions, so pull filterRequest out, clone the rest, and put it back —
1582
+ // a function reference is immutable in the sense that matters here.
1583
+ const { filterRequest, ...rest } = newConfig.network;
1584
+ config = structuredClone({ ...newConfig, network: rest });
1585
+ config.network.filterRequest = filterRequest;
1586
+ resolvedAddressGuard = nextGuard;
1587
+ // Re-resolve parent proxy so hot-reload picks up changes. Note: the proxy
1588
+ // servers capture `parentProxy` by value at creation, so changes here take
1589
+ // effect only on re-initialize. This keeps the state consistent for the
1590
+ // next initialize() call.
1591
+ parentProxy = resolveParentProxy(newConfig.network.parentProxy);
1592
+ logForDebugging('Sandbox configuration updated');
1593
+ }
1594
+ /**
1595
+ * Lightweight cleanup to call after each sandboxed command completes.
1596
+ *
1597
+ * On Linux, bwrap creates empty files on the host filesystem as mount points
1598
+ * when protecting non-existent deny paths (e.g. ~/.bashrc, ~/.gitconfig).
1599
+ * These persist after bwrap exits. This function removes them.
1600
+ *
1601
+ * Safe to call on any platform — it's a no-op on macOS.
1602
+ * Also called automatically by reset() and on process exit as safety nets.
1603
+ */
1604
+ function cleanupAfterCommand() {
1605
+ cleanupBwrapMountPoints();
1606
+ }
1607
+ /**
1608
+ * How long to wait for a bridge process to exit after SIGTERM before
1609
+ * escalating to SIGKILL.
1610
+ *
1611
+ * socat exits within ~10ms of SIGTERM; this is purely a safety margin.
1612
+ * Keep it well below bun's default 5s test/hook timeout: when a bridge's
1613
+ * `'exit'` event is missed entirely (a Linux-only Bun pidfd notification
1614
+ * bug, oven-sh/bun#30301), this timer is the only thing that lets `reset()`
1615
+ * make progress, and a 5000ms value here loses the race against the hook
1616
+ * timer by a couple of milliseconds — that race was the dominant CI flake.
1617
+ */
1618
+ const BRIDGE_EXIT_TIMEOUT_MS = 1500;
1619
+ /**
1620
+ * SIGTERM a bridge process and resolve once it has exited.
1621
+ *
1622
+ * Returns immediately if the process has already exited (`.exitCode` /
1623
+ * `.signalCode` set) — registering `.once('exit')` after the event has
1624
+ * already been emitted produces a listener that never fires.
1625
+ *
1626
+ * Falls back to SIGKILL after {@link BRIDGE_EXIT_TIMEOUT_MS}.
1627
+ */
1628
+ function killBridgeProcess(proc, label) {
1629
+ // Already exited → 'exit' already emitted → a fresh once('exit') would
1630
+ // never fire. Don't wait on it.
1631
+ if (!proc.pid || proc.exitCode !== null || proc.signalCode !== null) {
1632
+ return Promise.resolve();
1633
+ }
1634
+ try {
1635
+ process.kill(proc.pid, 'SIGTERM');
1636
+ logForDebugging(`Sent SIGTERM to ${label} bridge process`);
1637
+ }
1638
+ catch (err) {
1639
+ if (err.code !== 'ESRCH') {
1640
+ logForDebugging(`Error killing ${label} bridge: ${err}`, {
1641
+ level: 'error',
1642
+ });
1643
+ }
1644
+ // ESRCH = process already gone; nothing to wait for either way.
1645
+ return Promise.resolve();
1646
+ }
1647
+ return new Promise(resolve => {
1648
+ let settled = false;
1649
+ const done = () => {
1650
+ if (settled)
1651
+ return;
1652
+ settled = true;
1653
+ clearTimeout(timer);
1654
+ resolve();
1655
+ };
1656
+ proc.once('exit', () => {
1657
+ logForDebugging(`${label} bridge process exited`);
1658
+ done();
1659
+ });
1660
+ const timer = setTimeout(() => {
1661
+ // Re-check liveness — the 'exit' may have raced us.
1662
+ if (proc.exitCode === null && proc.signalCode === null) {
1663
+ logForDebugging(`${label} bridge did not exit, forcing SIGKILL`, {
1664
+ level: 'warn',
1665
+ });
1666
+ try {
1667
+ if (proc.pid)
1668
+ process.kill(proc.pid, 'SIGKILL');
1669
+ }
1670
+ catch {
1671
+ // Process may have already exited
1672
+ }
1673
+ }
1674
+ done();
1675
+ }, BRIDGE_EXIT_TIMEOUT_MS);
1676
+ // The bridge process is being torn down; this timer must not be the
1677
+ // only thing keeping the event loop alive.
1678
+ timer.unref?.();
1679
+ });
1680
+ }
1681
+ /**
1682
+ * Forcibly close an http.Server, including any in-flight requests.
1683
+ *
1684
+ * Plain `server.close()` waits for every active request to finish.
1685
+ * The proxy may be mid-upstream-request when reset() runs (e.g. a test's
1686
+ * curl was killed by --max-time while the proxy was still dialing the
1687
+ * real example.com / api.github.com), and `dialDirect()` allows up to
1688
+ * 30s before giving up. Combined with a socat fork that hasn't yet seen
1689
+ * its unix-socket EOF, that leaves a fully-open inbound connection and
1690
+ * `server.close()` never calls back. `closeAllConnections()` (Node 18.2+,
1691
+ * also implemented in Bun) tears down those sockets so `close()` resolves
1692
+ * immediately.
1693
+ */
1694
+ function forceCloseHttpServer(server) {
1695
+ return new Promise(resolve => {
1696
+ // Must run *before* close(): in Bun, close() also detaches the
1697
+ // underlying handle, so a closeAllConnections() called afterwards
1698
+ // becomes a no-op and the close callback waits for the in-flight
1699
+ // request to drain — defeating the purpose. With closeAllConnections()
1700
+ // first, the connections are gone by the time close() runs and its
1701
+ // callback fires immediately (Bun reports "Server is not running.",
1702
+ // Node reports no error). Verified against both orderings.
1703
+ if (typeof server.closeAllConnections === 'function') {
1704
+ server.closeAllConnections();
1705
+ }
1706
+ server.close(error => {
1707
+ if (error && error.message !== 'Server is not running.') {
1708
+ logForDebugging(`Error closing HTTP proxy server: ${error.message}`, {
1709
+ level: 'error',
1710
+ });
1711
+ }
1712
+ resolve();
1713
+ });
1714
+ });
1715
+ }
1716
+ async function reset() {
1717
+ // Windows: release this session's sandbox-user ACEs. Best-effort
1718
+ // — log anomalies rather than throw, so teardown always
1719
+ // completes. Leftover ACEs are recoverable later via
1720
+ // `srt-win acl recover` (which sweeps by trustee SID).
1721
+ if (windowsFsStampedSet && windowsFsSbUserSid) {
1722
+ const sb = windowsFsSbUserSid;
1723
+ // Captured at initialize() — the SAME binary the grants/stamps
1724
+ // were applied with, immune to `config` mutation between.
1725
+ const srtWin = srtWinSpawn;
1726
+ // 'restored'/'alreadyOriginal' are the pre- same-user-removal
1727
+ // srt-win's success vocabulary; 'revoked'/'stillHeld' are the
1728
+ // post-. Either is non-anomalous.
1729
+ const ok = new Set(['revoked', 'stillHeld', 'restored', 'alreadyOriginal']);
1730
+ const log = (kind, e) => {
1731
+ if (!ok.has(e.status)) {
1732
+ logForDebugging(`[Sandbox Windows] ${kind}: '${e.path}' ${e.status} — ` +
1733
+ `ACE may be left in place; resolve and run ` +
1734
+ `\`srt-win acl recover\` to clear`, { level: 'warn' });
1735
+ }
1736
+ };
1737
+ for (const e of revokeWindowsAcl({ sandboxUserSid: sb, srtWin }) ?? []) {
1738
+ log('grant revoke', e);
1739
+ }
1740
+ for (const e of restoreWindowsAcl({ sandboxUserSid: sb, srtWin }) ?? []) {
1741
+ log('deny restore', e);
1742
+ }
1743
+ }
1744
+ windowsFsStampedSet = undefined;
1745
+ windowsFsSbUserSid = undefined;
1746
+ windowsFsRawInputs = undefined;
1747
+ srtWinSpawn = undefined;
1748
+ // windowsWfpVerified is NOT cleared — per-process, not per-session.
1749
+ // Clean up any leftover bwrap mount points. Force past the
1750
+ // active-sandbox counter — reset() means the session is over.
1751
+ cleanupBwrapMountPoints({ force: true });
1752
+ // Stop log monitor
1753
+ if (logMonitorShutdown) {
1754
+ logMonitorShutdown();
1755
+ logMonitorShutdown = undefined;
1756
+ }
1757
+ if (linuxMonitor) {
1758
+ linuxMonitor.stop();
1759
+ linuxMonitor = undefined;
1760
+ }
1761
+ if (managerContext?.linuxBridge) {
1762
+ const { httpSocketPath, socksSocketPath, httpBridgeProcess, socksBridgeProcess, } = managerContext.linuxBridge;
1763
+ // Kill both bridges and wait for them to exit
1764
+ await Promise.all([
1765
+ killBridgeProcess(httpBridgeProcess, 'HTTP'),
1766
+ killBridgeProcess(socksBridgeProcess, 'SOCKS'),
1767
+ ]);
1768
+ // Clean up sockets
1769
+ if (httpSocketPath) {
1770
+ try {
1771
+ fs.rmSync(httpSocketPath, { force: true });
1772
+ logForDebugging('Cleaned up HTTP socket');
1773
+ }
1774
+ catch (err) {
1775
+ logForDebugging(`HTTP socket cleanup error: ${err}`, {
1776
+ level: 'error',
1777
+ });
1778
+ }
1779
+ }
1780
+ if (socksSocketPath) {
1781
+ try {
1782
+ fs.rmSync(socksSocketPath, { force: true });
1783
+ logForDebugging('Cleaned up SOCKS socket');
1784
+ }
1785
+ catch (err) {
1786
+ logForDebugging(`SOCKS socket cleanup error: ${err}`, {
1787
+ level: 'error',
1788
+ });
1789
+ }
1790
+ }
1791
+ }
1792
+ // Close servers in parallel (only if they exist, i.e., were started by us)
1793
+ const closePromises = [];
1794
+ if (mitmCA) {
1795
+ closePromises.push(disposeMitmCA(mitmCA));
1796
+ }
1797
+ if (muxProxyServer) {
1798
+ closePromises.push(muxProxyServer.close().catch((error) => {
1799
+ logForDebugging(`Error closing mux proxy server: ${error.message}`, {
1800
+ level: 'error',
1801
+ });
1802
+ }));
1803
+ }
1804
+ if (httpProxyServer) {
1805
+ closePromises.push(forceCloseHttpServer(httpProxyServer));
1806
+ }
1807
+ if (socksProxyServer) {
1808
+ const socksClose = socksProxyServer.close().catch((error) => {
1809
+ logForDebugging(`Error closing SOCKS proxy server: ${error.message}`, {
1810
+ level: 'error',
1811
+ });
1812
+ });
1813
+ closePromises.push(socksClose);
1814
+ }
1815
+ // Wait for all servers to close
1816
+ await Promise.all(closePromises);
1817
+ // Clear references
1818
+ muxProxyServer = undefined;
1819
+ httpProxyServer = undefined;
1820
+ proxyAuthToken = undefined;
1821
+ socksProxyServer = undefined;
1822
+ managerContext = undefined;
1823
+ initializationPromise = undefined;
1824
+ parentProxy = undefined;
1825
+ resolvedAddressGuard = createResolvedAddressGuard();
1826
+ mitmCA = undefined;
1827
+ javaAgentJarPath = undefined;
1828
+ sentinelRegistry.clear();
1829
+ awsPairRegistry.clear();
1830
+ commandTextsByKey.clear();
1831
+ maskedFileStore.dispose();
1832
+ }
1833
+ function getSandboxViolationStore() {
1834
+ return sandboxViolationStore;
1835
+ }
1836
+ function annotateStderrWithSandboxFailures(command, stderr) {
1837
+ if (!config) {
1838
+ return stderr;
1839
+ }
1840
+ const violations = sandboxViolationStore.getViolationsForCommand(command);
1841
+ if (violations.length === 0) {
1842
+ return stderr;
1843
+ }
1844
+ let annotated = stderr;
1845
+ annotated += EOL + '<sandbox_violations>' + EOL;
1846
+ for (const violation of violations) {
1847
+ annotated += violation.line + EOL;
1848
+ }
1849
+ annotated += '</sandbox_violations>';
1850
+ return annotated;
1851
+ }
1852
+ /**
1853
+ * Returns glob patterns from Edit/Read permission rules that are not
1854
+ * fully supported on Linux. Returns empty array on macOS or when
1855
+ * sandboxing is disabled.
1856
+ *
1857
+ * Patterns ending with /** are excluded since they work as subpaths.
1858
+ */
1859
+ function getLinuxGlobPatternWarnings() {
1860
+ // Only warn on Linux/WSL (bubblewrap doesn't support globs)
1861
+ // macOS supports glob patterns via regex conversion
1862
+ if (getPlatform() !== 'linux' || !config || config.filesystem.disabled) {
1863
+ return [];
1864
+ }
1865
+ const globPatterns = [];
1866
+ // Write paths take no globs at all on Linux: bubblewrap binds concrete
1867
+ // paths, and nothing expands them.
1868
+ const allPaths = [
1869
+ ...config.filesystem.allowWrite,
1870
+ ...config.filesystem.denyWrite,
1871
+ ];
1872
+ for (const path of allPaths) {
1873
+ // Strip trailing /** since that's just a subpath (directory and everything under it)
1874
+ const pathWithoutTrailingStar = removeTrailingGlobSuffix(path);
1875
+ // Only warn if there are still glob characters after removing trailing /**
1876
+ if (containsGlobChars(pathWithoutTrailingStar)) {
1877
+ globPatterns.push(path);
1878
+ }
1879
+ }
1880
+ // Read paths are expanded, so a glob there is supported — unless the
1881
+ // pattern has no literal directory for the walk to start from (a wildcard
1882
+ // in its first path component, `/**/*.pem`), which expands to nothing and
1883
+ // leaves the entry unenforced.
1884
+ for (const path of [
1885
+ ...config.filesystem.denyRead,
1886
+ ...(config.filesystem.allowRead ?? []),
1887
+ ]) {
1888
+ const baseDir = globPatternBaseDir(normalizePathForSandbox(path));
1889
+ if (containsGlobChars(removeTrailingGlobSuffix(path)) &&
1890
+ (baseDir === '' || baseDir === '/')) {
1891
+ globPatterns.push(path);
1892
+ }
1893
+ }
1894
+ return globPatterns;
1895
+ }
1896
+ // ============================================================================
1897
+ // Export as Namespace with Interface
1898
+ // ============================================================================
1899
+ /**
1900
+ * Global sandbox manager that handles both network and filesystem restrictions
1901
+ * for this session. This runs outside of the sandbox, on the host machine.
1902
+ */
1903
+ export const SandboxManager = {
1904
+ initialize,
1905
+ isSupportedPlatform,
1906
+ isSandboxingEnabled,
1907
+ checkDependencies,
1908
+ checkDependenciesAsync,
1909
+ getFsReadConfig,
1910
+ getFsWriteConfig,
1911
+ getNetworkRestrictionConfig,
1912
+ getAllowUnixSockets,
1913
+ getAllowLocalBinding,
1914
+ getAllowMachLookup,
1915
+ getIgnoreViolations,
1916
+ getEnableWeakerNestedSandbox,
1917
+ getProxyPort,
1918
+ getProxyAuthToken,
1919
+ getSocksProxyPort,
1920
+ getLinuxHttpSocketPath,
1921
+ getLinuxSocksSocketPath,
1922
+ waitForNetworkInitialization,
1923
+ wrapWithSandbox,
1924
+ wrapWithSandboxArgv,
1925
+ cleanupAfterCommand,
1926
+ reset,
1927
+ getMitmCA: () => mitmCA,
1928
+ getSentinelRegistry: () => sentinelRegistry,
1929
+ getAwsPairRegistry: () => awsPairRegistry,
1930
+ getMaskedFileStore: () => maskedFileStore,
1931
+ getSandboxViolationStore,
1932
+ annotateStderrWithSandboxFailures,
1933
+ getLinuxGlobPatternWarnings,
1934
+ getConfig,
1935
+ updateConfig,
1936
+ };
1937
+ //# sourceMappingURL=sandbox-manager.js.map