Skip to content

fix: Tauri runtime guard + market-script sha256 verification (+ architecture notes) - #603

Closed
keevingfu wants to merge 6 commits into
BigPizzaV3:mainfrom
keevingfu:fix/manager-tauri-runtime-guard
Closed

keevingfu wants to merge 6 commits into
BigPizzaV3:mainfrom
keevingfu:fix/manager-tauri-runtime-guard

Conversation

@keevingfu

@keevingfu keevingfu commented Jun 3, 2026

Copy link
Copy Markdown

Overview

This PR bundles three related pieces of work from a source walkthrough of the codebase. They are split into self-contained commits, so it reads cleanly commit-by-commit:

  1. Fix — guard the Tauri runtime before invoke in the manager.
  2. Hardening — verify a market script's sha256 before installing it.
  3. Docs — an architecture walkthrough (docs/architecture-notes.md, 11 chapters with file:line references).

If a maintainer would prefer the docs and/or the hardening split into separate PRs, happy to do that — just say the word.


1. Fix: guard Tauri runtime before invoke (923188b)

Backend commands in the manager are all reached through one call/invoke path. When the UI runs outside the Tauri webview (a browser, tauri dev opened directly, or a devtools/automation context), window.__TAURI_INTERNALS__ is undefined, so @tauri-apps/api's invoke throws:

Cannot read properties of undefined (reading 'invoke')

This was reported as "Restart Codex++" failing, but it affects every command — restart just happened to be the one clicked. The backend command (restart_codex_plus) is correctly registered and is not at fault.

Change: add a tauriRuntimeAvailable() runtime check; guard call and logDiagnostic so a missing runtime rejects with a clear, actionable message instead of the opaque TypeError (and logDiagnostic becomes a no-op so it can't re-trigger the same error). The popup now reads "Tauri 运行时不可用:请在已安装的「Codex++ 管理工具」窗口中操作…".

2. Hardening: verify market-script sha256 before install (c097924)

Market scripts are JS that get injected into the Codex page, so their integrity is security-relevant. The market manifest already carried a per-script sha256, but install_market_script_content wrote the downloaded bytes without checking it (the prior behavior was even pinned by a test that ignored mismatches).

Change: add verify_script_checksum — before writing, hash the downloaded content and compare (case-insensitive hex) against the manifest sha256. On mismatch the install aborts with a clear error: no file written, no install recorded, any existing version left intact. An empty sha256 skips the check, so hash-less legacy manifests still install. Pulls in sha2 + hex (both already resolved in Cargo.lock).

3. Docs: architecture walkthrough notes (74de9ca, 1681ffc, baffc04, db1f5c3)

docs/architecture-notes.md — a new-contributor map of the core mechanisms, each section carrying file:line references:

1–8. CDP injection · the Runtime-Binding bridge · React hooking in the injected script · the Responses⇄Chat protocol proxy (incl. apply_patch codec) · the macOS launcher · GitHub-release auto-update · Zed Remote open · upstream worktree creation.
9. Relay config & profile switching (mode × protocol, the three auth/config layouts).
10. Background consistency — provider_sync (history visibility across a provider switch) + watcher (keep-alive / stale recovery).
11. User scripts & the script market (which is where the §2 hardening was found).

Testing

  • npm run check (tsc --noEmit) passes.
  • cargo check -p codex-plus-core -p codex-plus-launcher -p codex-plus-data passes; no new warnings.
  • Rust suites run locally, all green:
    • bridge_routes 22 passed (incl. the new sha256 reject/accept/skip-when-empty cases)
    • protocol_proxy 35 · relay_config 67 · provider_sync 7 · watcher 9

🤖 Generated with Claude Code

cavinfu and others added 6 commits June 3, 2026 10:57
Backend commands are reached through a single `call`/`invoke` path. When the
UI runs outside the Tauri webview (browser, `tauri dev` opened directly, or a
devtools/automation context), `window.__TAURI_INTERNALS__` is undefined and
`@tauri-apps/api` throws "Cannot read properties of undefined (reading
'invoke')". This surfaced as "Restart Codex++" failing, but affects every
command.

Guard `call`/`logDiagnostic` with a runtime check that rejects with a clear,
actionable message instead of the opaque TypeError.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source-read notes covering the core mechanisms: CDP injection, the
Runtime-Binding bridge, React hooking in the injected script, the
Responses<->Chat protocol proxy (incl. apply_patch codec), the macOS
launcher, GitHub-release auto-update, Zed Remote open, and upstream
worktree creation. Each section carries file:line references.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source-read notes for the relay-config writer (relay_config.rs +
settings.rs): the mode × protocol axes, how Official/MixedApi/PureApi map
onto auth.json vs config.toml, the four-step profile-switch pipeline
(filter common -> complete provider -> merge+limits -> mode-specific
auth), shared common-config, atomic write+backup+validate, backfill/clear,
ChatGPT JWT account label, and the Tauri-command (not bridge) entry point.
Verified by running the relay_config suite: 67 passed.

Also marks ch.9 done in the dev log; remaining modules deferred to ch.10+.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source-read notes for the two background-consistency mechanisms:
provider_sync (codex-plus-data) migrates session-history visibility across
a provider switch by rewriting the model_provider tag in three sources
(rollout JSONL first line, state_5.sqlite threads index, global-state
workspace roots), preserving mtime, dir-locking against concurrent runs,
backing up before changes, rolling back on failure, skipping OS-locked
files, and warning that synced-but-encrypted history may not resume; and
watcher (codex-plus-core) keeps the launcher/injection alive via CDP
liveness probe, on-demand stale-launcher recovery with ancestor-chain
self-protection, and Windows auto-start install.

Honestly notes the three pacing constants have no in-tree polling loop and
recovery is on-demand (main.rs:64), not a 3s daemon. Verified by running
both suites: provider_sync 7 passed, watcher 9 passed.

Also marks ch.10 done in the dev log; user_scripts/script_market -> ch.11+.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source-read notes for user-authored / market-installed enhancement JS:
user_scripts (builtin+user two-source scan, global + per-script toggles
behind a Mutex+atomic_write, build_enabled_bundle wrapping each script in
an isolated try/catch IIFE, injected both via addScriptToNewDocument at
launch and via live Runtime.evaluate on /user-scripts/reload), and
script_market (GitHub-raw index.json manifest with strict per-entry
filtering, download + atomic install + recorded metadata).

Records an honest finding: the sha256 field is parsed and stored but never
verified on install (no Sha256/sha2 anywhere; the behavior is pinned by
install_market_script_ignores_checksum_mismatch...). Flagged as a future
hardening point. Verified by running the bridge_routes suite: 20 passed.

Also marks ch.11 done in the dev log; architecture notes now cover all
major modules.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Market scripts are JS injected into the Codex page, so their integrity is
security-relevant. The manifest already carried a per-script sha256, but
install_market_script_content wrote the downloaded bytes without checking
it (the old behavior was even pinned by a test that ignored mismatches).

Add verify_script_checksum: before writing, hash the downloaded content and
compare (case-insensitive hex) against the manifest sha256. On mismatch,
abort the install with a clear error — no file written, no install
recorded, any existing version left intact. An empty sha256 skips the check
so hash-less legacy manifests still install. Pull in sha2 + hex (both
already resolved in Cargo.lock).

Rewrite the ignore-mismatch test into reject-mismatch-and-keep-existing,
and add accept-matching + skip-when-empty. bridge_routes 20 -> 22 passed.
Sync architecture-notes ch.11.6 to describe the now-verified behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
keevingfu pushed a commit to keevingfu/CodexPlusPlus that referenced this pull request Jun 4, 2026
Running development worklog distinct from the release-facing CHANGELOG:
records the 2026-06-03 source walkthrough, the manager invoke runtime-guard
fix, branch/PR status (BigPizzaV3#603, pending maintainer CI approval), and the
next-step plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@keevingfu
keevingfu force-pushed the fix/manager-tauri-runtime-guard branch from c6d88bd to c097924 Compare June 4, 2026 01:31
@keevingfu keevingfu changed the title fix: guard Tauri runtime before invoke in manager fix: Tauri runtime guard + market-script sha256 verification (+ architecture notes) Jun 4, 2026
@chenbai365

Copy link
Copy Markdown

👋 @ 感谢贡献!此 PR 已开放 21 天,且当前存在 合并冲突 (merge conflict)

请 rebase 到最新的 main 分支并解决冲突。若 7 天内未更新,我们将关闭此 PR。

如有任何问题,欢迎在评论区讨论。

@BigPizzaV3

Copy link
Copy Markdown
Owner

Codex++ maintainer review note

当前 main 下这个 PR 仍存在 merge conflict,暂时不能合并。请先 rebase 到最新 main 并解决冲突;更新后我们会重新跑针对性测试再复审。

This PR currently conflicts with main, so it is not mergeable yet. Please rebase onto the latest main and resolve the conflicts, then we can review and test it again.

@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢贡献。该 PR 长期未 rebase,当前与 main 存在合并冲突;其中 market-script SHA-256 校验方向也与后续 Provider Guard/市场安全方案重叠。为避免保留无法直接合并且重复的实现,现关闭此 PR。若后续仍需保留 Tauri runtime guard 或校验逻辑,请基于最新 main 拆分并重新提交。

@BigPizzaV3

Copy link
Copy Markdown
Owner

已按维护说明关闭:当前存在合并冲突,且部分安全改动与其他方案重叠。

@BigPizzaV3 BigPizzaV3 closed this Aug 25, 2026
@BigPizzaV3 BigPizzaV3 reopened this Aug 25, 2026
@BigPizzaV3

Copy link
Copy Markdown
Owner

状态更正:此 PR 按维护要求保持开启。请基于 7385664 rebase,并拆开 Tauri runtime guard、市场脚本 SHA-256 强制校验和架构文档;脚本校验部分需覆盖缺失 hash、大小写/格式错误、下载后不匹配、缓存命中以及安装失败不落盘,且不要与 Provider Guard 重复实现同一下载边界。

@BigPizzaV3

Copy link
Copy Markdown
Owner

按此前维护意见继续保持开启,但请基于当前 main 拆分 Tauri runtime guard、脚本市场 SHA-256 校验和架构文档,避免与 #1517 重复。脚本校验需覆盖缺失/格式错误/不匹配、缓存命中和安装失败不落盘,并重新跑 CI。

@BigPizzaV3 BigPizzaV3 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

该 PR 分支长期未同步且与 main 冲突,混合了 Tauri runtime guard、脚本 sha256 校验和架构文档三类改动。请拆分或基于最新 main 重做,确认依赖变更确有必要,补跑三平台 CI 后再复审。

@BigPizzaV3

Copy link
Copy Markdown
Owner

关闭理由:分支基于很旧的 main(080611c5)已冲突,作者自 6-03 提交后再无更新,且其中『market-script sha256 校验』部分与 #1517 覆盖的安全加固主题重叠。若继续请基于最新 main rebase 并与 #1517 协调范围后重开。

@BigPizzaV3 BigPizzaV3 closed this Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants