Skip to content

fix: harden macOS clipboard fallback - #41

Merged
fly1d merged 1 commit into
mainfrom
codex/native-pasteboard-fallback
Aug 20, 2026
Merged

fix: harden macOS clipboard fallback#41
fly1d merged 1 commit into
mainfrom
codex/native-pasteboard-fallback

Conversation

@fly1d

@fly1d fly1d commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace the AppleScript clipboard round trip with a native, bounded snapshot of every pasteboard item, declared type, order, and exact data bytes.
  • Keep AppKit pasteboard objects on the macOS main thread while waiting for the static System Events Copy command off the UI thread behind a 15-second watchdog.
  • Restore only a stable exact-next candidate, return text only after restoration succeeds, and quarantine ambiguous post-Copy outcomes until restart so a late event cannot enter another fallback transaction.
  • Add Apple Events entitlement and usage text, build the .app in desktop CI, and require Developer ID authority, Team ID, and effective entitlement checks in release CI.
  • Document CurrentHostOnly, first-change attribution, delayed event behavior, and the remaining compare-and-write TOCTOU boundary.

Risk

  • Low: documentation, copy, styles, or isolated dictionary data
  • Medium: UI behavior, translation provider, document parsing, or shared API
  • High: selection capture, OS permissions, credentials, packaging, or releases

Verification

  • npm run check (34 tests and production build)
  • npm run test:smoke when user-facing behavior changed (5 passed, 1 skipped)
  • cargo check --manifest-path src-tauri/Cargo.toml when desktop code changed
  • npm run desktop:check (format, Clippy -D warnings, 21 Rust tests, check)
  • npm run test:site (12 passed)
  • Plist lint, workflow YAML parse, and git diff --check
  • Release .app build, local ad-hoc Hardened Runtime signature verification, bundled usage text, effective Apple Events entitlement, launch, steady process check, and normal termination
  • No API keys, user content, or sensitive logs were added
  • Error and fallback states were exercised

Review Notes

NSPasteboard does not expose writer identity or an atomic compare-and-swap restore. The first generation after Copy cannot be attributed with certainty, and a narrow check-to-write TOCTOU boundary remains. System Events also cannot acknowledge that the target app has processed an injected key event; quarantine prevents ambiguous failures from entering a newer Wordwise transaction, but a delayed event may still change the current system clipboard. Restored snapshots use NSPasteboardContentsCurrentHostOnly because the original sync option is not observable.

The local launch smoke does not replace signed/notarized-candidate validation. Keep the release blocker open until a real Developer ID build passes permission allow/deny, first-run TCC, no-selection/quarantine, timeout/quarantine, multi-format pasteboard, concurrent-write, revoke/regrant, and cross-application shortcut testing.

Refs #39

@fly1d fly1d added bug Something isn't working risk:high Permissions, credentials, packaging, or release risk github_actions Pull requests that update GitHub Actions code labels Aug 20, 2026
@fly1d
fly1d merged commit 23f1e8c into main Aug 20, 2026
5 checks passed
@fly1d
fly1d deleted the codex/native-pasteboard-fallback branch August 20, 2026 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working github_actions Pull requests that update GitHub Actions code risk:high Permissions, credentials, packaging, or release risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant