mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-29 02:01:50 +08:00
6b8f36431b
* fix(security): harden usage script execution and Grok session log collection Three hardening fixes in v3.19.0 code: 1. **usage_script: cap JS runtime resources and execution time** `execute_usage_script` used a vanilla `Runtime::new()` with no limits, so a malicious or buggy script delivered via deeplink or synced DB could hang the backend thread forever with `while(true)`. Add `create_script_runtime()` enforcing a 5-second interrupt handler, 16 MiB memory limit, and 256 KiB stack limit. Regression test confirms an infinite-loop script is rejected within seconds instead of blocking. 2. **Grok session log: skip oversized files** `sync_single_grok_file` loaded the entire `updates.jsonl` into memory with no size cap. Add a 50 MiB limit and skip files that exceed it. 3. **Grok session log: bound directory traversal** `collect_files_named` recursed without depth limits and followed symlinks, so a symlink cycle under `~/.grok/sessions` caused a stack overflow. Add a 16-level depth limit and skip symlinks entirely. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ui): show hidden usage access token and user id in deeplink provider import dialog The provider import confirmation dialog parsed usageAccessToken and usageUserId from ccswitch:// URLs and persisted them in ProviderMeta.usage_script, but never rendered them. Users could not see these credentials before approving the import. - Add i18n keys for usageAccessToken/usageUserId in all locales. - Render both fields in the usage script section; mask the access token like usageApiKey. - Add a regression test verifying the dialog displays the masked token and the user id. Co-Authored-By: Claude <noreply@anthropic.com> * fix(security): bound Codex model catalog and proxy response bodies Two issues were found while auditing security boundaries: 1. **Codex model_catalog_json arbitrary file read** only checked the filename and accepted any absolute path. A malicious could point CC Switch at an external file (e.g. ) or a huge file to exhaust memory. - Require the resolved path to stay inside using a new helper (lexical, no filesystem calls). - Treat Unix-style absolute paths as absolute on Windows. - Cap catalog reads at 32 MiB. 2. **Unbounded proxy response bodies / compression bombs** Non-streaming responses and error responses were read with and fully decompressed without any byte limit, allowing a malicious upstream to OOM the backend. - Add with a 128 MiB ceiling. - Reject oversized bodies and oversized decompressed payloads with . - Map the new error variant into the Codex proxy error response. Regression tests cover: absolute-path containment, traversal rejection, oversized catalog file, oversized buffered/streamed proxy responses. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ci): set up pnpm via Corepack instead of pnpm/action-setup v6 pnpm/action-setup v6 installs pnpm through a two-step self-installer: it bootstraps the latest pnpm (11.7.0) via npm, then downloads the pinned version (10.12.3) from the npm registry to switch. When that second tarball fetch failed (error 23), the self-installer still reported "done" and crashed with ENOENT on @pnpm/linux-x64's package.json, failing the CI setup step. Replace the action with Node 20's bundled Corepack and pin the version once via package.json's packageManager field, so setup performs a single exact-version download with no floating bootstrap. This also lets release.yml drop its Windows ARM64 special case, since Corepack has no arch restrictions, and pins the same version for local dev. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(security): close review gaps in proxy body caps, deeplink dialog, catalog path Address maintainer review on the security PR: - Proxy: bound the four remaining unbounded forwarder read paths (non-2xx error body, failover pre-read, both 2xx error-envelope validators) with bytes_with_limit + bounded decompression. - Proxy: bytes_with_limit now accumulates Hyper/Reqwest/Streamed bodies chunk-by-chunk and aborts mid-stream instead of collecting the full body before comparing; Buffered keeps the post-hoc check. - Proxy: decompression is budgeted at the decoder (Read::take on gzip/deflate/zstd, bounded brotli reader) via decompress_body_with_limit, so bombs are cut off at the byte budget instead of after full expansion, including stacked-encoding intermediates. - Deeplink: show the usage section whenever any usage field is present, matching build_provider_meta persistence — a deeplink carrying only usageAccessToken/usageUserId no longer imports credentials invisibly. - Codex catalog: after the lexical containment check, canonicalize the existing file and re-verify containment so symlinks inside ~/.codex cannot escape the config dir; the path_is_within doc comment no longer oversells the lexical check as symlink-safe. - Grok sync: comment now matches the skip-all-symlinks behavior and each skip is logged, so sessions behind a symlink are diagnosable. - Docs: CONTRIBUTING notes the packageManager pnpm pin and Corepack flow. Regression tests follow the same methodology as round 1: reverting a guard fails the corresponding test (server write-count assertions prove the mid-stream abort; a truncated gzip stream distinguishes TooLarge from read-to-end errors; symlink escape is rejected only after the canonicalize re-check). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>