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.
- package/LICENSE +201 -0
- package/NOTICE +10 -0
- package/README.md +77 -0
- package/dist/approvals.d.ts +72 -0
- package/dist/approvals.js +167 -0
- package/dist/approvals.js.map +1 -0
- package/dist/audit.d.ts +28 -0
- package/dist/audit.js +40 -0
- package/dist/audit.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/context-files.d.ts +14 -0
- package/dist/context-files.js +113 -0
- package/dist/context-files.js.map +1 -0
- package/dist/contracts.d.ts +258 -0
- package/dist/contracts.js +102 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/native/darwin-arm64/artifact.json +5 -0
- package/dist/native/darwin-arm64/pi-guard-execpolicy +0 -0
- package/dist/native/linux-x64/artifact.json +5 -0
- package/dist/native/linux-x64/pi-guard-execpolicy +0 -0
- package/dist/policy/domains.d.ts +5 -0
- package/dist/policy/domains.js +18 -0
- package/dist/policy/domains.js.map +1 -0
- package/dist/policy/index.d.ts +56 -0
- package/dist/policy/index.js +304 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/paths.d.ts +5 -0
- package/dist/policy/paths.js +54 -0
- package/dist/policy/paths.js.map +1 -0
- package/dist/policy/rules.d.ts +36 -0
- package/dist/policy/rules.js +61 -0
- package/dist/policy/rules.js.map +1 -0
- package/dist/policy/shell.d.ts +14 -0
- package/dist/policy/shell.js +122 -0
- package/dist/policy/shell.js.map +1 -0
- package/dist/reports.d.ts +21 -0
- package/dist/reports.js +42 -0
- package/dist/reports.js.map +1 -0
- package/dist/review/context.d.ts +25 -0
- package/dist/review/context.js +108 -0
- package/dist/review/context.js.map +1 -0
- package/dist/review/investigation.d.ts +39 -0
- package/dist/review/investigation.js +36 -0
- package/dist/review/investigation.js.map +1 -0
- package/dist/review/lifecycle.d.ts +29 -0
- package/dist/review/lifecycle.js +71 -0
- package/dist/review/lifecycle.js.map +1 -0
- package/dist/review/policy.d.ts +4 -0
- package/dist/review/policy.js +15 -0
- package/dist/review/policy.js.map +1 -0
- package/dist/review/upstream-policy.d.ts +2 -0
- package/dist/review/upstream-policy.js +210 -0
- package/dist/review/upstream-policy.js.map +1 -0
- package/dist/reviewer.d.ts +45 -0
- package/dist/reviewer.js +148 -0
- package/dist/reviewer.js.map +1 -0
- package/dist/sandbox/broker.d.ts +1 -0
- package/dist/sandbox/broker.js +135 -0
- package/dist/sandbox/broker.js.map +1 -0
- package/dist/sandbox/config.d.ts +5 -0
- package/dist/sandbox/config.js +91 -0
- package/dist/sandbox/config.js.map +1 -0
- package/dist/sandbox/executor.d.ts +20 -0
- package/dist/sandbox/executor.js +144 -0
- package/dist/sandbox/executor.js.map +1 -0
- package/dist/sandbox/hard-links.d.ts +4 -0
- package/dist/sandbox/hard-links.js +145 -0
- package/dist/sandbox/hard-links.js.map +1 -0
- package/dist/sandbox/linux-read-paths.d.ts +7 -0
- package/dist/sandbox/linux-read-paths.js +47 -0
- package/dist/sandbox/linux-read-paths.js.map +1 -0
- package/dist/sandbox/paths.d.ts +3 -0
- package/dist/sandbox/paths.js +10 -0
- package/dist/sandbox/paths.js.map +1 -0
- package/dist/sandbox/runtime-write-paths.d.ts +2 -0
- package/dist/sandbox/runtime-write-paths.js +8 -0
- package/dist/sandbox/runtime-write-paths.js.map +1 -0
- package/dist/sandbox/seccomp.d.ts +5 -0
- package/dist/sandbox/seccomp.js +16 -0
- package/dist/sandbox/seccomp.js.map +1 -0
- package/dist/sandbox/worker.d.ts +1 -0
- package/dist/sandbox/worker.js +73 -0
- package/dist/sandbox/worker.js.map +1 -0
- package/dist/signals.d.ts +10 -0
- package/dist/signals.js +21 -0
- package/dist/signals.js.map +1 -0
- package/dist/startup.d.ts +22 -0
- package/dist/startup.js +100 -0
- package/dist/startup.js.map +1 -0
- package/dist/tools/controller.d.ts +63 -0
- package/dist/tools/controller.js +286 -0
- package/dist/tools/controller.js.map +1 -0
- package/dist/tools/external.d.ts +30 -0
- package/dist/tools/external.js +24 -0
- package/dist/tools/external.js.map +1 -0
- package/dist/tools/mcp.d.ts +17 -0
- package/dist/tools/mcp.js +186 -0
- package/dist/tools/mcp.js.map +1 -0
- package/docs/publishing.md +73 -0
- package/docs/security/dependencies.md +43 -0
- package/docs/testing/auto-review-protection.md +130 -0
- package/docs/usage.md +217 -0
- package/native/execpolicy/LICENSE +201 -0
- package/native/execpolicy/NOTICE +6 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/LICENSE +201 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/README.md +901 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.d.ts +3 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.js +472 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/cli.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.d.ts +19 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.js +17 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/index.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.d.ts +52 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.js +153 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/address.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.d.ts +164 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.js +246 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/aws-sigv4.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.d.ts +58 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.js +128 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/body-substitution.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.d.ts +124 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.js +258 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-aws-pairs.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.d.ts +87 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.js +138 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-decode.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.d.ts +67 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.js +113 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-extract.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.d.ts +70 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.js +171 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-env.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.d.ts +120 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.js +281 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-mask-files.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.d.ts +108 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.js +208 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/credential-sentinel.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.d.ts +82 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.js +155 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/domain-pattern.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.d.ts +44 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.js +220 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/generate-seccomp-filter.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.d.ts +150 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.js +678 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/http-proxy.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.d.ts +32 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.js +111 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/java-proxy-agent.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.d.ts +305 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.js +2605 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-sandbox-utils.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.d.ts +55 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.js +152 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/linux-violation-monitor.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.d.ts +12 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.js +43 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/listen-in-range.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.d.ts +116 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.js +1195 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/macos-sandbox-utils.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.d.ts +200 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.js +443 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-ca.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.d.ts +28 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.js +114 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mitm-leaf.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.d.ts +59 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.js +159 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/mux-proxy.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.d.ts +147 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.js +445 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/parent-proxy.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.d.ts +17 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.js +163 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/read-deny-glob.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.d.ts +83 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.js +212 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/request-filter.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.d.ts +76 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.js +221 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/resolved-address-guard.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.d.ts +1691 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.js +1233 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-config.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.d.ts +97 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.js +1937 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-manager.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.d.ts +113 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.js +3 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-schemas.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.d.ts +411 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.js +1408 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-utils.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.d.ts +37 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.js +125 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/sandbox-violation-store.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.d.ts +57 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.js +332 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/socks-proxy.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.d.ts +100 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.js +546 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/tls-terminate-proxy.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.d.ts +923 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.js +1419 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/sandbox/windows-sandbox-utils.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.d.ts +31 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.js +69 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/config-loader.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.d.ts +7 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.js +25 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/debug.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.d.ts +15 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.js +49 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/platform.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.d.ts +17 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.js +37 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/ripgrep.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.d.ts +27 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.js +47 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/shell-quote.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.d.ts +9 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.d.ts.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.js +25 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/dist/utils/which.js.map +1 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/package.json +88 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/java-proxy-agent/build.ts +95 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/java-proxy-agent/srt-proxy-agent.jar +0 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/arm64/apply-seccomp +0 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/build.ts +69 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/x64/apply-seccomp +0 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/arm64/srt-win.exe +0 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/build.ts +28 -0
- package/node_modules/@anthropic-ai/sandbox-runtime/vendor/srt-win/x64/srt-win.exe +0 -0
- package/node_modules/@pondwader/socks5-server/.github/workflows/ci.yml +27 -0
- package/node_modules/@pondwader/socks5-server/LICENSE +20 -0
- package/node_modules/@pondwader/socks5-server/README.md +151 -0
- package/node_modules/@pondwader/socks5-server/dist/index.d.mts +87 -0
- package/node_modules/@pondwader/socks5-server/dist/index.d.ts +87 -0
- package/node_modules/@pondwader/socks5-server/dist/index.js +346 -0
- package/node_modules/@pondwader/socks5-server/dist/index.mjs +307 -0
- package/node_modules/@pondwader/socks5-server/package.json +31 -0
- package/node_modules/commander/LICENSE +22 -0
- package/node_modules/commander/Readme.md +1157 -0
- package/node_modules/commander/esm.mjs +16 -0
- package/node_modules/commander/index.js +24 -0
- package/node_modules/commander/lib/argument.js +149 -0
- package/node_modules/commander/lib/command.js +2509 -0
- package/node_modules/commander/lib/error.js +39 -0
- package/node_modules/commander/lib/help.js +520 -0
- package/node_modules/commander/lib/option.js +330 -0
- package/node_modules/commander/lib/suggestSimilar.js +101 -0
- package/node_modules/commander/package-support.json +16 -0
- package/node_modules/commander/package.json +84 -0
- package/node_modules/commander/typings/esm.d.mts +3 -0
- package/node_modules/commander/typings/index.d.ts +969 -0
- package/node_modules/node-forge/.editorconfig +17 -0
- package/node_modules/node-forge/.eslintrc.js +24 -0
- package/node_modules/node-forge/.github/workflows/main.yaml +96 -0
- package/node_modules/node-forge/.istanbul.yml +2 -0
- package/node_modules/node-forge/.npmignore +15 -0
- package/node_modules/node-forge/CHANGELOG.md +555 -0
- package/node_modules/node-forge/CONTRIBUTING.md +18 -0
- package/node_modules/node-forge/LICENSE +331 -0
- package/node_modules/node-forge/README.md +2071 -0
- package/node_modules/node-forge/RELEASE.md +19 -0
- package/node_modules/node-forge/SECURITY.md +5 -0
- package/node_modules/node-forge/examples/create-cert.js +110 -0
- package/node_modules/node-forge/examples/create-csr.js +66 -0
- package/node_modules/node-forge/examples/create-pkcs12.js +160 -0
- package/node_modules/node-forge/examples/imap.js +46 -0
- package/node_modules/node-forge/examples/sign-p7.js +115 -0
- package/node_modules/node-forge/examples/tls.js +189 -0
- package/node_modules/node-forge/flash/PooledSocket.as +18 -0
- package/node_modules/node-forge/flash/README.md +48 -0
- package/node_modules/node-forge/flash/SocketEvent.as +36 -0
- package/node_modules/node-forge/flash/SocketPool.as +754 -0
- package/node_modules/node-forge/flash/mod_fsp/README +135 -0
- package/node_modules/node-forge/flash/mod_fsp/mod_fsp.c +415 -0
- package/node_modules/node-forge/flash/package.json +28 -0
- package/node_modules/node-forge/flash/policyserver.js +65 -0
- package/node_modules/node-forge/flash/policyserver.py +112 -0
- package/node_modules/node-forge/flash/swf/SocketPool.swf +0 -0
- package/node_modules/node-forge/karma-sauce.conf.js +79 -0
- package/node_modules/node-forge/karma.conf.js +133 -0
- package/node_modules/node-forge/lib/aes.js +1091 -0
- package/node_modules/node-forge/lib/aesCipherSuites.js +282 -0
- package/node_modules/node-forge/lib/asn1-validator.js +91 -0
- package/node_modules/node-forge/lib/asn1.js +1503 -0
- package/node_modules/node-forge/lib/baseN.js +186 -0
- package/node_modules/node-forge/lib/cipher.js +230 -0
- package/node_modules/node-forge/lib/cipherModes.js +999 -0
- package/node_modules/node-forge/lib/des.js +496 -0
- package/node_modules/node-forge/lib/ed25519.js +1091 -0
- package/node_modules/node-forge/lib/forge.js +13 -0
- package/node_modules/node-forge/lib/form.js +149 -0
- package/node_modules/node-forge/lib/hmac.js +146 -0
- package/node_modules/node-forge/lib/http.js +1346 -0
- package/node_modules/node-forge/lib/index.all.js +16 -0
- package/node_modules/node-forge/lib/index.js +33 -0
- package/node_modules/node-forge/lib/jsbn.js +1294 -0
- package/node_modules/node-forge/lib/kem.js +168 -0
- package/node_modules/node-forge/lib/log.js +319 -0
- package/node_modules/node-forge/lib/md.all.js +13 -0
- package/node_modules/node-forge/lib/md.js +11 -0
- package/node_modules/node-forge/lib/md5.js +289 -0
- package/node_modules/node-forge/lib/mgf.js +12 -0
- package/node_modules/node-forge/lib/mgf1.js +57 -0
- package/node_modules/node-forge/lib/oids.js +180 -0
- package/node_modules/node-forge/lib/pbe.js +1023 -0
- package/node_modules/node-forge/lib/pbkdf2.js +211 -0
- package/node_modules/node-forge/lib/pem.js +237 -0
- package/node_modules/node-forge/lib/pkcs1.js +276 -0
- package/node_modules/node-forge/lib/pkcs12.js +1078 -0
- package/node_modules/node-forge/lib/pkcs7.js +1260 -0
- package/node_modules/node-forge/lib/pkcs7asn1.js +410 -0
- package/node_modules/node-forge/lib/pki.js +102 -0
- package/node_modules/node-forge/lib/prime.js +297 -0
- package/node_modules/node-forge/lib/prime.worker.js +168 -0
- package/node_modules/node-forge/lib/prng.js +419 -0
- package/node_modules/node-forge/lib/pss.js +241 -0
- package/node_modules/node-forge/lib/random.js +191 -0
- package/node_modules/node-forge/lib/rc2.js +410 -0
- package/node_modules/node-forge/lib/rsa.js +1973 -0
- package/node_modules/node-forge/lib/sha1.js +319 -0
- package/node_modules/node-forge/lib/sha256.js +327 -0
- package/node_modules/node-forge/lib/sha512.js +561 -0
- package/node_modules/node-forge/lib/socket.js +287 -0
- package/node_modules/node-forge/lib/ssh.js +236 -0
- package/node_modules/node-forge/lib/tls.js +4282 -0
- package/node_modules/node-forge/lib/tlssocket.js +249 -0
- package/node_modules/node-forge/lib/util.js +2652 -0
- package/node_modules/node-forge/lib/x509.js +3251 -0
- package/node_modules/node-forge/lib/xhr.js +738 -0
- package/node_modules/node-forge/package.json +123 -0
- package/node_modules/node-forge/tests/.eslintrc.js +5 -0
- package/node_modules/node-forge/tests/README.md +4 -0
- package/node_modules/node-forge/tests/benchmarks/aes-speed.js +62 -0
- package/node_modules/node-forge/tests/benchmarks/so-44303784.js +246 -0
- package/node_modules/node-forge/tests/flash/README.md +7 -0
- package/node_modules/node-forge/tests/flash/Test.as +96 -0
- package/node_modules/node-forge/tests/flash/build-flash.xml +7 -0
- package/node_modules/node-forge/tests/flash/index.html +28 -0
- package/node_modules/node-forge/tests/index.html +33 -0
- package/node_modules/node-forge/tests/issues/heartbleed.js +55 -0
- package/node_modules/node-forge/tests/issues/issue-428.html +95 -0
- package/node_modules/node-forge/tests/issues/issue-428.js +375 -0
- package/node_modules/node-forge/tests/karma/index.js +8 -0
- package/node_modules/node-forge/tests/karma/testWorker.js +65 -0
- package/node_modules/node-forge/tests/karma/web-worker-rsa.js +55 -0
- package/node_modules/node-forge/tests/legacy/common.html +65 -0
- package/node_modules/node-forge/tests/legacy/common.js +2199 -0
- package/node_modules/node-forge/tests/legacy/form.html +148 -0
- package/node_modules/node-forge/tests/legacy/form.js +40 -0
- package/node_modules/node-forge/tests/legacy/http.html +235 -0
- package/node_modules/node-forge/tests/legacy/index.html +70 -0
- package/node_modules/node-forge/tests/legacy/keygen.html +113 -0
- package/node_modules/node-forge/tests/legacy/login.css +26 -0
- package/node_modules/node-forge/tests/legacy/loginDemo.html +32 -0
- package/node_modules/node-forge/tests/legacy/loginDemo.js +149 -0
- package/node_modules/node-forge/tests/legacy/performance.html +533 -0
- package/node_modules/node-forge/tests/legacy/result.txt +1 -0
- package/node_modules/node-forge/tests/legacy/socketPool.html +302 -0
- package/node_modules/node-forge/tests/legacy/tasks.html +54 -0
- package/node_modules/node-forge/tests/legacy/tasks.js +378 -0
- package/node_modules/node-forge/tests/legacy/tls.html +389 -0
- package/node_modules/node-forge/tests/legacy/webid.html +89 -0
- package/node_modules/node-forge/tests/legacy/webid.js +313 -0
- package/node_modules/node-forge/tests/legacy/ws-webid.js +120 -0
- package/node_modules/node-forge/tests/legacy/xhr.html +67 -0
- package/node_modules/node-forge/tests/legacy/xhr.js +590 -0
- package/node_modules/node-forge/tests/pocs/ghsa-2328-f5f3-gj25.js +85 -0
- package/node_modules/node-forge/tests/pocs/ghsa-ppp5-5v6c-4jwp.js +166 -0
- package/node_modules/node-forge/tests/pocs/ghsa-q67f-28xg-22rw.js +103 -0
- package/node_modules/node-forge/tests/security/cve-2025-12816.js +75 -0
- package/node_modules/node-forge/tests/security/ghsa-554w-wpv2-vw27.js +81 -0
- package/node_modules/node-forge/tests/security/index.js +3 -0
- package/node_modules/node-forge/tests/server.crt +26 -0
- package/node_modules/node-forge/tests/server.js +87 -0
- package/node_modules/node-forge/tests/server.key +27 -0
- package/node_modules/node-forge/tests/support/task.js +718 -0
- package/node_modules/node-forge/tests/tests.css +61 -0
- package/node_modules/node-forge/tests/unit/aes.js +1498 -0
- package/node_modules/node-forge/tests/unit/asn1.js +1337 -0
- package/node_modules/node-forge/tests/unit/csr.js +129 -0
- package/node_modules/node-forge/tests/unit/des.js +231 -0
- package/node_modules/node-forge/tests/unit/ed25519.js +395 -0
- package/node_modules/node-forge/tests/unit/forge.js +2 -0
- package/node_modules/node-forge/tests/unit/hmac.js +64 -0
- package/node_modules/node-forge/tests/unit/index.html +20 -0
- package/node_modules/node-forge/tests/unit/index.js +27 -0
- package/node_modules/node-forge/tests/unit/jsbn.js +40 -0
- package/node_modules/node-forge/tests/unit/kem.js +167 -0
- package/node_modules/node-forge/tests/unit/md5.js +114 -0
- package/node_modules/node-forge/tests/unit/mgf1.js +16 -0
- package/node_modules/node-forge/tests/unit/pbkdf2.js +182 -0
- package/node_modules/node-forge/tests/unit/pem.js +159 -0
- package/node_modules/node-forge/tests/unit/pkcs1.js +1077 -0
- package/node_modules/node-forge/tests/unit/pkcs12.js +739 -0
- package/node_modules/node-forge/tests/unit/pkcs7.js +792 -0
- package/node_modules/node-forge/tests/unit/random.js +48 -0
- package/node_modules/node-forge/tests/unit/rc2.js +88 -0
- package/node_modules/node-forge/tests/unit/rsa.js +1278 -0
- package/node_modules/node-forge/tests/unit/sha1.js +72 -0
- package/node_modules/node-forge/tests/unit/sha256.js +79 -0
- package/node_modules/node-forge/tests/unit/sha512.js +200 -0
- package/node_modules/node-forge/tests/unit/ssh.js +175 -0
- package/node_modules/node-forge/tests/unit/tls.js +175 -0
- package/node_modules/node-forge/tests/unit/util.js +595 -0
- package/node_modules/node-forge/tests/unit/x509.js +1986 -0
- package/node_modules/node-forge/tests/websockets/server-webid.js +495 -0
- package/node_modules/node-forge/tests/websockets/server-ws.js +158 -0
- package/node_modules/node-forge/webpack-tests.config.js +26 -0
- package/node_modules/node-forge/webpack.config.js +130 -0
- package/node_modules/zod/LICENSE +21 -0
- package/node_modules/zod/README.md +208 -0
- package/node_modules/zod/index.cjs +33 -0
- package/node_modules/zod/index.d.cts +4 -0
- package/node_modules/zod/index.d.ts +4 -0
- package/node_modules/zod/index.js +4 -0
- package/node_modules/zod/package.json +118 -0
- package/node_modules/zod/src/index.ts +4 -0
- package/node_modules/zod/src/v3/ZodError.ts +330 -0
- package/node_modules/zod/src/v3/benchmarks/datetime.ts +58 -0
- package/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts +80 -0
- package/node_modules/zod/src/v3/benchmarks/index.ts +59 -0
- package/node_modules/zod/src/v3/benchmarks/ipv4.ts +57 -0
- package/node_modules/zod/src/v3/benchmarks/object.ts +69 -0
- package/node_modules/zod/src/v3/benchmarks/primitives.ts +162 -0
- package/node_modules/zod/src/v3/benchmarks/realworld.ts +63 -0
- package/node_modules/zod/src/v3/benchmarks/string.ts +55 -0
- package/node_modules/zod/src/v3/benchmarks/union.ts +80 -0
- package/node_modules/zod/src/v3/errors.ts +13 -0
- package/node_modules/zod/src/v3/external.ts +6 -0
- package/node_modules/zod/src/v3/helpers/enumUtil.ts +17 -0
- package/node_modules/zod/src/v3/helpers/errorUtil.ts +8 -0
- package/node_modules/zod/src/v3/helpers/parseUtil.ts +176 -0
- package/node_modules/zod/src/v3/helpers/partialUtil.ts +34 -0
- package/node_modules/zod/src/v3/helpers/typeAliases.ts +2 -0
- package/node_modules/zod/src/v3/helpers/util.ts +224 -0
- package/node_modules/zod/src/v3/index.ts +4 -0
- package/node_modules/zod/src/v3/locales/en.ts +124 -0
- package/node_modules/zod/src/v3/standard-schema.ts +113 -0
- package/node_modules/zod/src/v3/tests/Mocker.ts +54 -0
- package/node_modules/zod/src/v3/tests/all-errors.test.ts +157 -0
- package/node_modules/zod/src/v3/tests/anyunknown.test.ts +28 -0
- package/node_modules/zod/src/v3/tests/array.test.ts +71 -0
- package/node_modules/zod/src/v3/tests/async-parsing.test.ts +388 -0
- package/node_modules/zod/src/v3/tests/async-refinements.test.ts +46 -0
- package/node_modules/zod/src/v3/tests/base.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/bigint.test.ts +55 -0
- package/node_modules/zod/src/v3/tests/branded.test.ts +53 -0
- package/node_modules/zod/src/v3/tests/catch.test.ts +220 -0
- package/node_modules/zod/src/v3/tests/coerce.test.ts +133 -0
- package/node_modules/zod/src/v3/tests/complex.test.ts +56 -0
- package/node_modules/zod/src/v3/tests/custom.test.ts +31 -0
- package/node_modules/zod/src/v3/tests/date.test.ts +32 -0
- package/node_modules/zod/src/v3/tests/deepmasking.test.ts +186 -0
- package/node_modules/zod/src/v3/tests/default.test.ts +112 -0
- package/node_modules/zod/src/v3/tests/description.test.ts +33 -0
- package/node_modules/zod/src/v3/tests/discriminated-unions.test.ts +315 -0
- package/node_modules/zod/src/v3/tests/enum.test.ts +80 -0
- package/node_modules/zod/src/v3/tests/error.test.ts +551 -0
- package/node_modules/zod/src/v3/tests/firstparty.test.ts +87 -0
- package/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts +21 -0
- package/node_modules/zod/src/v3/tests/function.test.ts +257 -0
- package/node_modules/zod/src/v3/tests/generics.test.ts +48 -0
- package/node_modules/zod/src/v3/tests/instanceof.test.ts +37 -0
- package/node_modules/zod/src/v3/tests/intersection.test.ts +110 -0
- package/node_modules/zod/src/v3/tests/language-server.source.ts +76 -0
- package/node_modules/zod/src/v3/tests/language-server.test.ts +207 -0
- package/node_modules/zod/src/v3/tests/literal.test.ts +36 -0
- package/node_modules/zod/src/v3/tests/map.test.ts +110 -0
- package/node_modules/zod/src/v3/tests/masking.test.ts +4 -0
- package/node_modules/zod/src/v3/tests/mocker.test.ts +19 -0
- package/node_modules/zod/src/v3/tests/nan.test.ts +21 -0
- package/node_modules/zod/src/v3/tests/nativeEnum.test.ts +87 -0
- package/node_modules/zod/src/v3/tests/nullable.test.ts +42 -0
- package/node_modules/zod/src/v3/tests/number.test.ts +176 -0
- package/node_modules/zod/src/v3/tests/object-augmentation.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/object.test.ts +434 -0
- package/node_modules/zod/src/v3/tests/optional.test.ts +42 -0
- package/node_modules/zod/src/v3/tests/parseUtil.test.ts +23 -0
- package/node_modules/zod/src/v3/tests/parser.test.ts +41 -0
- package/node_modules/zod/src/v3/tests/partials.test.ts +243 -0
- package/node_modules/zod/src/v3/tests/pickomit.test.ts +111 -0
- package/node_modules/zod/src/v3/tests/pipeline.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/preprocess.test.ts +186 -0
- package/node_modules/zod/src/v3/tests/primitive.test.ts +440 -0
- package/node_modules/zod/src/v3/tests/promise.test.ts +90 -0
- package/node_modules/zod/src/v3/tests/readonly.test.ts +194 -0
- package/node_modules/zod/src/v3/tests/record.test.ts +171 -0
- package/node_modules/zod/src/v3/tests/recursive.test.ts +197 -0
- package/node_modules/zod/src/v3/tests/refine.test.ts +313 -0
- package/node_modules/zod/src/v3/tests/safeparse.test.ts +27 -0
- package/node_modules/zod/src/v3/tests/set.test.ts +142 -0
- package/node_modules/zod/src/v3/tests/standard-schema.test.ts +83 -0
- package/node_modules/zod/src/v3/tests/string.test.ts +916 -0
- package/node_modules/zod/src/v3/tests/transformer.test.ts +233 -0
- package/node_modules/zod/src/v3/tests/tuple.test.ts +90 -0
- package/node_modules/zod/src/v3/tests/unions.test.ts +57 -0
- package/node_modules/zod/src/v3/tests/validations.test.ts +133 -0
- package/node_modules/zod/src/v3/tests/void.test.ts +15 -0
- package/node_modules/zod/src/v3/types.ts +5136 -0
- package/node_modules/zod/src/v4/classic/checks.ts +30 -0
- package/node_modules/zod/src/v4/classic/coerce.ts +27 -0
- package/node_modules/zod/src/v4/classic/compat.ts +66 -0
- package/node_modules/zod/src/v4/classic/errors.ts +75 -0
- package/node_modules/zod/src/v4/classic/external.ts +50 -0
- package/node_modules/zod/src/v4/classic/index.ts +5 -0
- package/node_modules/zod/src/v4/classic/iso.ts +90 -0
- package/node_modules/zod/src/v4/classic/parse.ts +33 -0
- package/node_modules/zod/src/v4/classic/schemas.ts +2054 -0
- package/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts +26 -0
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +264 -0
- package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +210 -0
- package/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts +381 -0
- package/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts +68 -0
- package/node_modules/zod/src/v4/classic/tests/base.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +54 -0
- package/node_modules/zod/src/v4/classic/tests/brand.test.ts +63 -0
- package/node_modules/zod/src/v4/classic/tests/catch.test.ts +252 -0
- package/node_modules/zod/src/v4/classic/tests/coalesce.test.ts +20 -0
- package/node_modules/zod/src/v4/classic/tests/coerce.test.ts +160 -0
- package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +352 -0
- package/node_modules/zod/src/v4/classic/tests/custom.test.ts +40 -0
- package/node_modules/zod/src/v4/classic/tests/date.test.ts +31 -0
- package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +296 -0
- package/node_modules/zod/src/v4/classic/tests/default.test.ts +313 -0
- package/node_modules/zod/src/v4/classic/tests/description.test.ts +32 -0
- package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +619 -0
- package/node_modules/zod/src/v4/classic/tests/enum.test.ts +285 -0
- package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +527 -0
- package/node_modules/zod/src/v4/classic/tests/error.test.ts +711 -0
- package/node_modules/zod/src/v4/classic/tests/file.test.ts +91 -0
- package/node_modules/zod/src/v4/classic/tests/firstparty.test.ts +175 -0
- package/node_modules/zod/src/v4/classic/tests/function.test.ts +268 -0
- package/node_modules/zod/src/v4/classic/tests/generics.test.ts +72 -0
- package/node_modules/zod/src/v4/classic/tests/index.test.ts +829 -0
- package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +34 -0
- package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +171 -0
- package/node_modules/zod/src/v4/classic/tests/json.test.ts +108 -0
- package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +227 -0
- package/node_modules/zod/src/v4/classic/tests/literal.test.ts +92 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +196 -0
- package/node_modules/zod/src/v4/classic/tests/nan.test.ts +21 -0
- package/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts +168 -0
- package/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts +86 -0
- package/node_modules/zod/src/v4/classic/tests/nullable.test.ts +22 -0
- package/node_modules/zod/src/v4/classic/tests/number.test.ts +247 -0
- package/node_modules/zod/src/v4/classic/tests/object.test.ts +563 -0
- package/node_modules/zod/src/v4/classic/tests/optional.test.ts +123 -0
- package/node_modules/zod/src/v4/classic/tests/partial.test.ts +147 -0
- package/node_modules/zod/src/v4/classic/tests/pickomit.test.ts +127 -0
- package/node_modules/zod/src/v4/classic/tests/pipe.test.ts +81 -0
- package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +37 -0
- package/node_modules/zod/src/v4/classic/tests/preprocess.test.ts +298 -0
- package/node_modules/zod/src/v4/classic/tests/primitive.test.ts +175 -0
- package/node_modules/zod/src/v4/classic/tests/promise.test.ts +81 -0
- package/node_modules/zod/src/v4/classic/tests/prototypes.test.ts +23 -0
- package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +252 -0
- package/node_modules/zod/src/v4/classic/tests/record.test.ts +342 -0
- package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +356 -0
- package/node_modules/zod/src/v4/classic/tests/refine.test.ts +532 -0
- package/node_modules/zod/src/v4/classic/tests/registries.test.ts +204 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +179 -0
- package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +57 -0
- package/node_modules/zod/src/v4/classic/tests/string-formats.test.ts +109 -0
- package/node_modules/zod/src/v4/classic/tests/string.test.ts +881 -0
- package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +66 -0
- package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +758 -0
- package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +2314 -0
- package/node_modules/zod/src/v4/classic/tests/transform.test.ts +250 -0
- package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +163 -0
- package/node_modules/zod/src/v4/classic/tests/union.test.ts +94 -0
- package/node_modules/zod/src/v4/classic/tests/validations.test.ts +283 -0
- package/node_modules/zod/src/v4/classic/tests/void.test.ts +12 -0
- package/node_modules/zod/src/v4/core/api.ts +1594 -0
- package/node_modules/zod/src/v4/core/checks.ts +1283 -0
- package/node_modules/zod/src/v4/core/config.ts +15 -0
- package/node_modules/zod/src/v4/core/core.ts +134 -0
- package/node_modules/zod/src/v4/core/doc.ts +44 -0
- package/node_modules/zod/src/v4/core/errors.ts +424 -0
- package/node_modules/zod/src/v4/core/function.ts +176 -0
- package/node_modules/zod/src/v4/core/index.ts +15 -0
- package/node_modules/zod/src/v4/core/json-schema.ts +143 -0
- package/node_modules/zod/src/v4/core/parse.ts +94 -0
- package/node_modules/zod/src/v4/core/regexes.ts +135 -0
- package/node_modules/zod/src/v4/core/registries.ts +96 -0
- package/node_modules/zod/src/v4/core/schemas.ts +3842 -0
- package/node_modules/zod/src/v4/core/standard-schema.ts +64 -0
- package/node_modules/zod/src/v4/core/tests/index.test.ts +46 -0
- package/node_modules/zod/src/v4/core/tests/locales/be.test.ts +124 -0
- package/node_modules/zod/src/v4/core/tests/locales/en.test.ts +22 -0
- package/node_modules/zod/src/v4/core/tests/locales/ru.test.ts +128 -0
- package/node_modules/zod/src/v4/core/tests/locales/tr.test.ts +69 -0
- package/node_modules/zod/src/v4/core/to-json-schema.ts +977 -0
- package/node_modules/zod/src/v4/core/util.ts +775 -0
- package/node_modules/zod/src/v4/core/versions.ts +5 -0
- package/node_modules/zod/src/v4/core/zsf.ts +323 -0
- package/node_modules/zod/src/v4/index.ts +4 -0
- package/node_modules/zod/src/v4/locales/ar.ts +125 -0
- package/node_modules/zod/src/v4/locales/az.ts +121 -0
- package/node_modules/zod/src/v4/locales/be.ts +184 -0
- package/node_modules/zod/src/v4/locales/ca.ts +127 -0
- package/node_modules/zod/src/v4/locales/cs.ts +142 -0
- package/node_modules/zod/src/v4/locales/de.ts +124 -0
- package/node_modules/zod/src/v4/locales/en.ts +127 -0
- package/node_modules/zod/src/v4/locales/eo.ts +125 -0
- package/node_modules/zod/src/v4/locales/es.ts +125 -0
- package/node_modules/zod/src/v4/locales/fa.ts +134 -0
- package/node_modules/zod/src/v4/locales/fi.ts +131 -0
- package/node_modules/zod/src/v4/locales/fr-CA.ts +126 -0
- package/node_modules/zod/src/v4/locales/fr.ts +124 -0
- package/node_modules/zod/src/v4/locales/he.ts +125 -0
- package/node_modules/zod/src/v4/locales/hu.ts +126 -0
- package/node_modules/zod/src/v4/locales/id.ts +125 -0
- package/node_modules/zod/src/v4/locales/index.ts +39 -0
- package/node_modules/zod/src/v4/locales/it.ts +125 -0
- package/node_modules/zod/src/v4/locales/ja.ts +122 -0
- package/node_modules/zod/src/v4/locales/kh.ts +126 -0
- package/node_modules/zod/src/v4/locales/ko.ts +131 -0
- package/node_modules/zod/src/v4/locales/mk.ts +127 -0
- package/node_modules/zod/src/v4/locales/ms.ts +124 -0
- package/node_modules/zod/src/v4/locales/nl.ts +126 -0
- package/node_modules/zod/src/v4/locales/no.ts +124 -0
- package/node_modules/zod/src/v4/locales/ota.ts +125 -0
- package/node_modules/zod/src/v4/locales/pl.ts +126 -0
- package/node_modules/zod/src/v4/locales/ps.ts +133 -0
- package/node_modules/zod/src/v4/locales/pt.ts +123 -0
- package/node_modules/zod/src/v4/locales/ru.ts +184 -0
- package/node_modules/zod/src/v4/locales/sl.ts +126 -0
- package/node_modules/zod/src/v4/locales/sv.ts +127 -0
- package/node_modules/zod/src/v4/locales/ta.ts +125 -0
- package/node_modules/zod/src/v4/locales/th.ts +126 -0
- package/node_modules/zod/src/v4/locales/tr.ts +121 -0
- package/node_modules/zod/src/v4/locales/ua.ts +126 -0
- package/node_modules/zod/src/v4/locales/ur.ts +126 -0
- package/node_modules/zod/src/v4/locales/vi.ts +125 -0
- package/node_modules/zod/src/v4/locales/zh-CN.ts +123 -0
- package/node_modules/zod/src/v4/locales/zh-TW.ts +125 -0
- package/node_modules/zod/src/v4/mini/checks.ts +32 -0
- package/node_modules/zod/src/v4/mini/coerce.ts +22 -0
- package/node_modules/zod/src/v4/mini/external.ts +40 -0
- package/node_modules/zod/src/v4/mini/index.ts +3 -0
- package/node_modules/zod/src/v4/mini/iso.ts +62 -0
- package/node_modules/zod/src/v4/mini/parse.ts +1 -0
- package/node_modules/zod/src/v4/mini/schemas.ts +1579 -0
- package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +129 -0
- package/node_modules/zod/src/v4/mini/tests/brand.test.ts +51 -0
- package/node_modules/zod/src/v4/mini/tests/checks.test.ts +144 -0
- package/node_modules/zod/src/v4/mini/tests/computed.test.ts +36 -0
- package/node_modules/zod/src/v4/mini/tests/error.test.ts +22 -0
- package/node_modules/zod/src/v4/mini/tests/functions.test.ts +43 -0
- package/node_modules/zod/src/v4/mini/tests/index.test.ts +871 -0
- package/node_modules/zod/src/v4/mini/tests/number.test.ts +95 -0
- package/node_modules/zod/src/v4/mini/tests/object.test.ts +185 -0
- package/node_modules/zod/src/v4/mini/tests/prototypes.test.ts +43 -0
- package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +275 -0
- package/node_modules/zod/src/v4/mini/tests/string.test.ts +299 -0
- package/node_modules/zod/src/v4-mini/index.ts +1 -0
- package/node_modules/zod/v3/ZodError.cjs +138 -0
- package/node_modules/zod/v3/ZodError.d.cts +164 -0
- package/node_modules/zod/v3/ZodError.d.ts +164 -0
- package/node_modules/zod/v3/ZodError.js +133 -0
- package/node_modules/zod/v3/errors.cjs +17 -0
- package/node_modules/zod/v3/errors.d.cts +5 -0
- package/node_modules/zod/v3/errors.d.ts +5 -0
- package/node_modules/zod/v3/errors.js +9 -0
- package/node_modules/zod/v3/external.cjs +22 -0
- package/node_modules/zod/v3/external.d.cts +6 -0
- package/node_modules/zod/v3/external.d.ts +6 -0
- package/node_modules/zod/v3/external.js +6 -0
- package/node_modules/zod/v3/helpers/enumUtil.cjs +2 -0
- package/node_modules/zod/v3/helpers/enumUtil.d.cts +8 -0
- package/node_modules/zod/v3/helpers/enumUtil.d.ts +8 -0
- package/node_modules/zod/v3/helpers/enumUtil.js +1 -0
- package/node_modules/zod/v3/helpers/errorUtil.cjs +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.d.cts +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.d.ts +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.js +6 -0
- package/node_modules/zod/v3/helpers/parseUtil.cjs +124 -0
- package/node_modules/zod/v3/helpers/parseUtil.d.cts +78 -0
- package/node_modules/zod/v3/helpers/parseUtil.d.ts +78 -0
- package/node_modules/zod/v3/helpers/parseUtil.js +109 -0
- package/node_modules/zod/v3/helpers/partialUtil.cjs +2 -0
- package/node_modules/zod/v3/helpers/partialUtil.d.cts +8 -0
- package/node_modules/zod/v3/helpers/partialUtil.d.ts +8 -0
- package/node_modules/zod/v3/helpers/partialUtil.js +1 -0
- package/node_modules/zod/v3/helpers/typeAliases.cjs +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.d.cts +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.d.ts +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.js +1 -0
- package/node_modules/zod/v3/helpers/util.cjs +137 -0
- package/node_modules/zod/v3/helpers/util.d.cts +85 -0
- package/node_modules/zod/v3/helpers/util.d.ts +85 -0
- package/node_modules/zod/v3/helpers/util.js +133 -0
- package/node_modules/zod/v3/index.cjs +33 -0
- package/node_modules/zod/v3/index.d.cts +4 -0
- package/node_modules/zod/v3/index.d.ts +4 -0
- package/node_modules/zod/v3/index.js +4 -0
- package/node_modules/zod/v3/locales/en.cjs +111 -0
- package/node_modules/zod/v3/locales/en.d.cts +3 -0
- package/node_modules/zod/v3/locales/en.d.ts +3 -0
- package/node_modules/zod/v3/locales/en.js +109 -0
- package/node_modules/zod/v3/standard-schema.cjs +2 -0
- package/node_modules/zod/v3/standard-schema.d.cts +102 -0
- package/node_modules/zod/v3/standard-schema.d.ts +102 -0
- package/node_modules/zod/v3/standard-schema.js +1 -0
- package/node_modules/zod/v3/types.cjs +3775 -0
- package/node_modules/zod/v3/types.d.cts +1031 -0
- package/node_modules/zod/v3/types.d.ts +1031 -0
- package/node_modules/zod/v3/types.js +3693 -0
- package/node_modules/zod/v4/classic/checks.cjs +32 -0
- package/node_modules/zod/v4/classic/checks.d.cts +1 -0
- package/node_modules/zod/v4/classic/checks.d.ts +1 -0
- package/node_modules/zod/v4/classic/checks.js +1 -0
- package/node_modules/zod/v4/classic/coerce.cjs +47 -0
- package/node_modules/zod/v4/classic/coerce.d.cts +17 -0
- package/node_modules/zod/v4/classic/coerce.d.ts +17 -0
- package/node_modules/zod/v4/classic/coerce.js +17 -0
- package/node_modules/zod/v4/classic/compat.cjs +57 -0
- package/node_modules/zod/v4/classic/compat.d.cts +46 -0
- package/node_modules/zod/v4/classic/compat.d.ts +46 -0
- package/node_modules/zod/v4/classic/compat.js +27 -0
- package/node_modules/zod/v4/classic/errors.cjs +67 -0
- package/node_modules/zod/v4/classic/errors.d.cts +30 -0
- package/node_modules/zod/v4/classic/errors.d.ts +30 -0
- package/node_modules/zod/v4/classic/errors.js +41 -0
- package/node_modules/zod/v4/classic/external.cjs +70 -0
- package/node_modules/zod/v4/classic/external.d.cts +13 -0
- package/node_modules/zod/v4/classic/external.d.ts +13 -0
- package/node_modules/zod/v4/classic/external.js +18 -0
- package/node_modules/zod/v4/classic/index.cjs +33 -0
- package/node_modules/zod/v4/classic/index.d.cts +4 -0
- package/node_modules/zod/v4/classic/index.d.ts +4 -0
- package/node_modules/zod/v4/classic/index.js +4 -0
- package/node_modules/zod/v4/classic/iso.cjs +60 -0
- package/node_modules/zod/v4/classic/iso.d.cts +22 -0
- package/node_modules/zod/v4/classic/iso.d.ts +22 -0
- package/node_modules/zod/v4/classic/iso.js +30 -0
- package/node_modules/zod/v4/classic/parse.cjs +32 -0
- package/node_modules/zod/v4/classic/parse.d.cts +23 -0
- package/node_modules/zod/v4/classic/parse.d.ts +23 -0
- package/node_modules/zod/v4/classic/parse.js +6 -0
- package/node_modules/zod/v4/classic/schemas.cjs +1109 -0
- package/node_modules/zod/v4/classic/schemas.d.cts +630 -0
- package/node_modules/zod/v4/classic/schemas.d.ts +630 -0
- package/node_modules/zod/v4/classic/schemas.js +1006 -0
- package/node_modules/zod/v4/core/api.cjs +1039 -0
- package/node_modules/zod/v4/core/api.d.cts +284 -0
- package/node_modules/zod/v4/core/api.d.ts +284 -0
- package/node_modules/zod/v4/core/api.js +906 -0
- package/node_modules/zod/v4/core/checks.cjs +591 -0
- package/node_modules/zod/v4/core/checks.d.cts +278 -0
- package/node_modules/zod/v4/core/checks.d.ts +278 -0
- package/node_modules/zod/v4/core/checks.js +565 -0
- package/node_modules/zod/v4/core/core.cjs +67 -0
- package/node_modules/zod/v4/core/core.d.cts +49 -0
- package/node_modules/zod/v4/core/core.d.ts +49 -0
- package/node_modules/zod/v4/core/core.js +61 -0
- package/node_modules/zod/v4/core/doc.cjs +39 -0
- package/node_modules/zod/v4/core/doc.d.cts +14 -0
- package/node_modules/zod/v4/core/doc.d.ts +14 -0
- package/node_modules/zod/v4/core/doc.js +35 -0
- package/node_modules/zod/v4/core/errors.cjs +226 -0
- package/node_modules/zod/v4/core/errors.d.cts +208 -0
- package/node_modules/zod/v4/core/errors.d.ts +208 -0
- package/node_modules/zod/v4/core/errors.js +195 -0
- package/node_modules/zod/v4/core/function.cjs +102 -0
- package/node_modules/zod/v4/core/function.d.cts +52 -0
- package/node_modules/zod/v4/core/function.d.ts +52 -0
- package/node_modules/zod/v4/core/function.js +75 -0
- package/node_modules/zod/v4/core/index.cjs +44 -0
- package/node_modules/zod/v4/core/index.d.cts +15 -0
- package/node_modules/zod/v4/core/index.d.ts +15 -0
- package/node_modules/zod/v4/core/index.js +15 -0
- package/node_modules/zod/v4/core/json-schema.cjs +2 -0
- package/node_modules/zod/v4/core/json-schema.d.cts +87 -0
- package/node_modules/zod/v4/core/json-schema.d.ts +87 -0
- package/node_modules/zod/v4/core/json-schema.js +1 -0
- package/node_modules/zod/v4/core/parse.cjs +87 -0
- package/node_modules/zod/v4/core/parse.d.cts +25 -0
- package/node_modules/zod/v4/core/parse.d.ts +25 -0
- package/node_modules/zod/v4/core/parse.js +57 -0
- package/node_modules/zod/v4/core/regexes.cjs +103 -0
- package/node_modules/zod/v4/core/regexes.d.cts +62 -0
- package/node_modules/zod/v4/core/regexes.d.ts +62 -0
- package/node_modules/zod/v4/core/regexes.js +95 -0
- package/node_modules/zod/v4/core/registries.cjs +56 -0
- package/node_modules/zod/v4/core/registries.d.cts +35 -0
- package/node_modules/zod/v4/core/registries.d.ts +35 -0
- package/node_modules/zod/v4/core/registries.js +51 -0
- package/node_modules/zod/v4/core/schemas.cjs +1748 -0
- package/node_modules/zod/v4/core/schemas.d.cts +1041 -0
- package/node_modules/zod/v4/core/schemas.d.ts +1041 -0
- package/node_modules/zod/v4/core/schemas.js +1717 -0
- package/node_modules/zod/v4/core/standard-schema.cjs +2 -0
- package/node_modules/zod/v4/core/standard-schema.d.cts +55 -0
- package/node_modules/zod/v4/core/standard-schema.d.ts +55 -0
- package/node_modules/zod/v4/core/standard-schema.js +1 -0
- package/node_modules/zod/v4/core/to-json-schema.cjs +854 -0
- package/node_modules/zod/v4/core/to-json-schema.d.cts +88 -0
- package/node_modules/zod/v4/core/to-json-schema.d.ts +88 -0
- package/node_modules/zod/v4/core/to-json-schema.js +849 -0
- package/node_modules/zod/v4/core/util.cjs +539 -0
- package/node_modules/zod/v4/core/util.d.cts +183 -0
- package/node_modules/zod/v4/core/util.d.ts +183 -0
- package/node_modules/zod/v4/core/util.js +493 -0
- package/node_modules/zod/v4/core/versions.cjs +8 -0
- package/node_modules/zod/v4/core/versions.d.cts +5 -0
- package/node_modules/zod/v4/core/versions.d.ts +5 -0
- package/node_modules/zod/v4/core/versions.js +5 -0
- package/node_modules/zod/v4/index.cjs +22 -0
- package/node_modules/zod/v4/index.d.cts +3 -0
- package/node_modules/zod/v4/index.d.ts +3 -0
- package/node_modules/zod/v4/index.js +3 -0
- package/node_modules/zod/v4/locales/ar.cjs +142 -0
- package/node_modules/zod/v4/locales/ar.d.cts +4 -0
- package/node_modules/zod/v4/locales/ar.d.ts +4 -0
- package/node_modules/zod/v4/locales/ar.js +116 -0
- package/node_modules/zod/v4/locales/az.cjs +141 -0
- package/node_modules/zod/v4/locales/az.d.cts +4 -0
- package/node_modules/zod/v4/locales/az.d.ts +4 -0
- package/node_modules/zod/v4/locales/az.js +115 -0
- package/node_modules/zod/v4/locales/be.cjs +190 -0
- package/node_modules/zod/v4/locales/be.d.cts +4 -0
- package/node_modules/zod/v4/locales/be.d.ts +4 -0
- package/node_modules/zod/v4/locales/be.js +164 -0
- package/node_modules/zod/v4/locales/ca.cjs +144 -0
- package/node_modules/zod/v4/locales/ca.d.cts +4 -0
- package/node_modules/zod/v4/locales/ca.d.ts +4 -0
- package/node_modules/zod/v4/locales/ca.js +118 -0
- package/node_modules/zod/v4/locales/cs.cjs +161 -0
- package/node_modules/zod/v4/locales/cs.d.cts +4 -0
- package/node_modules/zod/v4/locales/cs.d.ts +4 -0
- package/node_modules/zod/v4/locales/cs.js +135 -0
- package/node_modules/zod/v4/locales/de.cjs +142 -0
- package/node_modules/zod/v4/locales/de.d.cts +4 -0
- package/node_modules/zod/v4/locales/de.d.ts +4 -0
- package/node_modules/zod/v4/locales/de.js +116 -0
- package/node_modules/zod/v4/locales/en.cjs +145 -0
- package/node_modules/zod/v4/locales/en.d.cts +5 -0
- package/node_modules/zod/v4/locales/en.d.ts +5 -0
- package/node_modules/zod/v4/locales/en.js +117 -0
- package/node_modules/zod/v4/locales/eo.cjs +144 -0
- package/node_modules/zod/v4/locales/eo.d.cts +5 -0
- package/node_modules/zod/v4/locales/eo.d.ts +5 -0
- package/node_modules/zod/v4/locales/eo.js +116 -0
- package/node_modules/zod/v4/locales/es.cjs +143 -0
- package/node_modules/zod/v4/locales/es.d.cts +4 -0
- package/node_modules/zod/v4/locales/es.d.ts +4 -0
- package/node_modules/zod/v4/locales/es.js +117 -0
- package/node_modules/zod/v4/locales/fa.cjs +148 -0
- package/node_modules/zod/v4/locales/fa.d.cts +4 -0
- package/node_modules/zod/v4/locales/fa.d.ts +4 -0
- package/node_modules/zod/v4/locales/fa.js +122 -0
- package/node_modules/zod/v4/locales/fi.cjs +148 -0
- package/node_modules/zod/v4/locales/fi.d.cts +4 -0
- package/node_modules/zod/v4/locales/fi.d.ts +4 -0
- package/node_modules/zod/v4/locales/fi.js +122 -0
- package/node_modules/zod/v4/locales/fr-CA.cjs +143 -0
- package/node_modules/zod/v4/locales/fr-CA.d.cts +4 -0
- package/node_modules/zod/v4/locales/fr-CA.d.ts +4 -0
- package/node_modules/zod/v4/locales/fr-CA.js +117 -0
- package/node_modules/zod/v4/locales/fr.cjs +142 -0
- package/node_modules/zod/v4/locales/fr.d.cts +4 -0
- package/node_modules/zod/v4/locales/fr.d.ts +4 -0
- package/node_modules/zod/v4/locales/fr.js +116 -0
- package/node_modules/zod/v4/locales/he.cjs +143 -0
- package/node_modules/zod/v4/locales/he.d.cts +4 -0
- package/node_modules/zod/v4/locales/he.d.ts +4 -0
- package/node_modules/zod/v4/locales/he.js +117 -0
- package/node_modules/zod/v4/locales/hu.cjs +143 -0
- package/node_modules/zod/v4/locales/hu.d.cts +4 -0
- package/node_modules/zod/v4/locales/hu.d.ts +4 -0
- package/node_modules/zod/v4/locales/hu.js +117 -0
- package/node_modules/zod/v4/locales/id.cjs +142 -0
- package/node_modules/zod/v4/locales/id.d.cts +4 -0
- package/node_modules/zod/v4/locales/id.d.ts +4 -0
- package/node_modules/zod/v4/locales/id.js +116 -0
- package/node_modules/zod/v4/locales/index.cjs +84 -0
- package/node_modules/zod/v4/locales/index.d.cts +39 -0
- package/node_modules/zod/v4/locales/index.d.ts +39 -0
- package/node_modules/zod/v4/locales/index.js +39 -0
- package/node_modules/zod/v4/locales/it.cjs +143 -0
- package/node_modules/zod/v4/locales/it.d.cts +4 -0
- package/node_modules/zod/v4/locales/it.d.ts +4 -0
- package/node_modules/zod/v4/locales/it.js +117 -0
- package/node_modules/zod/v4/locales/ja.cjs +141 -0
- package/node_modules/zod/v4/locales/ja.d.cts +4 -0
- package/node_modules/zod/v4/locales/ja.d.ts +4 -0
- package/node_modules/zod/v4/locales/ja.js +115 -0
- package/node_modules/zod/v4/locales/kh.cjs +143 -0
- package/node_modules/zod/v4/locales/kh.d.cts +4 -0
- package/node_modules/zod/v4/locales/kh.d.ts +4 -0
- package/node_modules/zod/v4/locales/kh.js +117 -0
- package/node_modules/zod/v4/locales/ko.cjs +147 -0
- package/node_modules/zod/v4/locales/ko.d.cts +4 -0
- package/node_modules/zod/v4/locales/ko.d.ts +4 -0
- package/node_modules/zod/v4/locales/ko.js +121 -0
- package/node_modules/zod/v4/locales/mk.cjs +144 -0
- package/node_modules/zod/v4/locales/mk.d.cts +4 -0
- package/node_modules/zod/v4/locales/mk.d.ts +4 -0
- package/node_modules/zod/v4/locales/mk.js +118 -0
- package/node_modules/zod/v4/locales/ms.cjs +142 -0
- package/node_modules/zod/v4/locales/ms.d.cts +4 -0
- package/node_modules/zod/v4/locales/ms.d.ts +4 -0
- package/node_modules/zod/v4/locales/ms.js +116 -0
- package/node_modules/zod/v4/locales/nl.cjs +143 -0
- package/node_modules/zod/v4/locales/nl.d.cts +4 -0
- package/node_modules/zod/v4/locales/nl.d.ts +4 -0
- package/node_modules/zod/v4/locales/nl.js +117 -0
- package/node_modules/zod/v4/locales/no.cjs +142 -0
- package/node_modules/zod/v4/locales/no.d.cts +4 -0
- package/node_modules/zod/v4/locales/no.d.ts +4 -0
- package/node_modules/zod/v4/locales/no.js +116 -0
- package/node_modules/zod/v4/locales/ota.cjs +143 -0
- package/node_modules/zod/v4/locales/ota.d.cts +4 -0
- package/node_modules/zod/v4/locales/ota.d.ts +4 -0
- package/node_modules/zod/v4/locales/ota.js +117 -0
- package/node_modules/zod/v4/locales/pl.cjs +143 -0
- package/node_modules/zod/v4/locales/pl.d.cts +4 -0
- package/node_modules/zod/v4/locales/pl.d.ts +4 -0
- package/node_modules/zod/v4/locales/pl.js +117 -0
- package/node_modules/zod/v4/locales/ps.cjs +148 -0
- package/node_modules/zod/v4/locales/ps.d.cts +4 -0
- package/node_modules/zod/v4/locales/ps.d.ts +4 -0
- package/node_modules/zod/v4/locales/ps.js +122 -0
- package/node_modules/zod/v4/locales/pt.cjs +142 -0
- package/node_modules/zod/v4/locales/pt.d.cts +4 -0
- package/node_modules/zod/v4/locales/pt.d.ts +4 -0
- package/node_modules/zod/v4/locales/pt.js +116 -0
- package/node_modules/zod/v4/locales/ru.cjs +190 -0
- package/node_modules/zod/v4/locales/ru.d.cts +4 -0
- package/node_modules/zod/v4/locales/ru.d.ts +4 -0
- package/node_modules/zod/v4/locales/ru.js +164 -0
- package/node_modules/zod/v4/locales/sl.cjs +143 -0
- package/node_modules/zod/v4/locales/sl.d.cts +4 -0
- package/node_modules/zod/v4/locales/sl.d.ts +4 -0
- package/node_modules/zod/v4/locales/sl.js +117 -0
- package/node_modules/zod/v4/locales/sv.cjs +144 -0
- package/node_modules/zod/v4/locales/sv.d.cts +4 -0
- package/node_modules/zod/v4/locales/sv.d.ts +4 -0
- package/node_modules/zod/v4/locales/sv.js +118 -0
- package/node_modules/zod/v4/locales/ta.cjs +143 -0
- package/node_modules/zod/v4/locales/ta.d.cts +4 -0
- package/node_modules/zod/v4/locales/ta.d.ts +4 -0
- package/node_modules/zod/v4/locales/ta.js +117 -0
- package/node_modules/zod/v4/locales/th.cjs +143 -0
- package/node_modules/zod/v4/locales/th.d.cts +4 -0
- package/node_modules/zod/v4/locales/th.d.ts +4 -0
- package/node_modules/zod/v4/locales/th.js +117 -0
- package/node_modules/zod/v4/locales/tr.cjs +143 -0
- package/node_modules/zod/v4/locales/tr.d.cts +5 -0
- package/node_modules/zod/v4/locales/tr.d.ts +5 -0
- package/node_modules/zod/v4/locales/tr.js +115 -0
- package/node_modules/zod/v4/locales/ua.cjs +143 -0
- package/node_modules/zod/v4/locales/ua.d.cts +4 -0
- package/node_modules/zod/v4/locales/ua.d.ts +4 -0
- package/node_modules/zod/v4/locales/ua.js +117 -0
- package/node_modules/zod/v4/locales/ur.cjs +143 -0
- package/node_modules/zod/v4/locales/ur.d.cts +4 -0
- package/node_modules/zod/v4/locales/ur.d.ts +4 -0
- package/node_modules/zod/v4/locales/ur.js +117 -0
- package/node_modules/zod/v4/locales/vi.cjs +142 -0
- package/node_modules/zod/v4/locales/vi.d.cts +4 -0
- package/node_modules/zod/v4/locales/vi.d.ts +4 -0
- package/node_modules/zod/v4/locales/vi.js +116 -0
- package/node_modules/zod/v4/locales/zh-CN.cjs +142 -0
- package/node_modules/zod/v4/locales/zh-CN.d.cts +4 -0
- package/node_modules/zod/v4/locales/zh-CN.d.ts +4 -0
- package/node_modules/zod/v4/locales/zh-CN.js +116 -0
- package/node_modules/zod/v4/locales/zh-TW.cjs +143 -0
- package/node_modules/zod/v4/locales/zh-TW.d.cts +4 -0
- package/node_modules/zod/v4/locales/zh-TW.d.ts +4 -0
- package/node_modules/zod/v4/locales/zh-TW.js +117 -0
- package/node_modules/zod/v4/mini/checks.cjs +34 -0
- package/node_modules/zod/v4/mini/checks.d.cts +1 -0
- package/node_modules/zod/v4/mini/checks.d.ts +1 -0
- package/node_modules/zod/v4/mini/checks.js +1 -0
- package/node_modules/zod/v4/mini/coerce.cjs +47 -0
- package/node_modules/zod/v4/mini/coerce.d.cts +7 -0
- package/node_modules/zod/v4/mini/coerce.d.ts +7 -0
- package/node_modules/zod/v4/mini/coerce.js +17 -0
- package/node_modules/zod/v4/mini/external.cjs +62 -0
- package/node_modules/zod/v4/mini/external.d.cts +11 -0
- package/node_modules/zod/v4/mini/external.d.ts +11 -0
- package/node_modules/zod/v4/mini/external.js +13 -0
- package/node_modules/zod/v4/mini/index.cjs +32 -0
- package/node_modules/zod/v4/mini/index.d.cts +3 -0
- package/node_modules/zod/v4/mini/index.d.ts +3 -0
- package/node_modules/zod/v4/mini/index.js +3 -0
- package/node_modules/zod/v4/mini/iso.cjs +60 -0
- package/node_modules/zod/v4/mini/iso.d.cts +22 -0
- package/node_modules/zod/v4/mini/iso.d.ts +22 -0
- package/node_modules/zod/v4/mini/iso.js +30 -0
- package/node_modules/zod/v4/mini/parse.cjs +8 -0
- package/node_modules/zod/v4/mini/parse.d.cts +1 -0
- package/node_modules/zod/v4/mini/parse.d.ts +1 -0
- package/node_modules/zod/v4/mini/parse.js +1 -0
- package/node_modules/zod/v4/mini/schemas.cjs +839 -0
- package/node_modules/zod/v4/mini/schemas.d.cts +356 -0
- package/node_modules/zod/v4/mini/schemas.d.ts +356 -0
- package/node_modules/zod/v4/mini/schemas.js +732 -0
- package/node_modules/zod/v4-mini/index.cjs +17 -0
- package/node_modules/zod/v4-mini/index.d.cts +1 -0
- package/node_modules/zod/v4-mini/index.d.ts +1 -0
- package/node_modules/zod/v4-mini/index.js +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,1408 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import { getPlatform } from '../utils/platform.js';
|
|
5
|
+
import { logForDebugging } from '../utils/debug.js';
|
|
6
|
+
/**
|
|
7
|
+
* Dangerous files that should be protected from writes.
|
|
8
|
+
* These files can be used for code execution or data exfiltration.
|
|
9
|
+
*/
|
|
10
|
+
export const DANGEROUS_FILES = [
|
|
11
|
+
'.gitconfig',
|
|
12
|
+
'.gitmodules',
|
|
13
|
+
'.bashrc',
|
|
14
|
+
'.bash_profile',
|
|
15
|
+
'.zshrc',
|
|
16
|
+
'.zprofile',
|
|
17
|
+
'.profile',
|
|
18
|
+
'.ripgreprc',
|
|
19
|
+
'.mcp.json',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Dangerous directories that should be protected from writes.
|
|
23
|
+
* These directories contain sensitive configuration or executable files.
|
|
24
|
+
*/
|
|
25
|
+
export const DANGEROUS_DIRECTORIES = ['.git', '.vscode', '.idea'];
|
|
26
|
+
/**
|
|
27
|
+
* Get the list of dangerous directories to deny writes to.
|
|
28
|
+
* Excludes .git since we need it writable for git operations -
|
|
29
|
+
* instead we block specific paths within .git (hooks and config).
|
|
30
|
+
*/
|
|
31
|
+
export function getDangerousDirectories() {
|
|
32
|
+
return [
|
|
33
|
+
...DANGEROUS_DIRECTORIES.filter(d => d !== '.git'),
|
|
34
|
+
'.claude/commands',
|
|
35
|
+
'.claude/agents',
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Normalizes a path for case-insensitive comparison.
|
|
40
|
+
* This prevents bypassing security checks using mixed-case paths on case-insensitive
|
|
41
|
+
* filesystems (macOS/Windows) like `.cLauDe/Settings.locaL.json`.
|
|
42
|
+
*
|
|
43
|
+
* We always normalize to lowercase regardless of platform for consistent security.
|
|
44
|
+
* @param path The path to normalize
|
|
45
|
+
* @returns The lowercase path for safe comparison
|
|
46
|
+
*/
|
|
47
|
+
export function normalizeCaseForComparison(pathStr) {
|
|
48
|
+
return pathStr.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `p` is `dir` itself or lies beneath it, by path segment ('/xy' is not under
|
|
52
|
+
* '/x'); root-aware, since '/' + '/' is a prefix of nothing.
|
|
53
|
+
*/
|
|
54
|
+
export function isAtOrUnder(p, dir) {
|
|
55
|
+
return p === dir || p.startsWith(dir === '/' ? '/' : dir + '/');
|
|
56
|
+
}
|
|
57
|
+
/** `p` lies strictly beneath `dir` (isAtOrUnder, excluding `dir` itself). */
|
|
58
|
+
export function isStrictlyUnder(p, dir) {
|
|
59
|
+
return p !== dir && isAtOrUnder(p, dir);
|
|
60
|
+
}
|
|
61
|
+
/** The proper ancestors of an absolute POSIX path, nearest first, ending at '/'. */
|
|
62
|
+
export function* properAncestors(absolutePath) {
|
|
63
|
+
for (let slash = absolutePath.lastIndexOf('/'); slash > 0; slash = absolutePath.lastIndexOf('/', slash - 1)) {
|
|
64
|
+
yield absolutePath.slice(0, slash);
|
|
65
|
+
}
|
|
66
|
+
if (absolutePath !== '/')
|
|
67
|
+
yield '/';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The spellings that name `candidatePath` for a mount comparison: as spelled,
|
|
71
|
+
* plus with every symlink resolved when that differs. A path that cannot be
|
|
72
|
+
* resolved (dangling, vanished) is named by its spelling alone.
|
|
73
|
+
*/
|
|
74
|
+
export function pathSpellings(candidatePath) {
|
|
75
|
+
try {
|
|
76
|
+
const resolved = fs.realpathSync(candidatePath);
|
|
77
|
+
if (resolved !== candidatePath)
|
|
78
|
+
return [candidatePath, resolved];
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Dangling or vanished: only the spelling names it.
|
|
82
|
+
}
|
|
83
|
+
return [candidatePath];
|
|
84
|
+
}
|
|
85
|
+
/** An fs error that means the name resolves to no file — it is missing, or
|
|
86
|
+
* the path cannot name one at all — as opposed to one that means a file is
|
|
87
|
+
* there but could not be looked at (EACCES, EPERM, EIO, anything
|
|
88
|
+
* unrecognised). */
|
|
89
|
+
export function isAbsenceErrno(err) {
|
|
90
|
+
const code = err?.code;
|
|
91
|
+
return (code === 'ENOENT' ||
|
|
92
|
+
code === 'ENOTDIR' ||
|
|
93
|
+
code === 'ELOOP' ||
|
|
94
|
+
code === 'ENAMETOOLONG');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if a path pattern contains glob characters
|
|
98
|
+
*/
|
|
99
|
+
export function containsGlobChars(pathPattern) {
|
|
100
|
+
return (pathPattern.includes('*') ||
|
|
101
|
+
pathPattern.includes('?') ||
|
|
102
|
+
pathPattern.includes('[') ||
|
|
103
|
+
pathPattern.includes(']'));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Windows-specific glob-char check. `[` and `]` are NOT
|
|
107
|
+
* metachars here — they are legal in Win32 filenames, so a
|
|
108
|
+
* literal `C:\app\[prod].env` must route to the literal-path
|
|
109
|
+
* branch, not glob expansion (where it would match nothing and
|
|
110
|
+
* be silently dropped). Only `*` and `?` trigger expansion.
|
|
111
|
+
*/
|
|
112
|
+
export function containsGlobCharsWin(p) {
|
|
113
|
+
return p.includes('*') || p.includes('?');
|
|
114
|
+
}
|
|
115
|
+
/** Platform-appropriate glob-char check. */
|
|
116
|
+
export function containsGlobCharsForPlatform(p) {
|
|
117
|
+
return getPlatform() === 'windows'
|
|
118
|
+
? containsGlobCharsWin(p)
|
|
119
|
+
: containsGlobChars(p);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Strip the Win32 `\\?\` extended-path prefix so the residue is
|
|
123
|
+
* a conventional absolute path (drive-letter or UNC) with no `?`
|
|
124
|
+
* for the glob-char check to misclassify. `\\?\UNC\srv\share\f`
|
|
125
|
+
* → `\\srv\share\f`; `\\?\C:\f` → `C:\f`; anything else → input.
|
|
126
|
+
* The UNC marker is matched case-insensitively (Windows accepts
|
|
127
|
+
* `\\?\unc\…` in any casing; a case-sensitive check would fall
|
|
128
|
+
* through to the 4-char strip and yield a cwd-relative residue).
|
|
129
|
+
*/
|
|
130
|
+
export function stripExtendedPathPrefix(p) {
|
|
131
|
+
if (/^\\\\\?\\unc\\/i.test(p))
|
|
132
|
+
return '\\\\' + p.slice(8);
|
|
133
|
+
if (p.startsWith('\\\\?\\'))
|
|
134
|
+
return p.slice(4);
|
|
135
|
+
return p;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* True for a Windows UNC path in any spelling — `\\server\share\…`,
|
|
139
|
+
* extended-length `\\?\UNC\server\share\…`, device-namespace
|
|
140
|
+
* `\\.\UNC\server\share\…` (all any casing, either separator).
|
|
141
|
+
* Delegates path-form normalization to
|
|
142
|
+
* `path.win32.toNamespacedPath` — every UNC spelling canonicalizes
|
|
143
|
+
* to `\\?\UNC\…` — so the check is "namespaced form starts with
|
|
144
|
+
* `\\?\UNC\` (or `\\.\UNC\`)". Drive-local forms (`C:\…`,
|
|
145
|
+
* `\\?\C:\…`), other device paths (`\\.\pipe\…`), relative paths
|
|
146
|
+
* (resolved against a local cwd), and server-only `\\srv` (no
|
|
147
|
+
* share) are all false.
|
|
148
|
+
*
|
|
149
|
+
* The broker uses this to skip `stat`/`realpath` on UNC **literals**
|
|
150
|
+
* (see {@link normalizePathForSandbox}): any such call is an SMB
|
|
151
|
+
* request carrying the **real user's** NTLM credentials to whatever
|
|
152
|
+
* host the path names — a forced-auth / path-encoded-exfil channel
|
|
153
|
+
* if the path is model-influenced. Literals pass through raw
|
|
154
|
+
* (resolution failures surface at `srt-win` stamp/grant time); a
|
|
155
|
+
* UNC **glob** still walks the share with real-user credentials —
|
|
156
|
+
* the user consented by naming their own share in the config.
|
|
157
|
+
* Defense-in-depth: the primary embedder already gates
|
|
158
|
+
* model-provided cwd/paths upstream.
|
|
159
|
+
*/
|
|
160
|
+
export function isUncPath(p) {
|
|
161
|
+
const ns = path.win32.toNamespacedPath(p);
|
|
162
|
+
// Already-namespaced input passes through `toNamespacedPath`
|
|
163
|
+
// verbatim (casing and separators preserved), so match the UNC
|
|
164
|
+
// marker case-insensitively with either separator. `[?.]` also
|
|
165
|
+
// catches the device-namespace `\\.\UNC\…` form — that is a real
|
|
166
|
+
// network access, not a local device.
|
|
167
|
+
return /^[\\/]{2}[?.][\\/]unc[\\/]/i.test(ns);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Remove trailing /** glob suffix from a path pattern
|
|
171
|
+
* Used to normalize path patterns since /** just means "directory and everything under it"
|
|
172
|
+
*/
|
|
173
|
+
export function removeTrailingGlobSuffix(pathPattern) {
|
|
174
|
+
const stripped = pathPattern.replace(/\/\*\*$/, '');
|
|
175
|
+
return stripped || '/';
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Check if a symlink resolution crosses expected path boundaries.
|
|
179
|
+
*
|
|
180
|
+
* When resolving symlinks for sandbox path normalization, we need to ensure
|
|
181
|
+
* the resolved path doesn't unexpectedly broaden the scope. This function
|
|
182
|
+
* returns true if the resolved path is an ancestor of the original path
|
|
183
|
+
* or resolves to a system root, which would indicate the symlink points
|
|
184
|
+
* outside expected boundaries.
|
|
185
|
+
*
|
|
186
|
+
* @param originalPath - The original path before symlink resolution
|
|
187
|
+
* @param resolvedPath - The path after fs.realpathSync() resolution
|
|
188
|
+
* @returns true if the resolved path is outside expected boundaries
|
|
189
|
+
*/
|
|
190
|
+
export function isSymlinkOutsideBoundary(originalPath, resolvedPath) {
|
|
191
|
+
const normalizedOriginal = path.normalize(originalPath);
|
|
192
|
+
const normalizedResolved = path.normalize(resolvedPath);
|
|
193
|
+
// Same path after normalization - OK
|
|
194
|
+
if (normalizedResolved === normalizedOriginal) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
// Handle macOS /tmp -> /private/tmp canonical resolution
|
|
198
|
+
// This is a legitimate system symlink that should be allowed
|
|
199
|
+
// /tmp/claude -> /private/tmp/claude is OK
|
|
200
|
+
// /var/folders/... -> /private/var/folders/... is OK
|
|
201
|
+
if (normalizedOriginal.startsWith('/tmp/') &&
|
|
202
|
+
normalizedResolved === '/private' + normalizedOriginal) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
if (normalizedOriginal.startsWith('/var/') &&
|
|
206
|
+
normalizedResolved === '/private' + normalizedOriginal) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
// If resolved path is "/" it's outside expected boundaries
|
|
210
|
+
if (normalizedResolved === '/') {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
// If resolved path is very short (single component like /tmp, /usr, /var),
|
|
214
|
+
// it's likely outside expected boundaries
|
|
215
|
+
const resolvedParts = normalizedResolved.split('/').filter(Boolean);
|
|
216
|
+
if (resolvedParts.length <= 1) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
// If original path starts with resolved path, the resolved path is an ancestor
|
|
220
|
+
// e.g., /tmp/claude -> /tmp means the symlink points to a broader scope
|
|
221
|
+
if (normalizedOriginal.startsWith(normalizedResolved + '/')) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
// Also check the canonical form of the original path for macOS
|
|
225
|
+
// e.g., /tmp/claude should also be checked as /private/tmp/claude
|
|
226
|
+
let canonicalOriginal = normalizedOriginal;
|
|
227
|
+
if (normalizedOriginal.startsWith('/tmp/')) {
|
|
228
|
+
canonicalOriginal = '/private' + normalizedOriginal;
|
|
229
|
+
}
|
|
230
|
+
else if (normalizedOriginal.startsWith('/var/')) {
|
|
231
|
+
canonicalOriginal = '/private' + normalizedOriginal;
|
|
232
|
+
}
|
|
233
|
+
if (canonicalOriginal !== normalizedOriginal &&
|
|
234
|
+
canonicalOriginal.startsWith(normalizedResolved + '/')) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
// STRICT CHECK: Only allow resolutions that stay within the expected path tree
|
|
238
|
+
// The resolved path must either:
|
|
239
|
+
// 1. Start with the original path (deeper/same) - already covered by returning false below
|
|
240
|
+
// 2. Start with the canonical original (deeper/same under canonical form)
|
|
241
|
+
// 3. BE the canonical form of the original (e.g., /tmp/x -> /private/tmp/x)
|
|
242
|
+
// Any other resolution (e.g., /tmp/claude -> /Users/dworken) is outside expected bounds
|
|
243
|
+
const resolvedStartsWithOriginal = normalizedResolved.startsWith(normalizedOriginal + '/');
|
|
244
|
+
const resolvedStartsWithCanonical = canonicalOriginal !== normalizedOriginal &&
|
|
245
|
+
normalizedResolved.startsWith(canonicalOriginal + '/');
|
|
246
|
+
const resolvedIsCanonical = canonicalOriginal !== normalizedOriginal &&
|
|
247
|
+
normalizedResolved === canonicalOriginal;
|
|
248
|
+
// If resolved path is not within expected tree, it's outside boundary
|
|
249
|
+
if (!resolvedIsCanonical &&
|
|
250
|
+
!resolvedStartsWithOriginal &&
|
|
251
|
+
!resolvedStartsWithCanonical) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
// Allow resolution to same directory level or deeper within expected tree
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Expand a leading `~` to the home directory. Handles bare `~`,
|
|
259
|
+
* `~/…`, and (on Windows only) the `~\…` form so callers don't each
|
|
260
|
+
* open-code the variants. `~\` is gated to Windows because `\` is a
|
|
261
|
+
* valid POSIX filename byte — `~\foo` is a legal relative filename
|
|
262
|
+
* on Linux/macOS and must NOT tilde-expand there.
|
|
263
|
+
*/
|
|
264
|
+
export function expandTilde(p) {
|
|
265
|
+
if (p === '~')
|
|
266
|
+
return homedir();
|
|
267
|
+
if (p.startsWith('~/') ||
|
|
268
|
+
(process.platform === 'win32' && p.startsWith('~\\'))) {
|
|
269
|
+
return homedir() + p.slice(1);
|
|
270
|
+
}
|
|
271
|
+
return p;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Expand Windows-style `%USERPROFILE%` / `%HOMEDRIVE%` / `%HOMEPATH%`
|
|
275
|
+
* references to the real user's home directory. Case-insensitive;
|
|
276
|
+
* idempotent. Applied by {@link normalizePathForSandbox}'s Windows
|
|
277
|
+
* pre-processing so every filesystem-config path field
|
|
278
|
+
* (`allowRead`/`allowWrite`/`denyRead`/`denyWrite`) accepts these
|
|
279
|
+
* forms uniformly.
|
|
280
|
+
*
|
|
281
|
+
* `%HOMEPATH%` is drive-RELATIVE (`\Users\name`) and `%HOMEDRIVE%` is
|
|
282
|
+
* the drive-only (`C:`) — the split matches how cmd.exe defines them,
|
|
283
|
+
* so `%HOMEDRIVE%%HOMEPATH%` composes to the full home path.
|
|
284
|
+
*/
|
|
285
|
+
export function expandWindowsEnvRefs(p) {
|
|
286
|
+
const home = homedir();
|
|
287
|
+
const drive = /^[A-Za-z]:/.test(home) ? home.slice(0, 2) : '';
|
|
288
|
+
const homePath = drive ? home.slice(2) : home;
|
|
289
|
+
return p
|
|
290
|
+
.replace(/%USERPROFILE%/gi, home)
|
|
291
|
+
.replace(/%HOMEDRIVE%/gi, drive)
|
|
292
|
+
.replace(/%HOMEPATH%/gi, homePath);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Runs of `/` collapsed to one and `/./` components dropped, leaving the rest
|
|
296
|
+
* of the spelling (a trailing `/` or `/.`, a `..`) to the caller. POSIX only.
|
|
297
|
+
*/
|
|
298
|
+
function collapseInteriorSpellings(pathPattern) {
|
|
299
|
+
return pathPattern.replace(/\/{2,}/g, '/').replace(/\/\.(?=\/)/g, '');
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Says so when a `..` reaches a backend unfolded — realpath could not resolve
|
|
303
|
+
* the path (absent, or unreadable), and folding `..` lexically here could aim
|
|
304
|
+
* the rule past a symlink at a file the kernel would never reach. Debug-only
|
|
305
|
+
* (`SRT_DEBUG`), so a rule that matches nothing is silent by default. Called
|
|
306
|
+
* at every return of {@link normalizePathForSandbox} that can carry one, glob
|
|
307
|
+
* spellings included.
|
|
308
|
+
*/
|
|
309
|
+
function warnIfParentRefUnfolded(normalizedPath) {
|
|
310
|
+
if (getPlatform() !== 'windows' &&
|
|
311
|
+
/(?:^|\/)\.\.(?:\/|$)/.test(normalizedPath)) {
|
|
312
|
+
logForDebugging(`[Sandbox] "${normalizedPath}" could not be resolved and still contains ` +
|
|
313
|
+
`a ".." component, so a rule spelled this way may not match.`, { level: 'warn' });
|
|
314
|
+
}
|
|
315
|
+
return normalizedPath;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Normalize a path for use in sandbox configurations
|
|
319
|
+
* Handles:
|
|
320
|
+
* - Tilde (~) expansion for home directory
|
|
321
|
+
* - Relative paths (./foo, ../foo, etc.) converted to absolute
|
|
322
|
+
* - POSIX: '//' runs, '/./' components and a trailing '/' or '/.' collapsed
|
|
323
|
+
* - Symlinks are resolved to their real paths for non-glob patterns
|
|
324
|
+
* - Glob patterns preserve wildcards after path normalization
|
|
325
|
+
*
|
|
326
|
+
* Returns the absolute path with symlinks resolved (or normalized glob pattern)
|
|
327
|
+
*
|
|
328
|
+
* `opts.literal` marks a path that names one file or directory rather
|
|
329
|
+
* than matching several: one the library computed itself, or a caller
|
|
330
|
+
* spelling that carried no glob character — resolving such a spelling can
|
|
331
|
+
* splice in a cwd or home directory whose own name does. The glob
|
|
332
|
+
* branches are skipped for it, so a component like `a[b` is resolved and
|
|
333
|
+
* later compiled as the name it is. A spelling the caller wrote with `*`,
|
|
334
|
+
* `?` or `[…]` in it keeps the character sniffing: there the brackets are
|
|
335
|
+
* the glob syntax it asked for. The interior collapse below is not one of
|
|
336
|
+
* the glob branches: `//` and `/./` are dead spellings either way.
|
|
337
|
+
*/
|
|
338
|
+
export function normalizePathForSandbox(pathPattern, opts) {
|
|
339
|
+
const isGlobSpelling = (p) => !opts?.literal && containsGlobCharsForPlatform(p);
|
|
340
|
+
// Windows pre-processing: expand `%USERPROFILE%` / `%HOMEDRIVE%` /
|
|
341
|
+
// `%HOMEPATH%`, strip the `\\?\` / `\\?\UNC\` extended prefix (its
|
|
342
|
+
// `?` is a literal, not a glob char), and uppercase the drive
|
|
343
|
+
// letter so `c:\…` and `C:\…` normalize identically.
|
|
344
|
+
if (getPlatform() === 'windows') {
|
|
345
|
+
pathPattern = stripExtendedPathPrefix(expandWindowsEnvRefs(pathPattern));
|
|
346
|
+
if (/^[a-z]:/.test(pathPattern)) {
|
|
347
|
+
pathPattern = pathPattern[0].toUpperCase() + pathPattern.slice(1);
|
|
348
|
+
}
|
|
349
|
+
// UNC literal: return as-is (separators normalised only) — no
|
|
350
|
+
// stat/realpath. A UNC *glob* falls through to the glob walk
|
|
351
|
+
// below (user-trusted share). See {@link isUncPath}.
|
|
352
|
+
if (isUncPath(pathPattern) && !isGlobSpelling(pathPattern)) {
|
|
353
|
+
return path.win32.normalize(pathPattern);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// POSIX: strip trailing slashes from non-glob spellings before any
|
|
357
|
+
// resolution. Consumers on the Linux and macOS paths compare spellings by
|
|
358
|
+
// exact match and `path + '/'` prefixes — which a preserved slash silently
|
|
359
|
+
// defeats ('<dir>//') — and the realpath-acceptance checks below treat a
|
|
360
|
+
// slash-only difference as a mismatch. A Seatbelt `subpath` filter is the
|
|
361
|
+
// one place the two spellings really are interchangeable: a `literal`
|
|
362
|
+
// filter and a glob regex ending '/$' match nothing when the slash is
|
|
363
|
+
// there, and a bwrap bind tolerates it only for a directory (a slashed
|
|
364
|
+
// file path fails ENOTDIR at mount). Glob spellings are left untouched: a
|
|
365
|
+
// slash after a glob segment is semantic ('/x/*/' compiles to a different
|
|
366
|
+
// regex than '/x/*'). That regex matches nothing, which an allow may
|
|
367
|
+
// harmlessly be — so an allow keeps the spelling, while the same spelling
|
|
368
|
+
// as a deny is rejected at config validation (see sandbox-config.ts). On
|
|
369
|
+
// Windows a trailing separator is the directory marker for absent deny
|
|
370
|
+
// targets (srt#404) and must survive.
|
|
371
|
+
if (getPlatform() !== 'windows' &&
|
|
372
|
+
pathPattern.endsWith('/') &&
|
|
373
|
+
!isGlobSpelling(pathPattern)) {
|
|
374
|
+
pathPattern = pathPattern.replace(/\/+$/, '') || '/';
|
|
375
|
+
}
|
|
376
|
+
let normalizedPath = expandTilde(pathPattern);
|
|
377
|
+
// A pattern with no tilde to expand and no root is resolved against the
|
|
378
|
+
// working directory; path.resolve covers './', '../', '.' and a bare
|
|
379
|
+
// relative name alike.
|
|
380
|
+
if (normalizedPath === pathPattern && !path.isAbsolute(pathPattern)) {
|
|
381
|
+
normalizedPath = path.resolve(process.cwd(), pathPattern);
|
|
382
|
+
}
|
|
383
|
+
// POSIX: collapse the interior spellings realpath would have removed, on the
|
|
384
|
+
// EXPANDED path — the trailing strip above runs before expansion and only
|
|
385
|
+
// ever touches a trailing run, and tilde expansion can put a run back
|
|
386
|
+
// (HOME='/home/u/' turns '~/x' into '/home/u//x'). Glob spellings need it
|
|
387
|
+
// for the same reason: '~/.aws//*.pem' compiles to a regex holding '//'.
|
|
388
|
+
//
|
|
389
|
+
// It matters on macOS: Seatbelt compares the kernel's canonical path, so a
|
|
390
|
+
// filter spelled with '//' or '/./' matches nothing, silently — which for a
|
|
391
|
+
// deny is exactly the absent-target case the deny exists for. bwrap
|
|
392
|
+
// tolerates the spelling, and the Linux backend rebuilds its destinations
|
|
393
|
+
// with path.dirname/join, so that argv was already right.
|
|
394
|
+
//
|
|
395
|
+
// Lexical only, and deliberately not path.normalize/path.resolve: those
|
|
396
|
+
// also fold '..', which through a symlinked component aims the rule at a
|
|
397
|
+
// different file than the kernel would reach. An absolute spelling's '..' is
|
|
398
|
+
// left to realpath below; a relative one was already folded lexically by the
|
|
399
|
+
// path.resolve above (pre-existing).
|
|
400
|
+
if (getPlatform() !== 'windows') {
|
|
401
|
+
normalizedPath = collapseInteriorSpellings(normalizedPath);
|
|
402
|
+
}
|
|
403
|
+
// For glob patterns, resolve symlinks for the directory portion only
|
|
404
|
+
if (isGlobSpelling(normalizedPath)) {
|
|
405
|
+
// Extract the static directory prefix before glob characters
|
|
406
|
+
// (on Windows, `[`/`]` are literal so only split on `*`/`?`).
|
|
407
|
+
const splitRe = getPlatform() === 'windows' ? /[*?]/ : /[*?[\]]/;
|
|
408
|
+
const staticPrefix = normalizedPath.split(splitRe)[0];
|
|
409
|
+
if (staticPrefix && staticPrefix !== '/') {
|
|
410
|
+
// Get the directory containing the glob pattern
|
|
411
|
+
// If staticPrefix ends with /, remove it to get the directory
|
|
412
|
+
const baseDir = staticPrefix.endsWith('/')
|
|
413
|
+
? staticPrefix.slice(0, -1)
|
|
414
|
+
: path.dirname(staticPrefix);
|
|
415
|
+
// Try to resolve symlinks for the base directory
|
|
416
|
+
try {
|
|
417
|
+
const resolvedBaseDir = fs.realpathSync(baseDir);
|
|
418
|
+
// Validate that resolution stays within expected boundaries
|
|
419
|
+
if (!isSymlinkOutsideBoundary(baseDir, resolvedBaseDir)) {
|
|
420
|
+
// Reconstruct the pattern with the resolved directory
|
|
421
|
+
const patternSuffix = normalizedPath.slice(baseDir.length);
|
|
422
|
+
return warnIfParentRefUnfolded(resolvedBaseDir + patternSuffix);
|
|
423
|
+
}
|
|
424
|
+
// If resolution would broaden scope, keep original pattern
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
// If directory doesn't exist or can't be resolved, keep the original pattern
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return warnIfParentRefUnfolded(normalizedPath);
|
|
431
|
+
}
|
|
432
|
+
// A trailing '/' or '/.' is not semantic outside a glob, and the empty
|
|
433
|
+
// string is not the filesystem root: an empty HOME makes expandTilde('~')
|
|
434
|
+
// empty, and '' || '/' would turn `allowWrite: ['~']` into a whole-
|
|
435
|
+
// filesystem grant.
|
|
436
|
+
if (getPlatform() !== 'windows' && normalizedPath !== '') {
|
|
437
|
+
normalizedPath =
|
|
438
|
+
normalizedPath.replace(/\/\.$/, '').replace(/\/+$/, '') || '/';
|
|
439
|
+
}
|
|
440
|
+
// Resolve symlinks to real paths to avoid bwrap issues
|
|
441
|
+
// Validate that the resolution stays within expected boundaries
|
|
442
|
+
try {
|
|
443
|
+
const resolvedPath = fs.realpathSync(normalizedPath);
|
|
444
|
+
// A symlink pointing outside the expected boundaries (e.g. to a parent
|
|
445
|
+
// directory) keeps the original path.
|
|
446
|
+
if (!isSymlinkOutsideBoundary(normalizedPath, resolvedPath)) {
|
|
447
|
+
normalizedPath = resolvedPath;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
// Absent, or unreadable: keep the normalized spelling.
|
|
452
|
+
}
|
|
453
|
+
return warnIfParentRefUnfolded(normalizedPath);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* What the sandbox itself needs writable: the child's stdio and the TMPDIR it
|
|
457
|
+
* is handed (generateProxyEnvVars). Kept whatever is read-denied.
|
|
458
|
+
*/
|
|
459
|
+
const SANDBOX_OWN_WRITE_PATHS = [
|
|
460
|
+
'/dev/stdout',
|
|
461
|
+
'/dev/stderr',
|
|
462
|
+
'/dev/null',
|
|
463
|
+
'/dev/tty',
|
|
464
|
+
'/dev/dtracehelper',
|
|
465
|
+
'/dev/autofs_nowait',
|
|
466
|
+
'/tmp/claude',
|
|
467
|
+
'/private/tmp/claude',
|
|
468
|
+
];
|
|
469
|
+
/**
|
|
470
|
+
* Directories under the home directory made writable as a convenience the
|
|
471
|
+
* caller never asked for. Every entry is subject to the read-rule check in
|
|
472
|
+
* {@link getDefaultWritePaths}.
|
|
473
|
+
*/
|
|
474
|
+
const HOME_CONVENIENCE_WRITE_DIRS = [
|
|
475
|
+
'.npm/_logs',
|
|
476
|
+
'.claude/debug',
|
|
477
|
+
];
|
|
478
|
+
/**
|
|
479
|
+
* Get recommended system paths that should be writable for commands to work properly
|
|
480
|
+
*
|
|
481
|
+
* WARNING: These default paths are intentionally broad for compatibility but may
|
|
482
|
+
* allow access to files from other processes. In highly security-sensitive
|
|
483
|
+
* environments, you should configure more restrictive write paths.
|
|
484
|
+
*
|
|
485
|
+
* With no argument this is the whole list. Given the read rules of a
|
|
486
|
+
* filesystem policy, a home convenience directory (~/.npm/_logs,
|
|
487
|
+
* ~/.claude/debug) is left out when a `denyRead` entry names it or a
|
|
488
|
+
* directory above it: kept, it would be bound back over that deny on Linux
|
|
489
|
+
* (readable and writable again) and stay writable on macOS, so the explicit
|
|
490
|
+
* denyRead wins over the implicit write allow. It is kept when an `allowRead`
|
|
491
|
+
* entry beneath that deny re-opens it, because the caller has already made it
|
|
492
|
+
* readable. A caller who wants it writable regardless lists it in
|
|
493
|
+
* `allowWrite`. What the sandbox itself needs (stdio, /tmp/claude) is never
|
|
494
|
+
* left out.
|
|
495
|
+
*
|
|
496
|
+
* Pass the entries as configured, not expanded. `dir/**` counts as `dir`,
|
|
497
|
+
* and a glob covers a directory when it matches that directory or one above
|
|
498
|
+
* it; nothing is listed from disk. On Linux, where the backend expands globs
|
|
499
|
+
* against the disk, two things follow: a glob that matches nothing there
|
|
500
|
+
* still counts (which only ever drops a convenience path), and a glob whose
|
|
501
|
+
* match is a symlink to one of these directories is not seen. A glob
|
|
502
|
+
* `allowRead` entry is not counted as re-opening anything.
|
|
503
|
+
*/
|
|
504
|
+
export function getDefaultWritePaths(readRules) {
|
|
505
|
+
const home = homedir();
|
|
506
|
+
const keptDirs = !readRules || readRules.denyRead.length === 0
|
|
507
|
+
? HOME_CONVENIENCE_WRITE_DIRS
|
|
508
|
+
: homeDirsNotReadDenied(home, readRules.denyRead, readRules.allowRead);
|
|
509
|
+
return [
|
|
510
|
+
...SANDBOX_OWN_WRITE_PATHS,
|
|
511
|
+
...keptDirs.map(rel => path.join(home, rel)),
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* The {@link HOME_CONVENIENCE_WRITE_DIRS} no `denyRead` entry covers, or
|
|
516
|
+
* that an `allowRead` entry beneath the covering deny re-opens.
|
|
517
|
+
*/
|
|
518
|
+
function homeDirsNotReadDenied(home, denyRead, allowRead = []) {
|
|
519
|
+
// Rules are compared as normalizePathForSandbox spells them, and on macOS
|
|
520
|
+
// that resolves /tmp and /var to /private/... for a path that exists. A
|
|
521
|
+
// convenience directory may not exist yet, so its second spelling is built
|
|
522
|
+
// from the home directory, which does.
|
|
523
|
+
const homes = [
|
|
524
|
+
...new Set([home, normalizePathForSandbox(home, { literal: true })]),
|
|
525
|
+
];
|
|
526
|
+
const denies = denyRead.map(entry => readRuleCovers(entry));
|
|
527
|
+
const reopened = allowRead
|
|
528
|
+
.map(entry => removeTrailingGlobSuffix(entry))
|
|
529
|
+
.filter(entry => !containsGlobCharsForPlatform(entry))
|
|
530
|
+
.map(entry => normalizePathForSandbox(entry, { literal: true }));
|
|
531
|
+
return HOME_CONVENIENCE_WRITE_DIRS.filter(rel => {
|
|
532
|
+
const spellings = homes.map(h => path.join(h, rel));
|
|
533
|
+
return !denies.some(denyCovers => spellings.some(denyCovers) &&
|
|
534
|
+
!reopened.some(allow => denyCovers(allow) && spellings.some(s => isAtOrUnder(s, allow))));
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Whether a read rule covers a path: the path is the rule's own or lies
|
|
539
|
+
* beneath it. `dir/**` is `dir`, and a glob covers whatever
|
|
540
|
+
* {@link denyGlobRegex} matches.
|
|
541
|
+
*
|
|
542
|
+
* Pattern or name is decided on what the caller wrote, before the spelling
|
|
543
|
+
* is resolved: `*`, `?` and `[…]` there are the syntax it asked for, while
|
|
544
|
+
* resolving splices in a cwd or home directory that may carry those
|
|
545
|
+
* characters in its own name. A spelling without them is normalized as the
|
|
546
|
+
* name it is.
|
|
547
|
+
*/
|
|
548
|
+
function readRuleCovers(entry) {
|
|
549
|
+
const stripped = removeTrailingGlobSuffix(entry);
|
|
550
|
+
if (containsGlobCharsForPlatform(stripped)) {
|
|
551
|
+
try {
|
|
552
|
+
const regex = new RegExp(denyGlobRegex(normalizePathForSandbox(stripped)));
|
|
553
|
+
return p => regex.test(p);
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
// Brackets that do not form a valid class. The entry may be a literal
|
|
557
|
+
// file name, so it is compared as one.
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
const rule = normalizePathForSandbox(stripped, { literal: true });
|
|
561
|
+
return p => isAtOrUnder(p, rule);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Generate proxy environment variables for sandboxed processes
|
|
565
|
+
*/
|
|
566
|
+
/**
|
|
567
|
+
* Per-tool trust-store env vars set to the TLS-termination CA cert path so
|
|
568
|
+
* HTTPS clients in the sandboxed child accept proxy-minted certs.
|
|
569
|
+
*/
|
|
570
|
+
export const CA_TRUST_VARS = [
|
|
571
|
+
'NODE_EXTRA_CA_CERTS',
|
|
572
|
+
'SSL_CERT_FILE',
|
|
573
|
+
'CURL_CA_BUNDLE',
|
|
574
|
+
'REQUESTS_CA_BUNDLE',
|
|
575
|
+
'PIP_CERT',
|
|
576
|
+
'GIT_SSL_CAINFO',
|
|
577
|
+
'AWS_CA_BUNDLE',
|
|
578
|
+
'CARGO_HTTP_CAINFO',
|
|
579
|
+
'DENO_CERT',
|
|
580
|
+
// gcloud ignores SSL_CERT_FILE/REQUESTS_CA_BUNDLE; this is its dedicated
|
|
581
|
+
// override (maps to core/custom_ca_certs_file).
|
|
582
|
+
'CLOUDSDK_CORE_CUSTOM_CA_CERTS_FILE',
|
|
583
|
+
// Nix-built binaries are patched to read this instead of SSL_CERT_FILE, and
|
|
584
|
+
// it's typically pre-set to the Nix system bundle in the parent env, so we
|
|
585
|
+
// must override it explicitly.
|
|
586
|
+
'NIX_SSL_CERT_FILE',
|
|
587
|
+
];
|
|
588
|
+
export function generateProxyEnvVars(httpProxyPort, socksProxyPort, caCertPath, proxyAuthToken, skipTmpdir, encodedCommand) {
|
|
589
|
+
// When the proxy requires auth, embed the credential in the URL so clients
|
|
590
|
+
// send Proxy-Authorization automatically. Only the sandbox child sees this
|
|
591
|
+
// env, so the token never reaches host processes.
|
|
592
|
+
//
|
|
593
|
+
// The username carries the per-command encodedCommand so the proxy can
|
|
594
|
+
// attribute denials to a specific invocation (see
|
|
595
|
+
// SandboxViolationStore). Standard base64 is percent-encoded in the URL so
|
|
596
|
+
// `+/=` survive userinfo parsing; clients URL-decode before building the
|
|
597
|
+
// Basic header / RFC 1929 frame, so the proxy receives the raw base64.
|
|
598
|
+
const userRaw = proxyUsernameFor(encodedCommand);
|
|
599
|
+
const userPct = userRaw === PROXY_AUTH_USER ? userRaw : encodeURIComponent(userRaw);
|
|
600
|
+
const auth = proxyAuthToken ? `${userPct}:${proxyAuthToken}@` : '';
|
|
601
|
+
const envVars = [`SANDBOX_RUNTIME=1`];
|
|
602
|
+
// TMPDIR is overridden so temp-file writers land in a path the FS sandbox
|
|
603
|
+
// allows (getDefaultWritePaths). When filesystem policy is disabled
|
|
604
|
+
// (writeConfig === undefined → skipTmpdir), the host TMPDIR is already
|
|
605
|
+
// writable and /tmp/claude may not exist, so leave it untouched.
|
|
606
|
+
// CLAUDE_CODE_TMPDIR is the current name; CLAUDE_TMPDIR is kept for
|
|
607
|
+
// backwards compatibility (#141).
|
|
608
|
+
if (!skipTmpdir) {
|
|
609
|
+
const tmpdir = process.env.CLAUDE_CODE_TMPDIR ||
|
|
610
|
+
process.env.CLAUDE_TMPDIR ||
|
|
611
|
+
'/tmp/claude';
|
|
612
|
+
envVars.push(`TMPDIR=${tmpdir}`);
|
|
613
|
+
}
|
|
614
|
+
// When TLS termination is configured, the child only ever sees proxy-minted
|
|
615
|
+
// certs signed by the configured CA. Point the common per-tool trust-store
|
|
616
|
+
// env vars at it so HTTPS clients accept those certs.
|
|
617
|
+
if (caCertPath) {
|
|
618
|
+
for (const v of CA_TRUST_VARS) {
|
|
619
|
+
envVars.push(`${v}=${caCertPath}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
// If no proxy ports provided, return minimal env vars
|
|
623
|
+
if (!httpProxyPort && !socksProxyPort) {
|
|
624
|
+
return envVars;
|
|
625
|
+
}
|
|
626
|
+
// Always set NO_PROXY to exclude localhost and private networks from
|
|
627
|
+
// proxying. *.local is intentionally absent: under network restriction the
|
|
628
|
+
// child has no usable resolver/routes (bwrap --unshare-net on Linux,
|
|
629
|
+
// loopback-only under seatbelt), so a NO_PROXY match makes the client try
|
|
630
|
+
// direct getaddrinfo() and fail. Routing .local hostnames through the proxy
|
|
631
|
+
// lets the parent resolve them (e.g. Kubernetes *.svc.cluster.local).
|
|
632
|
+
const noProxyAddresses = [
|
|
633
|
+
'localhost',
|
|
634
|
+
'127.0.0.1',
|
|
635
|
+
'::1',
|
|
636
|
+
'169.254.0.0/16', // Link-local
|
|
637
|
+
'10.0.0.0/8', // Private network
|
|
638
|
+
'172.16.0.0/12', // Private network
|
|
639
|
+
'192.168.0.0/16', // Private network
|
|
640
|
+
].join(',');
|
|
641
|
+
envVars.push(`NO_PROXY=${noProxyAddresses}`);
|
|
642
|
+
envVars.push(`no_proxy=${noProxyAddresses}`);
|
|
643
|
+
if (httpProxyPort) {
|
|
644
|
+
envVars.push(`HTTP_PROXY=http://${auth}localhost:${httpProxyPort}`);
|
|
645
|
+
envVars.push(`HTTPS_PROXY=http://${auth}localhost:${httpProxyPort}`);
|
|
646
|
+
// Lowercase versions for compatibility with some tools
|
|
647
|
+
envVars.push(`http_proxy=http://${auth}localhost:${httpProxyPort}`);
|
|
648
|
+
envVars.push(`https_proxy=http://${auth}localhost:${httpProxyPort}`);
|
|
649
|
+
if (proxyAuthToken) {
|
|
650
|
+
// Pre-send Basic so git never gets a 407 and never invokes a
|
|
651
|
+
// credential helper for the proxy URL (Windows GCM intercepts the
|
|
652
|
+
// challenge and the URL-embedded password doesn't survive it).
|
|
653
|
+
envVars.push(`GIT_CONFIG_PARAMETERS='http.proxyAuthMethod=basic'`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
// The URL to advertise to clients that need a general-purpose,
|
|
657
|
+
// CONNECT-capable proxy. The mux serves HTTP CONNECT and SOCKS on the same
|
|
658
|
+
// advertised port, so http:// works for everyone: clients that only speak
|
|
659
|
+
// CONNECT get a URL they understand, and anything that actually speaks
|
|
660
|
+
// SOCKS to it still reaches the SOCKS handler. Falls back to socks5h://
|
|
661
|
+
// only when no HTTP proxy port exists, which no current caller configures.
|
|
662
|
+
const connectProxyUrl = httpProxyPort
|
|
663
|
+
? `http://${auth}localhost:${httpProxyPort}`
|
|
664
|
+
: `socks5h://${auth}localhost:${socksProxyPort}`;
|
|
665
|
+
// ALL_PROXY: prefer the HTTP proxy URL over SOCKS. httpx (and similar
|
|
666
|
+
// Python clients) eagerly import `socksio` at client construction when
|
|
667
|
+
// ALL_PROXY is a socks5h:// URL and crash with ImportError in envs that
|
|
668
|
+
// lack the package — before any bytes hit the wire, so the mux's
|
|
669
|
+
// protocol sniffing can't help.
|
|
670
|
+
envVars.push(`ALL_PROXY=${connectProxyUrl}`);
|
|
671
|
+
envVars.push(`all_proxy=${connectProxyUrl}`);
|
|
672
|
+
// gRPC-based tools. gRPC C-core (every google-cloud-* Python client, and
|
|
673
|
+
// grpc-js) only understands HTTP CONNECT proxies. Given a socks5h:// URL it
|
|
674
|
+
// logs "'socks5h' scheme not supported in proxy URI", ignores the var, and
|
|
675
|
+
// resolves the target directly via c-ares — which the sandbox blocks, so
|
|
676
|
+
// the client dies with "address lookup failed / Could not contact DNS
|
|
677
|
+
// servers" instead of falling back to https_proxy. Not gated on
|
|
678
|
+
// socksProxyPort: the value no longer depends on it, and a gRPC client in
|
|
679
|
+
// an HTTP-only sandbox needs this var just as much.
|
|
680
|
+
envVars.push(`GRPC_PROXY=${connectProxyUrl}`);
|
|
681
|
+
envVars.push(`grpc_proxy=${connectProxyUrl}`);
|
|
682
|
+
if (socksProxyPort) {
|
|
683
|
+
// Configure Git to use SSH through the proxy so DNS resolution happens outside the sandbox.
|
|
684
|
+
// ControlMaster/ControlPath are disabled because SSH connection multiplexing breaks inside
|
|
685
|
+
// the sandbox: the mux socket path from the user's ssh config (typically under ~/.ssh) is
|
|
686
|
+
// not an allowed Unix socket path, and OpenSSH treats a mux listener bind failure as fatal
|
|
687
|
+
// even with ControlMaster=auto — it exits right after authentication, before running the
|
|
688
|
+
// git command. Command-line options take precedence over ssh_config, so this neutralizes
|
|
689
|
+
// any user ControlMaster setup. ControlPath=none is needed in addition to ControlMaster=no:
|
|
690
|
+
// with ControlMaster=no alone, ssh still tries to connect to an existing mux socket at the
|
|
691
|
+
// configured ControlPath.
|
|
692
|
+
const sshMuxOverride = '-o ControlMaster=no -o ControlPath=none';
|
|
693
|
+
const platform = getPlatform();
|
|
694
|
+
if (platform === 'macos') {
|
|
695
|
+
// macOS: use BSD nc SOCKS5 proxy support (-X 5 -x). nc has no SOCKS5
|
|
696
|
+
// auth, so when proxyAuthToken is set, git-over-ssh fails at the SOCKS
|
|
697
|
+
// handshake — use git-over-https (HTTP_PROXY carries the credential).
|
|
698
|
+
envVars.push(`GIT_SSH_COMMAND=ssh ${sshMuxOverride} -o ProxyCommand='nc -X 5 -x localhost:${socksProxyPort} %h %p'`);
|
|
699
|
+
}
|
|
700
|
+
else if (platform === 'linux' && httpProxyPort) {
|
|
701
|
+
// Linux: use socat HTTP CONNECT via the HTTP proxy bridge.
|
|
702
|
+
// socat is already a required Linux sandbox dependency, and PROXY: is
|
|
703
|
+
// portable across all socat versions (unlike SOCKS5-CONNECT which needs >= 1.8.0).
|
|
704
|
+
const socatAuth = proxyAuthToken
|
|
705
|
+
? `,proxyauth=${userRaw}:${proxyAuthToken}`
|
|
706
|
+
: '';
|
|
707
|
+
envVars.push(`GIT_SSH_COMMAND=ssh ${sshMuxOverride} -o ProxyCommand='socat - PROXY:localhost:%h:%p,proxyport=${httpProxyPort}${socatAuth}'`);
|
|
708
|
+
}
|
|
709
|
+
// FTP proxy support (use socks5h for DNS resolution through proxy).
|
|
710
|
+
// Deliberately not connectProxyUrl: given an http:// ftp_proxy, curl does
|
|
711
|
+
// not CONNECT-tunnel by default, it gateways the transfer as
|
|
712
|
+
// `GET ftp://host/path HTTP/1.1` to the proxy — which the mux does not
|
|
713
|
+
// implement, and an env var can't ask curl for --proxytunnel. socks5h is
|
|
714
|
+
// transparent at the TCP layer, so it is the value that works here.
|
|
715
|
+
envVars.push(`FTP_PROXY=socks5h://${auth}localhost:${socksProxyPort}`);
|
|
716
|
+
envVars.push(`ftp_proxy=socks5h://${auth}localhost:${socksProxyPort}`);
|
|
717
|
+
// rsync proxy support — RSYNC_PROXY is host:port only, no userinfo. With
|
|
718
|
+
// proxy auth on, rsync via this var fails at the CONNECT (407); use SSH
|
|
719
|
+
// transport or wrap with proxychains instead.
|
|
720
|
+
envVars.push(`RSYNC_PROXY=localhost:${socksProxyPort}`);
|
|
721
|
+
// Database tools NOTE: Most database clients don't have built-in proxy support
|
|
722
|
+
// You typically need to use SSH tunneling or a SOCKS wrapper like tsocks/proxychains
|
|
723
|
+
// Docker CLI uses HTTP for the API
|
|
724
|
+
// This makes Docker use the HTTP proxy for registry operations
|
|
725
|
+
envVars.push(`DOCKER_HTTP_PROXY=http://${auth}localhost:${httpProxyPort || socksProxyPort}`);
|
|
726
|
+
envVars.push(`DOCKER_HTTPS_PROXY=http://${auth}localhost:${httpProxyPort || socksProxyPort}`);
|
|
727
|
+
// Google Cloud SDK - has specific proxy settings.
|
|
728
|
+
// proxy/type names the protocol the *proxy* speaks, not the traffic it
|
|
729
|
+
// tunnels. Our HTTP CONNECT proxy carries TLS to Google APIs, so the
|
|
730
|
+
// correct value is "http" (gcloud only accepts http, http_no_tunnel,
|
|
731
|
+
// socks4, socks5; "https" is rejected at startup).
|
|
732
|
+
if (httpProxyPort) {
|
|
733
|
+
envVars.push(`CLOUDSDK_PROXY_TYPE=http`);
|
|
734
|
+
envVars.push(`CLOUDSDK_PROXY_ADDRESS=localhost`);
|
|
735
|
+
envVars.push(`CLOUDSDK_PROXY_PORT=${httpProxyPort}`);
|
|
736
|
+
if (proxyAuthToken) {
|
|
737
|
+
envVars.push(`CLOUDSDK_PROXY_USERNAME=${userRaw}`);
|
|
738
|
+
envVars.push(`CLOUDSDK_PROXY_PASSWORD=${proxyAuthToken}`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
// kubectl, the AWS CLI, the Azure CLI, Terraform and gRPC read the
|
|
742
|
+
// standard vars already emitted; nothing tool-specific is needed.
|
|
743
|
+
}
|
|
744
|
+
// Do not set HTTP_PROXY/HTTPS_PROXY to SOCKS URLs in the SOCKS-only path:
|
|
745
|
+
// most HTTP clients reject socks*:// in those vars. ALL_PROXY (above)
|
|
746
|
+
// already carries the route for clients that read it.
|
|
747
|
+
return envVars;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* `safe.directory` entries above this count collapse to a single
|
|
751
|
+
* `safe.directory=*`. Keeps `GIT_CONFIG_COUNT` (and the argv it rides
|
|
752
|
+
* on) bounded when the safe-dir set is wide.
|
|
753
|
+
*/
|
|
754
|
+
const SAFE_DIRECTORY_WILDCARD_THRESHOLD = 8;
|
|
755
|
+
/**
|
|
756
|
+
* Build the `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_<n>` /
|
|
757
|
+
* `GIT_CONFIG_VALUE_<n>` env-var set for the sandboxed child.
|
|
758
|
+
*
|
|
759
|
+
* Emits:
|
|
760
|
+
* - `safe.directory=<dir>` for each entry in `safeDirs` (or one
|
|
761
|
+
* `safe.directory=*` when the list is long) — inside the sandbox
|
|
762
|
+
* the working tree is owned by a different user (Windows: the
|
|
763
|
+
* real user vs `srt-sandbox`; Linux: unmapped uid under
|
|
764
|
+
* `bwrap --unshare-user`), so git refuses with "detected dubious
|
|
765
|
+
* ownership" without it.
|
|
766
|
+
* - `http.schannelUseSSLCAInfo=true` and
|
|
767
|
+
* `http.schannelCheckRevoke=false` when `schannelCa` (Windows
|
|
768
|
+
* only) — makes git's schannel backend honor `GIT_SSL_CAINFO`
|
|
769
|
+
* without `-c http.sslBackend=openssl`. Revocation is disabled
|
|
770
|
+
* because CryptoAPI CRL/OCSP fetches ignore proxy env and would
|
|
771
|
+
* be WFP-fenced.
|
|
772
|
+
*
|
|
773
|
+
* Composes with an existing `GIT_CONFIG_COUNT` in `baseEnv` by
|
|
774
|
+
* continuing its numbering; the returned `GIT_CONFIG_COUNT` is the
|
|
775
|
+
* new total. `baseEnv` should reflect what the child will actually
|
|
776
|
+
* see: on Windows the two-hop launch means the broker's own
|
|
777
|
+
* `process.env` never reaches the child, so `baseEnv` is the caller
|
|
778
|
+
* overlay (`WindowsSandboxParams.setEnvVars`); on Linux/macOS the
|
|
779
|
+
* child inherits `process.env`, so callers use
|
|
780
|
+
* {@link buildPosixGitSafeDirEnv} (which folds in `process.env`,
|
|
781
|
+
* `unsetEnvVars`, and `setEnvVars`).
|
|
782
|
+
*
|
|
783
|
+
* Paths are emitted with forward slashes so the value survives
|
|
784
|
+
* msys2's env conversion untouched and native git accepts it (a
|
|
785
|
+
* no-op on POSIX paths).
|
|
786
|
+
*/
|
|
787
|
+
export function buildGitConfigEnv(opts) {
|
|
788
|
+
// An explicit `GIT_CONFIG_COUNT=0` in baseEnv is an opt-out ("no
|
|
789
|
+
// env-level git config") — respect it rather than overwriting.
|
|
790
|
+
if (opts.baseEnv?.GIT_CONFIG_COUNT === '0')
|
|
791
|
+
return {};
|
|
792
|
+
const parsed = Number.parseInt(opts.baseEnv?.GIT_CONFIG_COUNT ?? '', 10);
|
|
793
|
+
const start = Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
794
|
+
let n = start;
|
|
795
|
+
const out = {};
|
|
796
|
+
const emit = (key, value) => {
|
|
797
|
+
out[`GIT_CONFIG_KEY_${n}`] = key;
|
|
798
|
+
out[`GIT_CONFIG_VALUE_${n}`] = value;
|
|
799
|
+
n++;
|
|
800
|
+
};
|
|
801
|
+
const dirs = [
|
|
802
|
+
...new Set(opts.safeDirs
|
|
803
|
+
.filter((d) => !!d)
|
|
804
|
+
.map(d => {
|
|
805
|
+
const fwd = d.replace(/\\/g, '/');
|
|
806
|
+
const stripped = fwd.replace(/\/+$/, '');
|
|
807
|
+
// Don't strip the trailing slash off a bare root: `C:`
|
|
808
|
+
// is drive-relative-cwd (git wants `C:/`), and `` is
|
|
809
|
+
// git's list-reset sentinel for safe.directory (would
|
|
810
|
+
// wipe preceding entries) — POSIX `/` must stay `/`.
|
|
811
|
+
if (stripped === '' || /^[A-Za-z]:$/.test(stripped)) {
|
|
812
|
+
return `${stripped}/`;
|
|
813
|
+
}
|
|
814
|
+
return stripped;
|
|
815
|
+
})),
|
|
816
|
+
];
|
|
817
|
+
if (dirs.length > SAFE_DIRECTORY_WILDCARD_THRESHOLD) {
|
|
818
|
+
emit('safe.directory', '*');
|
|
819
|
+
}
|
|
820
|
+
else {
|
|
821
|
+
// git matches safe.directory against the REPO TOP-LEVEL exactly,
|
|
822
|
+
// so a workspace root doesn't cover a nested repo. Emit both the
|
|
823
|
+
// exact path and the `<dir>/*` glob (git ≥2.46) so any repo
|
|
824
|
+
// at-or-under a granted dir is trusted. Roots keep their trailing
|
|
825
|
+
// `/`; don't double it in the glob (`//*` never wildmatches).
|
|
826
|
+
for (const d of dirs) {
|
|
827
|
+
emit('safe.directory', d);
|
|
828
|
+
emit('safe.directory', d.endsWith('/') ? `${d}*` : `${d}/*`);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (opts.schannelCa) {
|
|
832
|
+
emit('http.schannelUseSSLCAInfo', 'true');
|
|
833
|
+
emit('http.schannelCheckRevoke', 'false');
|
|
834
|
+
}
|
|
835
|
+
if (n === start)
|
|
836
|
+
return {};
|
|
837
|
+
out.GIT_CONFIG_COUNT = String(n);
|
|
838
|
+
return out;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* POSIX-side wrapper over {@link buildGitConfigEnv} that constructs
|
|
842
|
+
* the correct `baseEnv` for a Linux/macOS sandbox: the child inherits
|
|
843
|
+
* `process.env` under bwrap/sandbox-exec, then `unsetEnvVars` are
|
|
844
|
+
* dropped and `setEnvVars` overlaid — so numbering must continue from
|
|
845
|
+
* whatever `GIT_CONFIG_COUNT` survives that. Shared by
|
|
846
|
+
* `wrapCommandWithSandbox{Linux,MacOS}`.
|
|
847
|
+
*/
|
|
848
|
+
export function buildPosixGitSafeDirEnv(opts) {
|
|
849
|
+
const baseEnv = {
|
|
850
|
+
GIT_CONFIG_COUNT: process.env.GIT_CONFIG_COUNT,
|
|
851
|
+
};
|
|
852
|
+
for (const k of opts.unsetEnvVars ?? [])
|
|
853
|
+
delete baseEnv[k];
|
|
854
|
+
Object.assign(baseEnv, opts.setEnvVars ?? {});
|
|
855
|
+
return buildGitConfigEnv({ safeDirs: opts.safeDirs, baseEnv });
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* How much of an attribution key rides the carriers. A key is cut to this
|
|
859
|
+
* many characters before encoding, so two commands that share this much of
|
|
860
|
+
* a prefix share a key.
|
|
861
|
+
*/
|
|
862
|
+
export const SANDBOXED_COMMAND_KEY_LENGTH = 100;
|
|
863
|
+
/**
|
|
864
|
+
* The attribution key for an invocation: the caller's `commandId`, or the
|
|
865
|
+
* command itself when there is no usable id.
|
|
866
|
+
*/
|
|
867
|
+
export function attributionKeyFor(command, commandId) {
|
|
868
|
+
// Falsy, not `=== undefined`: every carrier drops an empty attribution, and
|
|
869
|
+
// a JavaScript caller's `null` would throw in encodeSandboxedCommand.
|
|
870
|
+
return !commandId ? command : commandId;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Encode a command for sandbox monitoring
|
|
874
|
+
* Truncates to SANDBOXED_COMMAND_KEY_LENGTH chars and base64 encodes to
|
|
875
|
+
* avoid parsing issues
|
|
876
|
+
*/
|
|
877
|
+
export function encodeSandboxedCommand(command) {
|
|
878
|
+
const truncatedCommand = command.slice(0, SANDBOXED_COMMAND_KEY_LENGTH);
|
|
879
|
+
return Buffer.from(truncatedCommand).toString('base64');
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Decode a base64-encoded command from sandbox monitoring
|
|
883
|
+
*/
|
|
884
|
+
export function decodeSandboxedCommand(encodedCommand) {
|
|
885
|
+
return Buffer.from(encodedCommand, 'base64').toString('utf8');
|
|
886
|
+
}
|
|
887
|
+
/** Base proxy username; the auth token is the credential, this is a label. */
|
|
888
|
+
export const PROXY_AUTH_USER = 'srt';
|
|
889
|
+
/** RFC 1929 caps a SOCKS5 username at 255 bytes. */
|
|
890
|
+
const MAX_PROXY_USERNAME_BYTES = 255;
|
|
891
|
+
/**
|
|
892
|
+
* The longest encodedCommand a carrier this process mints can hold: what is
|
|
893
|
+
* left of the username budget after `srt.`. Every carrier is bounded far more
|
|
894
|
+
* loosely than that (an HTTP proxy header budget is kilobytes), so a longer
|
|
895
|
+
* attribution field was not minted here and is stored by nobody.
|
|
896
|
+
*/
|
|
897
|
+
export const MAX_ENCODED_COMMAND_BYTES = MAX_PROXY_USERNAME_BYTES - Buffer.byteLength(`${PROXY_AUTH_USER}.`);
|
|
898
|
+
/**
|
|
899
|
+
* Build the proxy username for a sandboxed command: `srt.<encodedCommand>`
|
|
900
|
+
* so the proxy can attribute a denial to the invocation that triggered it,
|
|
901
|
+
* or bare `srt` when there is nothing to attribute. A multibyte command whose
|
|
902
|
+
* 100-code-unit truncation still base64s past the username budget would fail
|
|
903
|
+
* the SOCKS handshake, so fall back to bare `srt` (attribution is lost,
|
|
904
|
+
* connectivity is not).
|
|
905
|
+
*/
|
|
906
|
+
export function proxyUsernameFor(encodedCommand) {
|
|
907
|
+
if (!encodedCommand)
|
|
908
|
+
return PROXY_AUTH_USER;
|
|
909
|
+
const user = `${PROXY_AUTH_USER}.${encodedCommand}`;
|
|
910
|
+
return Buffer.byteLength(user) <= MAX_PROXY_USERNAME_BYTES
|
|
911
|
+
? user
|
|
912
|
+
: PROXY_AUTH_USER;
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Inverse of {@link proxyUsernameFor}: extract the encodedCommand suffix
|
|
916
|
+
* from `srt.<encodedCommand>`, or undefined for bare `srt` / anything else.
|
|
917
|
+
* The username is client-controlled inside the sandbox, so a forged suffix
|
|
918
|
+
* can only misattribute a denial in the violation report — it cannot
|
|
919
|
+
* authenticate (the token does that) or reach another command's data. A
|
|
920
|
+
* suffix past {@link MAX_ENCODED_COMMAND_BYTES} is longer than this process
|
|
921
|
+
* can mint, so it is dropped rather than stored: the denial is still
|
|
922
|
+
* recorded, unattributed.
|
|
923
|
+
*/
|
|
924
|
+
export function encodedCommandFromProxyUser(username) {
|
|
925
|
+
if (!username || !username.startsWith(`${PROXY_AUTH_USER}.`))
|
|
926
|
+
return undefined;
|
|
927
|
+
const suffix = username.slice(PROXY_AUTH_USER.length + 1);
|
|
928
|
+
if (!suffix || Buffer.byteLength(suffix) > MAX_ENCODED_COMMAND_BYTES) {
|
|
929
|
+
return undefined;
|
|
930
|
+
}
|
|
931
|
+
return suffix;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Convert a glob pattern to a regular expression
|
|
935
|
+
*
|
|
936
|
+
* This implements gitignore-style pattern matching to match the behavior of the
|
|
937
|
+
* `ignore` library used by the permission system.
|
|
938
|
+
*
|
|
939
|
+
* Supported patterns:
|
|
940
|
+
* - * matches any characters except / (e.g., *.ts matches foo.ts but not foo/bar.ts)
|
|
941
|
+
* - ** matches any characters including / (e.g., src/**\/*.ts matches all .ts files in src/)
|
|
942
|
+
* - ? matches any single character except / (e.g., file?.txt matches file1.txt)
|
|
943
|
+
* - [abc] matches any character in the set (e.g., file[0-9].txt matches file3.txt)
|
|
944
|
+
*
|
|
945
|
+
* Exported for testing and shared between macOS sandbox profiles and Linux glob expansion.
|
|
946
|
+
*/
|
|
947
|
+
export function globToRegex(globPattern) {
|
|
948
|
+
return ('^' +
|
|
949
|
+
globPattern
|
|
950
|
+
// Escape regex special characters (except glob chars * ? [ ])
|
|
951
|
+
.replace(/[.^$+{}()|\\]/g, '\\$&')
|
|
952
|
+
// Escape unclosed brackets (no matching ])
|
|
953
|
+
.replace(/\[([^\]]*?)$/g, '\\[$1')
|
|
954
|
+
// Convert glob patterns to regex (order matters - ** before *)
|
|
955
|
+
.replace(/\*\*\//g, '__GLOBSTAR_SLASH__') // Placeholder for **/
|
|
956
|
+
.replace(/\*\*/g, '__GLOBSTAR__') // Placeholder for **
|
|
957
|
+
.replace(/\*/g, '[^/]*') // * matches anything except /
|
|
958
|
+
.replace(/\?/g, '[^/]') // ? matches single character except /
|
|
959
|
+
// Restore placeholders
|
|
960
|
+
.replace(/__GLOBSTAR_SLASH__/g, '(.*/)?') // **/ matches zero or more dirs
|
|
961
|
+
.replace(/__GLOBSTAR__/g, '.*') + // ** matches anything including /
|
|
962
|
+
'$');
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Regex for a glob used in a DENY rule: {@link globToRegex} plus an optional
|
|
966
|
+
* `/…` tail, so the deny covers everything beneath each match the way
|
|
967
|
+
* `subpath` does for literals. Callers strip a trailing `/**` before the
|
|
968
|
+
* pattern gets here (removeTrailingGlobSuffix), so `**\/secrets/**` arrives
|
|
969
|
+
* as `**\/secrets` and, matched exactly, would deny only the directory
|
|
970
|
+
* vnode while `secrets/key` stayed readable. This is what the Linux backend
|
|
971
|
+
* already does (a deny masks the whole subtree). Only ever widens a deny.
|
|
972
|
+
*
|
|
973
|
+
* Takes a whole pattern, so every character in it is glob syntax: right for
|
|
974
|
+
* a spelling the caller wrote, which is what {@link readRuleCovers} passes.
|
|
975
|
+
* A pattern the library anchored at a directory of its own goes through the
|
|
976
|
+
* macOS `denyGlobEntryRegex`, which splices that directory back in escaped
|
|
977
|
+
* and calls this for the tail.
|
|
978
|
+
*/
|
|
979
|
+
export function denyGlobRegex(normalizedGlob) {
|
|
980
|
+
// globToRegex() always returns '^…$'.
|
|
981
|
+
return globToRegex(normalizedGlob).slice(0, -1) + '(/.*)?$';
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Expand a glob pattern into the concrete paths matching it.
|
|
985
|
+
*
|
|
986
|
+
* Used on Linux (where bubblewrap doesn't support glob patterns
|
|
987
|
+
* natively) and Windows (point-in-time expansion before `srt-win
|
|
988
|
+
* acl stamp`). A symlink is a match in its own right and is not
|
|
989
|
+
* descended into; {@link walkGlobPattern} is the read-deny expansion's
|
|
990
|
+
* richer view of the same walk.
|
|
991
|
+
*
|
|
992
|
+
* @param globPath - A path pattern containing glob characters (e.g., ~/test/*.env)
|
|
993
|
+
* @returns Array of absolute paths matching the glob pattern
|
|
994
|
+
*/
|
|
995
|
+
export function expandGlobPattern(globPath, opts = {}) {
|
|
996
|
+
return walkGlobPattern(globPath, opts).matches;
|
|
997
|
+
}
|
|
998
|
+
function globPieces(pattern, flags) {
|
|
999
|
+
// globToRegex rewrites its own placeholders where a pattern spells one.
|
|
1000
|
+
if (pattern.includes('__GLOBSTAR'))
|
|
1001
|
+
return undefined;
|
|
1002
|
+
const sourceOf = (text) => globToRegex(text).slice(1, -1);
|
|
1003
|
+
const pieces = [];
|
|
1004
|
+
let unclosed = 0;
|
|
1005
|
+
// A bracket expression first, the way a regular expression reads one:
|
|
1006
|
+
// everything up to the first `]`. Then a run of `*` with the separator
|
|
1007
|
+
// after it, since `**/` is one thing to globToRegex.
|
|
1008
|
+
const tokenizer = /(\[[^\]]*\])|(\*+)(\/?)|(\/)|([^[*/]+|\[)/g;
|
|
1009
|
+
for (const match of pattern.matchAll(tokenizer)) {
|
|
1010
|
+
const [text, bracket, stars, separatorAfterStars, separator] = match;
|
|
1011
|
+
if (bracket !== undefined) {
|
|
1012
|
+
if (/[*?]/.test(bracket))
|
|
1013
|
+
return undefined;
|
|
1014
|
+
const source = sourceOf(bracket);
|
|
1015
|
+
pieces.push(new RegExp(`^${source}$`, flags).test('/')
|
|
1016
|
+
? { source, canBeSeparator: true }
|
|
1017
|
+
: { source });
|
|
1018
|
+
}
|
|
1019
|
+
else if (stars !== undefined) {
|
|
1020
|
+
// globToRegex takes `**/` first, so the last two of a run before a
|
|
1021
|
+
// separator go with it. What is left of the run is `**` pairs from the
|
|
1022
|
+
// left and then a `*`; a `.*` takes in a `.*` or `[^/]*` beside it.
|
|
1023
|
+
const withSeparator = separatorAfterStars === '/' && stars.length >= 2;
|
|
1024
|
+
const left = stars.length - (withSeparator ? 2 : 0);
|
|
1025
|
+
if (left >= 2)
|
|
1026
|
+
pieces.push('any');
|
|
1027
|
+
else if (left === 1)
|
|
1028
|
+
pieces.push({ source: '[^/]*' });
|
|
1029
|
+
if (withSeparator)
|
|
1030
|
+
pieces.push('anyDirs');
|
|
1031
|
+
else if (separatorAfterStars === '/')
|
|
1032
|
+
pieces.push('/');
|
|
1033
|
+
}
|
|
1034
|
+
else if (separator !== undefined) {
|
|
1035
|
+
pieces.push('/');
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
// globToRegex escapes the first `[` that nothing closes and no other:
|
|
1039
|
+
// a second one reads on into whatever a later wildcard is rewritten to.
|
|
1040
|
+
if (text === '[' && unclosed++ > 0)
|
|
1041
|
+
return undefined;
|
|
1042
|
+
pieces.push({ source: sourceOf(text) });
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
// `(.*/)?` adds nothing before another one or before a `.*`.
|
|
1046
|
+
return pieces.filter((piece, i) => piece !== 'anyDirs' ||
|
|
1047
|
+
(pieces[i + 1] !== 'anyDirs' && pieces[i + 1] !== 'any'));
|
|
1048
|
+
}
|
|
1049
|
+
function globPositions(normalizedPattern, flags) {
|
|
1050
|
+
const regex = new RegExp(globToRegex(normalizedPattern), flags);
|
|
1051
|
+
const directoryForm = removeTrailingGlobSuffix(normalizedPattern);
|
|
1052
|
+
const directoryRegex = directoryForm !== normalizedPattern
|
|
1053
|
+
? new RegExp(globToRegex(directoryForm), flags)
|
|
1054
|
+
: undefined;
|
|
1055
|
+
const unsplit = {
|
|
1056
|
+
splits: false,
|
|
1057
|
+
start: [0],
|
|
1058
|
+
next: () => [0],
|
|
1059
|
+
matches: (_positions, _name, spelled) => regex.test(spelled),
|
|
1060
|
+
matchesDirectoryForm: (_positions, _name, spelled) => directoryRegex?.test(spelled) === true,
|
|
1061
|
+
};
|
|
1062
|
+
const states = [];
|
|
1063
|
+
const star = '[^/]*';
|
|
1064
|
+
/** The automaton of one pattern, as the position it starts at. */
|
|
1065
|
+
const build = (pieces) => {
|
|
1066
|
+
const memo = new Map();
|
|
1067
|
+
const globstar = (then) => states.push({ then }) - 1;
|
|
1068
|
+
/** The position of a component that starts at `pieces[i]`, after a
|
|
1069
|
+
* `[^/]*` when `lead`. */
|
|
1070
|
+
const componentAt = (i, lead) => {
|
|
1071
|
+
const key = `${i}${lead ? '*' : ''}`;
|
|
1072
|
+
const known = memo.get(key);
|
|
1073
|
+
if (known !== undefined)
|
|
1074
|
+
return known;
|
|
1075
|
+
if (!lead && pieces[i] === 'anyDirs') {
|
|
1076
|
+
const id = globstar(undefined);
|
|
1077
|
+
memo.set(key, id);
|
|
1078
|
+
states[id].then = componentAt(i + 1, false);
|
|
1079
|
+
return id;
|
|
1080
|
+
}
|
|
1081
|
+
if (!lead && pieces[i] === 'any' && i === pieces.length - 1) {
|
|
1082
|
+
const id = globstar(undefined);
|
|
1083
|
+
memo.set(key, id);
|
|
1084
|
+
return id;
|
|
1085
|
+
}
|
|
1086
|
+
const component = { edges: [] };
|
|
1087
|
+
const id = states.push(component) - 1;
|
|
1088
|
+
memo.set(key, id);
|
|
1089
|
+
const endsWith = (source, to) => {
|
|
1090
|
+
component.edges.push({ regex: new RegExp(`^${source}$`, flags), to });
|
|
1091
|
+
};
|
|
1092
|
+
let source = lead ? star : '';
|
|
1093
|
+
for (let j = i;; j++) {
|
|
1094
|
+
const piece = pieces[j];
|
|
1095
|
+
if (piece === undefined) {
|
|
1096
|
+
endsWith(source, undefined);
|
|
1097
|
+
break;
|
|
1098
|
+
}
|
|
1099
|
+
if (piece === '/') {
|
|
1100
|
+
endsWith(source, componentAt(j + 1, false));
|
|
1101
|
+
break;
|
|
1102
|
+
}
|
|
1103
|
+
if (piece === 'any') {
|
|
1104
|
+
// Spanning separators: `X*` / `**` / `*Y`. Or not: `X*Y`.
|
|
1105
|
+
endsWith(source + star, globstar(componentAt(j + 1, true)));
|
|
1106
|
+
source += star;
|
|
1107
|
+
}
|
|
1108
|
+
else if (piece === 'anyDirs') {
|
|
1109
|
+
// Spanning: `X*` / `**` / what follows. Or X run into it.
|
|
1110
|
+
endsWith(source + star, globstar(componentAt(j + 1, false)));
|
|
1111
|
+
}
|
|
1112
|
+
else if (piece.canBeSeparator) {
|
|
1113
|
+
endsWith(source, componentAt(j + 1, false));
|
|
1114
|
+
source += `(?!/)${piece.source}`;
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
source += piece.source;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return id;
|
|
1121
|
+
};
|
|
1122
|
+
return componentAt(0, false);
|
|
1123
|
+
};
|
|
1124
|
+
let starts;
|
|
1125
|
+
let firstOfDirectoryForm;
|
|
1126
|
+
try {
|
|
1127
|
+
const pieces = globPieces(normalizedPattern, flags);
|
|
1128
|
+
const directoryPieces = directoryRegex
|
|
1129
|
+
? globPieces(directoryForm, flags)
|
|
1130
|
+
: [];
|
|
1131
|
+
if (pieces === undefined || directoryPieces === undefined)
|
|
1132
|
+
return unsplit;
|
|
1133
|
+
starts = [build(pieces)];
|
|
1134
|
+
firstOfDirectoryForm = states.length;
|
|
1135
|
+
if (directoryRegex)
|
|
1136
|
+
starts.push(build(directoryPieces));
|
|
1137
|
+
}
|
|
1138
|
+
catch {
|
|
1139
|
+
// A piece of the pattern that is no regular expression on its own.
|
|
1140
|
+
return unsplit;
|
|
1141
|
+
}
|
|
1142
|
+
const open = (into, position) => {
|
|
1143
|
+
for (let p = position; p !== undefined && !into.has(p);) {
|
|
1144
|
+
into.add(p);
|
|
1145
|
+
const state = states[p];
|
|
1146
|
+
p = 'then' in state ? state.then : undefined;
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
const sorted = (positions) => [...positions].sort((x, y) => x - y);
|
|
1150
|
+
const endsAt = (positions, name, ofDirectoryForm) => positions.some(p => {
|
|
1151
|
+
if (p >= firstOfDirectoryForm !== ofDirectoryForm)
|
|
1152
|
+
return false;
|
|
1153
|
+
const state = states[p];
|
|
1154
|
+
return 'then' in state
|
|
1155
|
+
? state.then === undefined
|
|
1156
|
+
: state.edges.some(e => e.to === undefined && e.regex.test(name));
|
|
1157
|
+
});
|
|
1158
|
+
const start = new Set();
|
|
1159
|
+
for (const p of starts)
|
|
1160
|
+
open(start, p);
|
|
1161
|
+
return {
|
|
1162
|
+
splits: true,
|
|
1163
|
+
start: sorted(start),
|
|
1164
|
+
next: (positions, name) => {
|
|
1165
|
+
const next = new Set();
|
|
1166
|
+
for (const p of positions) {
|
|
1167
|
+
const state = states[p];
|
|
1168
|
+
if ('then' in state)
|
|
1169
|
+
open(next, p);
|
|
1170
|
+
else {
|
|
1171
|
+
for (const edge of state.edges) {
|
|
1172
|
+
if (edge.to !== undefined && edge.regex.test(name)) {
|
|
1173
|
+
open(next, edge.to);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return sorted(next);
|
|
1179
|
+
},
|
|
1180
|
+
matches: (positions, name) => endsAt(positions, name, false),
|
|
1181
|
+
matchesDirectoryForm: (positions, name) => endsAt(positions, name, true),
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* The literal directory a glob's walk starts from: the static prefix before
|
|
1186
|
+
* the pattern's first glob character, without its last path component when
|
|
1187
|
+
* that component is not a directory of its own. '' or '/' means the pattern
|
|
1188
|
+
* has no literal directory to start from (a wildcard in its first path
|
|
1189
|
+
* component), which {@link walkGlobPattern} refuses to expand.
|
|
1190
|
+
*
|
|
1191
|
+
* @param normalizedPattern - a pattern already through
|
|
1192
|
+
* {@link normalizePathForSandbox} (and, on Windows, {@link toForwardSlashes})
|
|
1193
|
+
*/
|
|
1194
|
+
export function globPatternBaseDir(normalizedPattern) {
|
|
1195
|
+
const staticPrefix = normalizedPattern.split(/[*?[\]]/)[0];
|
|
1196
|
+
if (!staticPrefix)
|
|
1197
|
+
return '';
|
|
1198
|
+
return staticPrefix.endsWith('/')
|
|
1199
|
+
? staticPrefix.slice(0, -1)
|
|
1200
|
+
: path.dirname(staticPrefix);
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Normalize to `/` separators so {@link globToRegex} (which treats `/` as the
|
|
1204
|
+
* segment boundary) and the static-prefix split work on Windows paths. Gated
|
|
1205
|
+
* to win32: `\` is a valid filename byte on POSIX, so rewriting it there
|
|
1206
|
+
* would change the path (e.g. a Linux directory literally named `app\creds`).
|
|
1207
|
+
*/
|
|
1208
|
+
export function toForwardSlashes(s) {
|
|
1209
|
+
return process.platform === 'win32' ? s.replace(/\\/g, '/') : s;
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* The walk behind {@link expandGlobPattern}: one listing of the pattern's
|
|
1213
|
+
* static prefix, filtered by `globPath` and, with `withDirectoryForm`, by
|
|
1214
|
+
* `globPath` without its trailing `/**`, with the symlinks seen recorded.
|
|
1215
|
+
* With `followSymlinkedDirectories` it also lists through a symlinked
|
|
1216
|
+
* directory and reports every match where it really lives.
|
|
1217
|
+
*/
|
|
1218
|
+
export function walkGlobPattern(globPath, opts = {}) {
|
|
1219
|
+
const walk = {
|
|
1220
|
+
baseLocation: '',
|
|
1221
|
+
matches: [],
|
|
1222
|
+
directoryMatches: [],
|
|
1223
|
+
symlinks: new Set(),
|
|
1224
|
+
uninspectableLinks: new Set(),
|
|
1225
|
+
unlisted: [],
|
|
1226
|
+
realOf: new Map(),
|
|
1227
|
+
};
|
|
1228
|
+
const normalizedPattern = toForwardSlashes(normalizePathForSandbox(globPath));
|
|
1229
|
+
const baseDir = globPatternBaseDir(normalizedPattern);
|
|
1230
|
+
if (baseDir === '' || baseDir === '/') {
|
|
1231
|
+
logForDebugging(`[Sandbox] Glob pattern has no literal directory to start from, skipping: ${globPath}`, { level: 'warn' });
|
|
1232
|
+
return walk;
|
|
1233
|
+
}
|
|
1234
|
+
// `s`: a name may hold a line terminator, which `.` alone does not match.
|
|
1235
|
+
const flags = opts.caseInsensitive ? 'is' : 's';
|
|
1236
|
+
const positions = globPositions(normalizedPattern, flags);
|
|
1237
|
+
if (opts.followSymlinkedDirectories && !positions.splits) {
|
|
1238
|
+
logForDebugging(`[Sandbox] Glob pattern ${globPath} cannot be followed one path component at a time, so it is matched against real paths only and not through symlinked directories`, { level: 'warn' });
|
|
1239
|
+
}
|
|
1240
|
+
/** The positions each real directory has been listed for. */
|
|
1241
|
+
const listedFor = new Map();
|
|
1242
|
+
/** Successful listings, by real directory: a second position reads the
|
|
1243
|
+
* same entries. */
|
|
1244
|
+
const listings = new Map();
|
|
1245
|
+
const pending = [];
|
|
1246
|
+
/** A filesystem call on a real path, and on a shorter name for it when that
|
|
1247
|
+
* fails. The real path crosses no link, so a long chain of them cannot
|
|
1248
|
+
* fail the call (ELOOP). */
|
|
1249
|
+
const onRealPath = (real, short, call) => {
|
|
1250
|
+
try {
|
|
1251
|
+
return call(real);
|
|
1252
|
+
}
|
|
1253
|
+
catch (err) {
|
|
1254
|
+
if (short === real)
|
|
1255
|
+
throw err;
|
|
1256
|
+
return call(short);
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
const linkTargets = new Map();
|
|
1260
|
+
const linkTargetOf = (linkPath, realLinkPath) => {
|
|
1261
|
+
const cached = linkTargets.get(realLinkPath);
|
|
1262
|
+
if (cached !== undefined)
|
|
1263
|
+
return cached;
|
|
1264
|
+
let target;
|
|
1265
|
+
try {
|
|
1266
|
+
target = onRealPath(realLinkPath, linkPath, p => ({
|
|
1267
|
+
isDirectory: fs.statSync(p).isDirectory(),
|
|
1268
|
+
real: fs.realpathSync(p),
|
|
1269
|
+
}));
|
|
1270
|
+
}
|
|
1271
|
+
catch (err) {
|
|
1272
|
+
target = isAbsenceErrno(err) ? 'absent' : 'uninspectable';
|
|
1273
|
+
}
|
|
1274
|
+
linkTargets.set(realLinkPath, target);
|
|
1275
|
+
return target;
|
|
1276
|
+
};
|
|
1277
|
+
let baseReal = baseDir;
|
|
1278
|
+
try {
|
|
1279
|
+
baseReal = fs.realpathSync(baseDir);
|
|
1280
|
+
}
|
|
1281
|
+
catch {
|
|
1282
|
+
// Not there, or a component of it cannot be resolved: list the spelling.
|
|
1283
|
+
}
|
|
1284
|
+
walk.baseLocation = baseReal;
|
|
1285
|
+
pending.push({
|
|
1286
|
+
dir: baseDir,
|
|
1287
|
+
real: baseReal,
|
|
1288
|
+
short: baseDir.length < baseReal.length ? baseDir : baseReal,
|
|
1289
|
+
positions: baseDir.split('/').reduce(positions.next, positions.start),
|
|
1290
|
+
});
|
|
1291
|
+
for (let frame = pending.pop(); frame !== undefined; frame = pending.pop()) {
|
|
1292
|
+
const { dir, real } = frame;
|
|
1293
|
+
let listed = listedFor.get(real);
|
|
1294
|
+
if (listed === undefined)
|
|
1295
|
+
listedFor.set(real, (listed = new Set()));
|
|
1296
|
+
// What a position finds beneath a directory does not depend on the
|
|
1297
|
+
// others it came with, so only the ones new to this directory are taken.
|
|
1298
|
+
const fresh = frame.positions.filter(p => !listed.has(p));
|
|
1299
|
+
if (fresh.length === 0)
|
|
1300
|
+
continue;
|
|
1301
|
+
for (const p of fresh)
|
|
1302
|
+
listed.add(p);
|
|
1303
|
+
let entries = listings.get(real);
|
|
1304
|
+
try {
|
|
1305
|
+
entries ?? (entries = onRealPath(real, frame.short, p => fs.readdirSync(p, { withFileTypes: true })));
|
|
1306
|
+
listings.set(real, entries);
|
|
1307
|
+
}
|
|
1308
|
+
catch (err) {
|
|
1309
|
+
const errorCode = err?.code;
|
|
1310
|
+
logForDebugging(`[Sandbox] Error listing ${dir} for glob pattern ${globPath}: ${err}`, { level: errorCode === 'ENOENT' ? 'info' : 'warn' });
|
|
1311
|
+
if (errorCode !== 'ENOENT') {
|
|
1312
|
+
walk.unlisted.push(dir);
|
|
1313
|
+
if (real !== dir)
|
|
1314
|
+
walk.realOf.set(dir, real);
|
|
1315
|
+
}
|
|
1316
|
+
continue;
|
|
1317
|
+
}
|
|
1318
|
+
for (const entry of entries) {
|
|
1319
|
+
const fullPath = path.join(dir, entry.name);
|
|
1320
|
+
const realPath = path.join(real, entry.name);
|
|
1321
|
+
const candidate = toForwardSlashes(fullPath);
|
|
1322
|
+
const isMatch = positions.matches(fresh, entry.name, candidate);
|
|
1323
|
+
if (isMatch)
|
|
1324
|
+
walk.matches.push(fullPath);
|
|
1325
|
+
if (entry.isDirectory()) {
|
|
1326
|
+
const beneath = positions.next(fresh, entry.name);
|
|
1327
|
+
const isDirectoryMatch = opts.withDirectoryForm === true &&
|
|
1328
|
+
positions.matchesDirectoryForm(fresh, entry.name, candidate);
|
|
1329
|
+
if (isDirectoryMatch)
|
|
1330
|
+
walk.directoryMatches.push(fullPath);
|
|
1331
|
+
if ((isMatch || isDirectoryMatch) && realPath !== fullPath) {
|
|
1332
|
+
walk.realOf.set(fullPath, realPath);
|
|
1333
|
+
}
|
|
1334
|
+
if (beneath.length > 0) {
|
|
1335
|
+
pending.push({
|
|
1336
|
+
dir: fullPath,
|
|
1337
|
+
real: realPath,
|
|
1338
|
+
short: path.join(frame.short, entry.name),
|
|
1339
|
+
positions: beneath,
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1342
|
+
continue;
|
|
1343
|
+
}
|
|
1344
|
+
if (!entry.isSymbolicLink()) {
|
|
1345
|
+
if (isMatch && realPath !== fullPath) {
|
|
1346
|
+
walk.realOf.set(fullPath, realPath);
|
|
1347
|
+
}
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
walk.symlinks.add(fullPath);
|
|
1351
|
+
// Only the read-deny expansion lists through a symlinked directory: it
|
|
1352
|
+
// has to cover what the pattern reaches by every name. The allowRead
|
|
1353
|
+
// expansion and the Windows ACL stamp take the link itself and stop
|
|
1354
|
+
// there, as the allow bind and the ACL they feed do — Windows does not
|
|
1355
|
+
// follow reparse points at all.
|
|
1356
|
+
if (!opts.followSymlinkedDirectories)
|
|
1357
|
+
continue;
|
|
1358
|
+
const isDirectoryFormCandidate = opts.withDirectoryForm === true &&
|
|
1359
|
+
positions.matchesDirectoryForm(fresh, entry.name, candidate);
|
|
1360
|
+
// A pattern that does not split is not listed through a link: no two
|
|
1361
|
+
// names for a directory can be told apart, so none but its own is
|
|
1362
|
+
// listed. A link that is itself a match still denies what it leads to.
|
|
1363
|
+
const beneath = positions.splits ? positions.next(fresh, entry.name) : [];
|
|
1364
|
+
if (!isMatch && !isDirectoryFormCandidate && beneath.length === 0) {
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
const shortPath = path.join(frame.short, entry.name);
|
|
1368
|
+
const target = linkTargetOf(shortPath, realPath);
|
|
1369
|
+
if (target === 'absent')
|
|
1370
|
+
continue;
|
|
1371
|
+
if (target === 'uninspectable') {
|
|
1372
|
+
// Where it leads is unknown, so it gets no real location and nothing
|
|
1373
|
+
// is listed through it — but it is still a match, and a deny
|
|
1374
|
+
// expansion covers it under its own spelling.
|
|
1375
|
+
walk.uninspectableLinks.add(fullPath);
|
|
1376
|
+
if (isDirectoryFormCandidate)
|
|
1377
|
+
walk.directoryMatches.push(fullPath);
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
if (isMatch)
|
|
1381
|
+
walk.realOf.set(fullPath, target.real);
|
|
1382
|
+
if (!target.isDirectory)
|
|
1383
|
+
continue;
|
|
1384
|
+
if (isDirectoryFormCandidate) {
|
|
1385
|
+
walk.directoryMatches.push(fullPath);
|
|
1386
|
+
walk.realOf.set(fullPath, target.real);
|
|
1387
|
+
}
|
|
1388
|
+
if (beneath.length === 0)
|
|
1389
|
+
continue;
|
|
1390
|
+
// A link that leads up — to this directory or above it, or to the
|
|
1391
|
+
// walk's base or above it — is not listed through: beneath it is a tree
|
|
1392
|
+
// the pattern was never aimed at (`/`, a home directory).
|
|
1393
|
+
if (isAtOrUnder(real, target.real) ||
|
|
1394
|
+
isAtOrUnder(baseReal, target.real)) {
|
|
1395
|
+
logForDebugging(`[Sandbox] Not following symlink ${fullPath} -> ${target.real} for glob pattern ${globPath}: it leads back up the tree`);
|
|
1396
|
+
continue;
|
|
1397
|
+
}
|
|
1398
|
+
pending.push({
|
|
1399
|
+
dir: target.real,
|
|
1400
|
+
real: target.real,
|
|
1401
|
+
short: shortPath.length < target.real.length ? shortPath : target.real,
|
|
1402
|
+
positions: beneath,
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return walk;
|
|
1407
|
+
}
|
|
1408
|
+
//# sourceMappingURL=sandbox-utils.js.map
|