# Risk map — farion1231/cc-switch

> Canonical page: https://codevetter.com/unpack/cc-switch/risk-map

# Risk map — farion1231/cc-switch

Scanned commit 09c5d39d8c3cf44b1bdfd0c6432c46495e546578 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The trust boundary is documented in SECURITY.md: the bundled renderer is trusted, but deep links, proxy listeners, sync payloads, imports, and upstream responses are not. The highest-impact code is the local proxy (optionally non-loopback), QuickJS usage scripts, and shell launches for terminals and session resume. Live config writes sit outside the repo and can brick Claude, Codex, Gemini, or Grok sessions if a takeover backup is mishandled. A few docs and defaults disagree with the code (i18n paths, Hermes visibility, AppType error text).
- SECURITY.md states there is no project cloud backend. The local HTTP proxy listen address is user-configurable and may be non-loopback; inbound requests are in scope. Also in scope: ccswitch:// payloads, WebDAV/S3 restores, SQL and config imports, proxy upstream responses, and credential leakage into logs or shared snippets. DevTools-only IPC calls are explicitly out of scope. — [SECURITY.md#L14-80](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/SECURITY.md#L14-L80)
- CSP allows connect-src http: and https: plus ipc, and img-src http/https. script-src stays 'self' plus one hash. SECURITY.md says introducing eval, new Function, an iframe, or a wider script-src voids the renderer trust decision. launch_session_terminal documents that it forwards the renderer command string to a shell because of that trust decision, while cwd is shell-escaped. — [src-tauri/tauri.conf.json#L28-34](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/tauri.conf.json#L28-L34) [SECURITY.md#L24-62](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/SECURITY.md#L24-L62) [src-tauri/src/commands/session_manager.rs#L27-70](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/session_manager.rs#L27-L70)
- execute_usage_script evals attacker-influenceable JavaScript (deep link or imported provider) inside rquickjs. Mitigations present in code are a 5-second interrupt, 16 MiB memory cap, 256 KiB stack, and base_url validation except for custom templates that embed their own URL. The HTTP request itself is performed by Rust after the script returns a request object. — [src-tauri/src/usage_script.rs#L8-67](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/usage_script.rs#L8-L67) [src-tauri/src/deeplink/mod.rs#L115-138](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/deeplink/mod.rs#L115-L138) [SECURITY.md#L70-79](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/SECURITY.md#L70-L79)
- open_provider_terminal extracts env vars, including API keys, from provider settings_config and passes them to launch_terminal_with_env. That function uses std::process::Command for bash, cmd, wsl.exe, osascript, and user-selected terminal binaries. MCP server commands are stored and later executed by the external CLI, not by validate_mcp_command, which only does a PATH lookup. — [src-tauri/src/commands/misc.rs#L3798-3856](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/misc.rs#L3798-L3856) [src-tauri/src/commands/mcp.rs#L38-42](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/mcp.rs#L38-L42) [SECURITY.md#L90-93](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/SECURITY.md#L90-L93)
- macOS subscription quota reads credentials by spawning the security CLI. Device names for sync can come from CC_SWITCH_DEVICE_NAME or a hostname command. These are local process launches with the user's privileges. — [src-tauri/src/services/subscription.rs#L133-133](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/subscription.rs#L133-L133) [src-tauri/src/services/sync_protocol.rs#L402-411](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/sync_protocol.rs#L402-L411)
- Provider API keys and live auth tokens are stored in SQLite providers.settings_config and in CLI files such as ~/.codex/auth.json. settings.json is written mode 0600 on Unix and secrets are stripped only in get_settings_for_frontend. Log redaction is exact-string based (minimum 8 characters) plus URL userinfo/query stripping, not a general secret scanner. — [src-tauri/src/settings.rs#L692-720](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/settings.rs#L692-L720) [src-tauri/src/settings.rs#L771-779](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/settings.rs#L771-L779) [src-tauri/src/lib.rs#L132-178](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L132-L178) [src-tauri/src/database/schema.rs#L26-43](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/database/schema.rs#L26-L43)
- Switching while a takeover backup exists must not overwrite the stub live file with the real upstream URL. recover_from_crash on the next launch is what restores live configs after a crash. A bug in hot_switch_provider_inner or the backup row can leave Claude/Codex/Gemini/Grok pointed at a dead local port or lose the pre-takeover file. — [src-tauri/src/services/provider/mod.rs#L5739-5801](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/mod.rs#L5739-L5801) [src-tauri/src/lib.rs#L1221-1244](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L1221-L1244) [src-tauri/src/services/provider/live.rs#L1704-1711](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/live.rs#L1704-L1711)
- AppType::from_str accepts mcode but the localized error string lists only claude, claude-desktop, codex, gemini, grokbuild, opencode, openclaw, hermes, and pi. Backend VisibleApps::default sets hermes to false while src/config/appConfig.tsx DEFAULT_VISIBLE_APPS sets hermes to true, so a missing settings value can disagree across the IPC boundary. — [src-tauri/src/app_config.rs#L467-488](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/app_config.rs#L467-L488) [src-tauri/src/settings.rs#L47-68](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/settings.rs#L47-L68) [src/config/appConfig.tsx#L32-43](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/config/appConfig.tsx#L32-L43)
- CONTRIBUTING.md tells contributors to edit src/locales/*/translation.json and to run pnpm lint. Neither the path nor the script exists. Locale edits that follow the doc will not ship; the loaded files are src/i18n/locales/en.json, zh.json, zh-TW.json, and ja.json. package.json's description still names only Claude, Codex, and Gemini. — [CONTRIBUTING.md#L66-128](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/CONTRIBUTING.md#L66-L128) [src/i18n/index.ts#L4-7](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src/i18n/index.ts#L4-L7) [package.json](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/package.json)
- The SQLite connection is a single Mutex<Connection>. Provider switches, MCP sync, and the 60-second session scanner all take that lock, sometimes inside spawn_blocking or block_on from async commands. Long writes (skill sync, usage rollup) stall every other command. — [src-tauri/src/database/mod.rs#L76-81](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/database/mod.rs#L76-L81) [src-tauri/src/services/provider/mod.rs#L5743-5746](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/mod.rs#L5743-L5746) [src-tauri/src/lib.rs#L1283-1316](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L1283-L1316)
- God-module concentration: ProviderService::switch is in services/provider/mod.rs past line 5700, open_provider_terminal is in commands/misc.rs past line 3800, and proxy takeover lives in services/proxy.rs (a test at line 7571). A drive-by edit in those files can change every app's live write. — [src-tauri/src/services/provider/mod.rs#L5712-5801](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/provider/mod.rs#L5712-L5801) [src-tauri/src/commands/misc.rs#L3803-3826](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/misc.rs#L3803-L3826) [src-tauri/src/services/proxy.rs#L3416-3416](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/services/proxy.rs#L3416-L3416)
- Legacy compatibility still in the boot path: JSON config.json migration when no database exists, Windows HOME/.cc-switch fallback when the default db is missing, Claude settings.json versus claude.json, and deprecated get_mcp_config marked allow(deprecated). Official seed ids are special-cased so an import does not resurrect deleted official rows on ordinary startup, but a manual import does re-seed them. — [src-tauri/src/lib.rs#L534-567](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/lib.rs#L534-L567) [src-tauri/src/config.rs#L258-288](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/config.rs#L258-L288) [src-tauri/src/config.rs#L243-255](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/config.rs#L243-L255) [src-tauri/src/commands/provider.rs#L135-174](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/provider.rs#L135-L174) [src-tauri/src/commands/mcp.rs#L53-55](https://github.com/farion1231/cc-switch/blob/09c5d39d8c3cf44b1bdfd0c6432c46495e546578/src-tauri/src/commands/mcp.rs#L53-L55)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
