-
Notifications
You must be signed in to change notification settings - Fork 0
Tauri 2 migration + security hardening, CodeMirror 6 editor, signed auto-updating builds #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Anic888
wants to merge
13
commits into
main
Choose a base branch
from
tauri-v2-migration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
773eb17
Sanitize snippet/macro ids to fix path traversal (H1)
Anic888 e59f06c
Harden git invocations: config-driven RCE + option injection
Anic888 3170036
Lock down terminal command execution (C1, C2)
Anic888 2f92482
Scope file_exists and cap read/search file sizes (M2, M10, H4)
Anic888 bb041e8
Redact OAuth token material from cloud errors and logs (M9)
Anic888 2ee346f
Add PKCE (S256) to cloud OAuth authorization-code flow (M8)
Anic888 19b50cf
Add signed+notarized release pipeline and auto-updater (C4, H3)
Anic888 3585900
Replace textarea editor with CodeMirror 6 (virtualized) — fixes large…
Anic888 f6fbafd
Code-split the bundle into cacheable vendor chunks
Anic888 16b6de9
Deny credential/secret paths inside $HOME in validate_path (M1)
Anic888 cd05010
Store Keychain secrets via native API, not argv (M6)
Anic888 a361612
Migrate to Tauri 2 (capabilities, plugins, v2 menu/event API)
Anic888 996fc75
docs: refresh README for Tauri 2 + CodeMirror, add CHANGELOG, fix hea…
Anic888 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| name: Release | ||
|
|
||
| # Cut a release by pushing a version tag, e.g. | ||
| # git tag v2.0.1 && git push origin v2.0.1 | ||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| release: | ||
| permissions: | ||
| contents: write | ||
| runs-on: macos-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Node | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
|
|
||
| - name: Set up Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| targets: aarch64-apple-darwin,x86_64-apple-darwin | ||
|
|
||
| - name: Cache cargo | ||
| uses: Swatinem/rust-cache@v2 | ||
| with: | ||
| workspaces: src-tauri | ||
|
|
||
| - name: Install frontend dependencies | ||
| run: npm install | ||
|
|
||
| - name: Build, sign, notarize & publish | ||
| uses: tauri-apps/tauri-action@v0 | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| # --- Code signing (Developer ID Application) --- | ||
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | ||
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | ||
| APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} | ||
| # --- Notarization (Apple ID + app-specific password) --- | ||
| APPLE_ID: ${{ secrets.APPLE_ID }} | ||
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | ||
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||
| # --- Updater artifact signing --- | ||
| TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} | ||
| TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} | ||
| with: | ||
| tagName: ${{ github.ref_name }} | ||
| releaseName: 'RocketNote ${{ github.ref_name }}' | ||
| releaseBody: 'Download the .dmg below. The app is signed and notarized; existing installs update automatically.' | ||
| releaseDraft: true | ||
| prerelease: false | ||
| # Universal binary (Apple Silicon + Intel). tauri-action emits the | ||
| # signed updater bundle + latest.json and attaches them to the release. | ||
| args: --target universal-apple-darwin | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to RocketNote are documented here. | ||
| Format based on [Keep a Changelog](https://keepachangelog.com/). | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - **CodeMirror 6 editor** with true viewport virtualization — multi-megabyte logs and minified bundles open without freezing the UI. | ||
| - **Auto-updater** — signed update channel served from GitHub Releases (Tauri updater + `latest.json`). | ||
| - **Signed & notarized macOS builds** — GitHub Actions release pipeline (`.github/workflows/release.yml`) with Developer ID signing and notarization. See [docs/distribution-setup.md](docs/distribution-setup.md). | ||
| - **PKCE (S256)** on the cloud OAuth authorization-code flow for all providers. | ||
|
|
||
| ### Changed | ||
| - **Migrated to Tauri 2** — capabilities/ACL permission model, split plugins, v2 menu API. | ||
| - Production bundle is **code-split** into cacheable vendor chunks (app-shell entry ~174 kB instead of a single ~1.7 MB chunk). | ||
| - Secrets are stored in the macOS Keychain via the **native Security framework** instead of the `security` CLI, so secret values never appear on the process command line. | ||
|
|
||
| ### Security | ||
| - **Git:** every git invocation is hardened (`GIT_CONFIG_NOSYSTEM`, `core.fsmonitor` / `core.hooksPath` disabled, `ext`/`file` transports blocked) — opening an untrusted repository can no longer execute code via its `.git/config`. | ||
| - **Terminal:** script interpreters removed from the quick-run allowlist; `pty_write_force` only accepts confirmation keystrokes for a pending danger prompt (one-shot). | ||
| - **Filesystem:** snippet/macro ids are sanitized; `validate_path` denies credential locations (`~/.ssh`, `~/.aws`, `~/.gnupg`, `~/Library/Keychains`, …); `file_exists` is scope-checked; read and global-search size caps prevent memory-exhaustion hangs. | ||
| - **Cloud / Git:** OAuth token material is redacted from error messages and logs; git branch/ref names are guarded against option injection. | ||
|
|
||
| ### Fixed | ||
| - License metadata in `Cargo.toml` aligned to GPL-3.0 (matches `LICENSE`). | ||
| - Broken README header image. | ||
|
|
||
| ## [2.0.0] | ||
| - Initial public release — encryption, cloud sync, AI assistant, Git, terminal, global search, developer tools. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # RocketNote — Distribution Setup (signing · notarization · auto-update) | ||
|
|
||
| This closes audit findings **C4** (unsigned/un-notarized macOS build) and **H3** (no update channel). Everything below is wired in `.github/workflows/release.yml`; you only need to add the GitHub **secrets** and cut a tag. | ||
|
|
||
| > The build is signed + notarized **in CI** with your Apple credentials. Nothing here can be verified on a machine without your Apple Developer account, so treat this as a checklist, not a finished build. | ||
|
|
||
| --- | ||
|
|
||
| ## 1. One-time: Apple code-signing identity | ||
|
|
||
| 1. In the Apple Developer portal create a **Developer ID Application** certificate (this is the cert for apps distributed *outside* the App Store). | ||
| 2. In **Keychain Access** → export it (with its private key) as a `.p12` file, set an export password. | ||
| 3. Base64-encode it for the secret: | ||
| ```sh | ||
| base64 -i DeveloperID.p12 | pbcopy | ||
| ``` | ||
| 4. Find the exact identity string: | ||
| ```sh | ||
| security find-identity -v -p codesigning | ||
| # e.g. "Developer ID Application: Your Name (TEAMID1234)" | ||
| ``` | ||
|
|
||
| ## 2. One-time: notarization credentials | ||
|
|
||
| - Use your **Apple ID** + an **app-specific password** (appleid.apple.com → Sign-In and Security → App-Specific Passwords). | ||
| - Your **Team ID** is the 10-char code in the identity above / in the developer portal membership page. | ||
|
|
||
| ## 3. Updater signing key — already generated ✅ | ||
|
|
||
| A Tauri updater keypair was generated for you: | ||
|
|
||
| - **Public key** is already committed in `src-tauri/tauri.conf.json` → `updater.pubkey`. | ||
| - **Private key** is at `~/.tauri/rocketnote_updater.key` on this machine (it was created with an **empty** password). | ||
|
|
||
| Add its *contents* as the `TAURI_PRIVATE_KEY` secret: | ||
| ```sh | ||
| cat ~/.tauri/rocketnote_updater.key | pbcopy | ||
| ``` | ||
| > Prefer to control the key yourself? Regenerate with | ||
| > `cargo tauri signer generate --ci -w ~/.tauri/rocketnote_updater.key -f`, | ||
| > then paste the **new** public key into `updater.pubkey`. Keep the private key out of git. | ||
|
|
||
| ## 4. GitHub repository secrets | ||
|
|
||
| Settings → Secrets and variables → Actions → **New repository secret**: | ||
|
|
||
| | Secret | Value | | ||
| |---|---| | ||
| | `APPLE_CERTIFICATE` | base64 of the `.p12` (step 1.3) | | ||
| | `APPLE_CERTIFICATE_PASSWORD` | the `.p12` export password | | ||
| | `APPLE_SIGNING_IDENTITY` | `Developer ID Application: Your Name (TEAMID)` | | ||
| | `APPLE_ID` | your Apple ID email | | ||
| | `APPLE_PASSWORD` | the app-specific password | | ||
| | `APPLE_TEAM_ID` | your 10-char Team ID | | ||
| | `TAURI_PRIVATE_KEY` | contents of `~/.tauri/rocketnote_updater.key` | | ||
| | `TAURI_KEY_PASSWORD` | empty string (the key has no password) | | ||
|
|
||
| `GITHUB_TOKEN` is provided automatically — do not add it. | ||
|
|
||
| ## 5. Cut a release | ||
|
|
||
| ```sh | ||
| git tag v2.0.1 | ||
| git push origin v2.0.1 | ||
| ``` | ||
|
|
||
| The workflow builds a **universal** (Apple Silicon + Intel) binary, signs it with Developer ID, notarizes + staples it, and creates a **draft** GitHub Release with: | ||
| - `RocketNote_*.dmg` — the installer users download; | ||
| - `RocketNote.app.tar.gz` + `RocketNote.app.tar.gz.sig` — the signed update bundle; | ||
| - `latest.json` — the updater manifest. | ||
|
|
||
| Review the draft, then **Publish**. Publishing makes it the `latest` release, which is exactly what `updater.endpoints` points to: | ||
| `https://github.com/Anic888/rocketnote/releases/latest/download/latest.json`. | ||
|
|
||
| ## 6. How auto-update works after this | ||
|
|
||
| On launch the app fetches `latest.json`, compares versions, verifies the bundle signature against the embedded `pubkey`, and (because `updater.dialog = true`) prompts the user to install. Ship a fix by bumping the version in `package.json` + `src-tauri/tauri.conf.json` and pushing a new tag. | ||
|
|
||
| ## Notes / gotchas | ||
|
|
||
| - Bump the version in **both** `package.json` and `src-tauri/tauri.conf.json` (`package.version`) before tagging; the tag and the config version should match. | ||
| - First notarization can take a few minutes; tauri-action waits for it. | ||
| - If notarization fails on "hardened runtime" entitlements, the exceptions live in `src-tauri/Entitlements.plist`. | ||
| - `package-lock.json` is git-ignored, so CI uses `npm install` (not `npm ci`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For tagged releases, this step passes the old updater key names, but Tauri 2's bundler reads
TAURI_SIGNING_PRIVATE_KEYandTAURI_SIGNING_PRIVATE_KEY_PASSWORD. Becausesrc-tauri/tauri.conf.jsonnow contains an updaterpubkey, 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 👍 / 👎.