Tauri 2 migration + security hardening, CodeMirror 6 editor, signed auto-updating builds#3
Tauri 2 migration + security hardening, CodeMirror 6 editor, signed auto-updating builds#3Anic888 wants to merge 13 commits into
Conversation
Add helpers::sanitize_id() rejecting path separators, traversal, NUL and absolute paths; apply to snippet/macro save+delete (the session-name fix was never applied here). Also add exceeds_size_limit() helper used by the read/search size caps.
Route every git command through git_cmd_base(), which sets GIT_CONFIG_NOSYSTEM and disables core.fsmonitor / core.hooksPath and the ext/file protocols. An untrusted repo's .git/config can no longer execute code on the automatic git_status (C3). Reject option-like branch/ref names in git_checkout/git_create_branch.
Remove script interpreters (bash/zsh/python3/node/swift) from execute_command's quick-run allowlist so the metacharacter/danger filters can't be trivially bypassed. Gate pty_write_force to accept ONLY confirmation keystrokes (Enter/Ctrl-C) and ONLY when a danger warning is pending (consumed one-shot), closing the direct force-write bypass.
Route file_exists through validate_path to remove the arbitrary host-path existence oracle. Enforce a 50 MiB cap in read_file/read_file_bytes and a 5 MiB per-file cap in global_search to prevent memory-exhaustion hangs.
Add redact_secrets() and wrap all cloud error bodies and token-response JSON before returning them; stop logging raw error objects in CloudStoragePanel.
generate_pkce() command returns a random verifier + base64url(SHA-256) challenge (verified against the RFC 7636 test vector). The frontend sends code_challenge/code_challenge_method=S256 in the auth URL for all three providers and passes the verifier to exchange_oauth_token, which binds it into the token request. An intercepted loopback authorization code can no longer be redeemed without the verifier.
GitHub Actions release.yml (tauri-action) builds a universal macOS binary, signs it with Developer ID, notarizes+staples, and publishes a draft Release with the updater bundle + latest.json. Enable the Tauri updater (active + S256 pubkey + GitHub 'latest' endpoint) and add the 'updater' cargo feature. Add Hardened-Runtime Entitlements.plist (un-ignored so CI can use it). Full secret/setup checklist in docs/distribution-setup.md. Signing/notarization run in CI with the maintainer's Apple credentials; not verifiable here.
…-file freeze (H4) The old editor rendered the entire document as a highlight overlay + one DOM node per line, freezing the UI on multi-MB / many-line files. CodeMirror 6 virtualizes the viewport. Verified in-browser: a 50,000-line document keeps only ~82 line nodes in the DOM. Preserves the full EditorProps/EditorRef contract (App.tsx untouched): line numbers, per-language syntax highlighting, find/replace + navigate via @codemirror/search, native undo/redo history, word wrap, tab size, Cmd-wheel font zoom, theme, and the minimap. tsc + vite build pass. Note: bundle grew (~1.7MB) from CodeMirror + language packages; code-splitting is a separate optimization.
Replace the single ~1.74MB JS chunk with manualChunks: codemirror, xterm, markdown, react-vendor, icons. App-shell entry drops from 1739kB to ~174kB; heavy libs load in parallel and stay cached across releases. Verified via npm run build.
validate_path previously allowed read/write/delete anywhere under $HOME. Add is_sensitive_path() denying secret stores (.ssh, .aws, .gnupg, .kube, .docker), macOS Keychains (~/Library/Keychains), and credential/history files (.netrc, .git-credentials, .npmrc, .pypirc, shell history). Ordinary files and ~/.config remain editable. Pure-path helper unit-tested.
Replace the 'security add/find-generic-password -w <value>' shell-outs with the keyring crate (native Security framework). The secret value no longer appears on the process command line, which is world-readable via ps/KERN_PROCARGS2 and was a cross-local-user disclosure of API keys / OAuth tokens. Service/account naming is preserved, so secrets stored by older versions stay readable. Verified: cargo test (39 passed) + live Keychain roundtrip (store/get/delete) passes.
Ran the official tauri migrate, then completed the manual parts: rewrote main.rs to the v2 menu builder API (SubmenuBuilder/MenuItemBuilder), on_menu_event(|app,event|) + Emitter, get_webview_window; added the seven tauri-plugin-* (dialog/clipboard/shell/fs/http/notification/updater); moved allowlist -> capabilities/*.json; tauri.conf.json -> v2 schema (app/bundle/plugins.updater with the existing pubkey, fileDropEnabled->dragDropEnabled). Frontend: invoke -> @tauri-apps/api/core, dialog -> @tauri-apps/plugin-dialog (type->kind), shell -> @tauri-apps/plugin-shell. Added Emitter import in terminal.rs. cargo update brought tauri 2.11.3 (fixes a wry 0.54 build incompat). Verified: npm run build (tsc+vite) clean, cargo build clean, cargo test 39 passed/1 ignored. Full bundle + GUI feature-test still pending.
…der icon & license README: editor is now CodeMirror 6 (virtualized), backend Tauri 2, v2 build instructions (npm run tauri), auto-update + signed-build note. Add CHANGELOG.md (Unreleased) documenting the security hardening, PKCE, code-split, distribution pipeline and Tauri 2 migration. Add app-icon.png so the README header renders. Align Cargo.toml license to GPL-3.0 (matches LICENSE/README).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 996fc754a2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} | ||
| TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} |
There was a problem hiding this comment.
Use Tauri 2 updater signing environment variables
For tagged releases, this step passes the old updater key names, but Tauri 2's bundler reads TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PRIVATE_KEY_PASSWORD. Because src-tauri/tauri.conf.json now contains an updater pubkey, the release build will not see the private key under the names it checks, so updater artifacts/signatures won't be produced correctly and the release job can fail.
Useful? React with 👍 / 👎.
| .plugin(tauri_plugin_clipboard_manager::init()) | ||
| .plugin(tauri_plugin_shell::init()) | ||
| .plugin(tauri_plugin_fs::init()) | ||
| .plugin(tauri_plugin_updater::Builder::new().build()) |
There was a problem hiding this comment.
Start the updater check from the app
Registering the updater plugin only exposes the updater API; it does not fetch latest.json or install anything by itself in Tauri 2. I searched src and src-tauri and there is no @tauri-apps/plugin-updater check()/downloadAndInstall() call or Rust UpdaterExt::check() path, so even signed releases will never be discovered by installed clients.
Useful? React with 👍 / 👎.
| "decorations": true, | ||
| "fileDropEnabled": true, | ||
| "transparent": false | ||
| "dragDropEnabled": true, |
There was a problem hiding this comment.
Update the file-drop listener for Tauri 2
With Tauri 2 drag/drop enabled here, the frontend still listens for the old v1 tauri://file-drop event in src/hooks/useFileManager.ts; Tauri 2 renamed these to tauri://drag-drop/drag-enter and the drop payload now carries paths for type === 'drop'. As a result, dropping files onto the window no longer opens them after this migration.
Useful? React with 👍 / 👎.
Summary
Migrates RocketNote to Tauri 2 and lands a round of security hardening, an editor swap, and a signed/auto-updating release pipeline. Full list in
CHANGELOG.md.Highlights
Security
core.fsmonitor/hooks disabled,GIT_CONFIG_NOSYSTEM,ext/filetransports blocked) — opening an untrusted repo can't run code via.git/config.pty_write_forcegated to confirmation keystrokes (one-shot).validate_pathdenies credential paths (~/.ssh,~/.aws, Keychains, …); snippet/macro ids sanitized;file_existsscope-checked; read/global-search size caps.Editor & performance
Distribution
docs/distribution-setup.md.Framework
cargo updatepulled tauri 2.11.3.Verification
npm run build(tsc + vite): clean.cargo build: clean.cargo test: 39 passed, 1 ignored (live-Keychain roundtrip, run with-- --ignored).npx tauri build: produces a signed.app+.dmg+ updater bundle; installs and launches on macOS.