stablyai / stablyai/orca

macOS 26 (Tahoe): login(1) TCC attribution wrapper no longer isolates terminal children — App Data prompts re-fire on every spawn

Open
#12,971 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
71.3k
Forks
4.7k
Avg merge
14h 54m
Merged PRs (30d)
520

Description

## Summary

The macOS TCC attribution fix from #6996 / #8985 (`wrapShellSpawnForMacosTccAttribution`, wrapping pane shells in `/usr/bin/login -flpq ...`) is silently ineffective on macOS 26 (Tahoe). Children of a *verified-wrapped* pane still have their `kTCCServiceSystemPolicyAppData` accesses attributed to `com.stablyai.orca`, and because Tahoe issues only session-scoped consent for this class (never persisted to TCC.db), users get the "Orca would like to access data from other apps" dialog on **every** invocation of tools like the 1Password CLI (`op`) — from every agent shell, all day. This makes agent-heavy workflows on Tahoe effectively unusable without clicking dialogs continuously.

## Environment

- Orca 1.4.174 (installed build wraps via `login -flpq /usr/bin/env SHELL=... -l`; current main uses the bash trampoline — both are login(1)-based and share the failing premise)
- macOS 26.x (Darwin 25.5.0), Apple Silicon
- 1Password CLI 2.38.1 as the App-Data-touching reproduction tool (any binary touching another app's container reproduces)

## Differential reproduction

1. In an Orca terminal: run `op whoami` twice → the App Data dialog appears **both times** (and on every subsequent run; consent never persists).
2. In iTerm2 (or Terminal.app): run `op whoami` twice → at most one prompt ever, then permanently quiet.
3. Running an agent harness *inside iTerm2* and invoking `op whoami` repeatedly through it: no prompts — confirming the delta is the hosting terminal's attribution, not the CLI, the harness, or the daemon architecture.

## Evidence that the wrapper is active AND ineffective (same pane, same minute)

Pane ancestry (via `/bin/ps`; the wrapper IS present, running as root):

```
73728 1055 root /usr/bin/login -flpq shawnkoh /usr/bin/env SHELL=/bin/zsh /bin/zsh -l
73730 73728 shawnkoh /bin/zsh -l (pane shell; agent + op are descendants)
```

TCC record for an `op` invocation from a descendant of that wrapped shell:

```
tccd: Handling access request to kTCCServiceSystemPolicyAppData, from
Sub:{com.stablyai.orca} Resp:{TCCDProcess: identifier=com.stablyai.orca,
responsible_path=/Applications/Orca.app/Contents/MacOS/Orca,
binary_path=/opt/homebrew/Caskroom/1password-cli/2.38.1/op},
ReqResult(Auth Right: Unknown (Service Policy), promptType: 1, DB Action:None)
```

`DB Action:None` + `authorization_right=Session` on consent: Tahoe never persists this grant, so with responsibility collapsing to Orca, every fresh `op` process re-prompts. One invocation can produce two dialogs (the client's probe and the spawned `op daemon`'s own probe each require separate session consent).

## Root cause

On macOS 26, an intermediate setuid `login(1)` session does **not** break TCC responsibility inheritance for the App Data class — tccd walks through it to the app bundle. The mechanism terminals actually rely on for per-tool attribution is `responsibility_spawnattrs_setdisclaim` at `posix_spawn` time (used by Terminal.app and iTerm2), which macOS 26 still honors — hence the differential above.

## Suggested fix

Apply `responsibility_spawnattrs_setdisclaim(attrs, 1)` in the PTY spawn path — Orca already maintains a node-pty patch (`config/patches/node-pty@1.1.0.patch`), and its darwin `spawn-helper` is the natural place. The login(1) wrapper could then be retired or kept solely for login-session semantics.

Also worth adding: a runtime effectiveness check. The current `onMacosTccSpawnStrategy` reports `wrapped`, but `wrapped` no longer implies isolated — a one-time probe that verifies a child's responsible identity would have surfaced this regression immediately instead of silently degrading to prompt storms.

## Additional observation (compounding, separate)

The 1.4.17x update chain changed the app's signing TeamID (2DC432GLL2 → 6CX3WHS9HZ at 1.4.174 on this machine), which invalidates users' existing TCC grants across all classes (Accessibility, Automation, Screen Recording re-prompts). Independent of the attribution bug, but it amplifies the perceived prompt storm after updates. Happy to file separately if useful.

Contributor guide

Open the contributing guide

Research direction

Start with config/patches/node-pty@1.1.0.patch and the Darwin spawn-helper in the PTY spawn path; compare the current login(1) wrapper with the responsibility attribution behavior described here. Validate the change using the repeated op whoami reproduction in Orca and iTerm2, confirming that consent does not reappear for each spawned process.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, typescript
Domain
desktop, devtools, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.