fix: graceful decrypt failure + CSP wasm-unsafe-eval for Rive mascot#2671
Conversation
Two bugs fixed: 1. config decrypt crash (load.rs): when a channel token (e.g. discord.bot_token) is stored with enc2: encryption but the decryption key is no longer accessible (keyring reset, machine migration, key rotation), decrypt_optional_secret was propagating a hard error via ? on every config load. This made the app unusable after login — every RPC that loaded config failed with "Failed to decrypt discord.bot_token". Fix: match on decrypt result, log a warn and clear the field on failure so config loads successfully with the affected integration disabled. Adds regression test config_load_succeeds_when_decryption_key_inaccessible. 2. Rive mascot invisible (tauri.conf.json): PR tinyhumansai#2659 replaced the SVG Ghosty mascot with a Rive WebGL2 renderer. Rive requires WebAssembly compilation (WebAssembly.instantiate), which CEF blocks because the auto-generated script-src CSP only contains 'self' + sha256 hashes — no eval-related source. Fix: add an explicit script-src directive with 'wasm-unsafe-eval' (CSP Level 3 — permits WASM compilation without enabling arbitrary eval). Tauri appends its sha256 hashes to this directive at compile time.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR introduces graceful handling of decryption failures in config loading and updates the Tauri app's Content Security Policy to permit WebAssembly unsafe evaluation. Config loading no longer crashes when optional secrets cannot be decrypted; instead, the affected secrets are cleared and a warning is logged. ChangesSecret Decryption Resilience and CSP Update
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Comment |
Summary
decrypt_optional_secretnow degrades gracefully when a storedenc2:secret can't be decrypted (e.g. after a keyring reset or machine migration). The field is cleared and aWARNis logged instead of propagating an error that made every config load fail and crashed the app after login.script-srcdirective with'wasm-unsafe-eval'totauri.conf.jsonso CEF allowsWebAssembly.instantiate(). Without it, Tauri generated a restrictivescript-src 'self' <sha256s>at compile time that blocked the Rive WebGL2 renderer introduced in PR feat(mascot): replace SVG animations with Rive renderer #2659, making the mascot invisible.config_load_succeeds_when_decryption_key_inaccessibleto verify the config loads cleanly when a field contains a stale/garbageenc2:ciphertext.Problem
discord.bot_token(or any other credential) was stored with anenc2:prefix but the master key had been rotated or lost —decrypt_optional_secretreturnedErrvia?, causing the entireConfig::load_or_initto fail. The subconscious bootstrap failure cascaded into all RPC calls that depend on config, making the app unusable.@rive-app/react-webgl2) requires WASM compilation. Tauri v2's CSP generator createsscript-srcfrom scratch (only'self'+ sha256 hashes) when no explicitscript-srcis present in the config, which CEF honoured — blockingWebAssembly.instantiate()with a CSP violation.Solution
decrypt_optional_secret: replaced?propagation onstore.decrypt()error with amatcharm that logswarnand sets the field toNone, returningOk(()).tauri.conf.jsonsecurity.csp: addedscript-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'so Tauri appends its sha256 hashes to this directive rather than generating a restrictive one.Submission Checklist
config_load_succeeds_when_decryption_key_inaccessiblecovers the decrypt-failure pathload_tests.rstest directly exercises the changed lines inload.rs; CSP change is config-only with no testable code pathImpact
'wasm-unsafe-eval'is narrower than'unsafe-eval'; it permits only WASM compilation, not arbitraryeval().Related
AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
bug-fixesa93a3ba5,ecfbdf37Validation Run
pnpm --filter openhuman-app format:checkpnpm typecheck(npx tsc --noEmit — clean)config_load_succeeds_when_decryption_key_inaccessible(via pre-push hook cargo check)cargo fmt --check— clean after auto-fixcargo fmt --manifest-path src-tauri/Cargo.toml --check— cleanValidation Blocked
command:N/Aerror:N/Aimpact:N/ABehavior Changes
enc2:tokens are silently cleared rather than crashing config loadParity Contract
is_encrypted()check is unchanged; only the error branch is modifiedDuplicate / Superseded PR Handling
Summary by CodeRabbit
Bug Fixes
Tests