Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/content/docs/cua-driver/guide/getting-started/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@ This is the same TCC-attribution issue as the previous question, applied to the

macOS is attributing the process to a different bundle id than the one you granted. Run `cua-driver diagnose` and share the output when filing an issue. It reports cdhash, team id, and which bundle TCC matched against.

### After a rebuild, the driver reports `NOT granted` but System Settings still shows CuaDriver toggled ON.

This is a stale TCC grant. TCC pins each Accessibility / Screen-Recording grant to the app's **designated requirement at grant time**. If you first granted while `CuaDriver.app` was *ad-hoc* signed, the requirement is a bare `cdhash H"…"`, which changes on every rebuild — so the grant row stays `allowed` but its requirement no longer matches the new binary, and re-toggling the switch doesn't help (the row already records a decision, so the prompt never re-fires).

Release builds are CI-signed with a stable identity, so this only affects the local dev loop (`install-local.sh`). That installer now signs with a **stable self-signed certificate** and, when it detects the signing identity changed since the last install, runs `tccutil reset` for you so the next grant re-pins cleanly. After you re-grant once on the certificate-signed build, the grant survives every future rebuild.

To clear it by hand:

```bash
tccutil reset Accessibility com.trycua.driver
tccutil reset ScreenCapture com.trycua.driver
cua-driver permissions grant # re-grant once; now pinned to the stable cert
```

## Config and telemetry

### Where does config live?
Expand Down
13 changes: 13 additions & 0 deletions docs/content/docs/cua-driver/reference/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ The canonical, always-current source is the
release body is auto-generated per release from the commits touching
`libs/cua-driver/rust`, including SHA256 checksums and install instructions.

## Unreleased

- macOS (local dev install only): `install-local.sh` now clears a stale TCC
grant left over from a previous signing identity. If you first granted
Accessibility / Screen Recording while the bundle was ad-hoc signed, that
grant was pinned to the per-build `cdhash` and silently stopped matching on
the next rebuild — the daemon read `NOT granted` while System Settings still
showed CuaDriver toggled ON, a dead end re-toggling couldn't fix. The
installer records the signing identity and, when it changes, runs
`tccutil reset` so the next grant re-pins cleanly to the stable self-signed
certificate (after which grants survive all future rebuilds). Release builds
are unaffected — they're CI-signed with a stable identity (#1792 follow-up).

## 0.4.3 (2026-05-31)

- macOS: the agent-cursor overlay now actually renders in the `serve` daemon.
Expand Down
39 changes: 39 additions & 0 deletions libs/cua-driver/scripts/_install-local-rust.sh
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,45 @@ if [ "$OS" = "Darwin" ]; then
fi
fi
echo "${GREEN}installed $APP_DEST${NORMAL}"

# --- Clear a TCC grant pinned to a PREVIOUS signing identity -----------
#
# TCC pins each Accessibility / Screen-Recording grant to the app's
# designated requirement AT GRANT TIME. A user who granted while the app
# was ad-hoc signed has a grant whose csreq is a bare `cdhash H"..."`
# (changes every rebuild); a user who granted under a different cert has
# one pinned to that leaf. After we re-sign with the stable cert above,
# that old row survives with auth_value=allowed but a csreq that no longer
# matches THIS build — so the daemon reads "not granted" while System
# Settings still shows the toggle ON. That's a dead end: re-toggling
# doesn't help because the row already records a decision, so the grant
# prompt never re-fires. Detect a signing-identity change vs the last
# install and `tccutil reset` once, so the next `permissions grant`
# prompts cleanly and re-pins to the current (stable cert) identity —
# after which cert-pinned grants survive all future rebuilds.
#
# `tccutil reset` needs no sudo / Full Disk Access, and is a no-op when
# nothing was granted. We only reset when moving TO a cert identity (the
# case a clean re-grant durably fixes); an ad-hoc build churns its cdhash
# every rebuild regardless, so resetting it would just add friction.
if command -v tccutil >/dev/null 2>&1; then
IDENTITY_MARKER="$HOME_DIR/.tcc-signing-identity"
NEW_IDENTITY="$(codesign -d -r- "$APP_DEST" 2>&1 \
| sed -n 's/.*certificate leaf = H"\([0-9a-fA-F]*\)".*/cert:\1/p' | head -1)"
[ -n "$NEW_IDENTITY" ] || NEW_IDENTITY="adhoc"
OLD_IDENTITY="$(cat "$IDENTITY_MARKER" 2>/dev/null || true)"
case "$NEW_IDENTITY" in
cert:*)
if [ "$NEW_IDENTITY" != "$OLD_IDENTITY" ]; then
tccutil reset Accessibility com.trycua.driver >/dev/null 2>&1 || true
tccutil reset ScreenCapture com.trycua.driver >/dev/null 2>&1 || true
echo "${BOLD}cleared any stale Accessibility / Screen-Recording grant pinned to a previous build.${NORMAL}"
echo " Grant once more (System Settings → Privacy & Security) and it will${BOLD} stick across every future rebuild${NORMAL} — the grant now pins to a stable signing certificate, not the per-build cdhash."
fi
;;
esac
printf '%s\n' "$NEW_IDENTITY" > "$IDENTITY_MARKER" 2>/dev/null || true
fi
fi

# --- Visible-bin symlink ------------------------------------------------
Expand Down
Loading