mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
fix(bundle): declare macOS TCC privacy keys for child processes (#323)
* fix(bundle): declare macOS TCC privacy keys for child processes tty7 currently ships no NS*UsageDescription keys and no data-access entitlements, so macOS falls back to a repeated "access other apps' data" prompt whenever a child process (shell, coding agent, mole, etc.) touches a protected folder such as ~/Library/Containers, Mail, Messages, or Calendar. kitty and Kaku both declare these privacy intents, which converts the prompt into a single, clear one-time grant. Add the folder/volume usage descriptions and the matching personal-information and device entitlements to the macOS bundle so the app behaves like its terminal peers. * fix(bundle): rework TCC usage strings per review - Correct problem statement: describe child-process-denied-without-prompt instead of the Full Disk Access framing (no NS*UsageDescription key exists for that class). - Add the full usage-string set (camera, microphone, contacts, calendars, reminders, photos, location, motion, local network, bluetooth, speech recognition, system administration, apple events), kitty-style wording. - Use macOS spellings: NSCalendarsFullAccessUsageDescription / NSRemindersFullAccessUsageDescription / NSLocationUsageDescription. - Drop every entitlement that has no matching usage string; keep only com.apple.security.automation.apple-events. - Restore trailing newline at EOF in bundle-macos.sh. - Document the Full Disk Access manual-grant requirement in docs/features.md. * docs: rewrite macOS privacy as feature notes (en + zh-CN) * fix(bundle): drop the apple-events entitlement, tidy the privacy docs The entitlement did not do what its comment claimed. Nothing in tty7 or in gpui's mac platform layer sends an Apple event, and it would not help the case this change is about either: the hardened-runtime automation check runs against the process actually sending the event, which is the pane's child carrying its own signature. What TCC reads off tty7.app is the usage string in Info.plist, which stays. Entitlements are per-executable and never inherited, so granting this one only widened what injected code could reach under an identity that already holds disable-library-validation. Docs: spell out the four Full Disk Access paths instead of running them together as one nested path, drop motion from the user-facing list (Core Motion has no macOS implementation, though the key stays for kitty parity), and place the section identically in the English and Chinese files. --------- Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
This commit is contained in:
@@ -68,6 +68,40 @@ cat > "$APP/Contents/Info.plist" <<PLIST
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>NSHighResolutionCapable</key><true/>
|
||||
<key>NSPrincipalClass</key><string>NSApplication</string>
|
||||
<!-- tty7 is a terminal workbench: panes are forked from the bundled
|
||||
executable, so macOS attributes a child process's protected-resource
|
||||
requests to tty7.app. Without these usage strings a program you run in
|
||||
a pane that asks for camera / microphone / contacts / calendar /
|
||||
photos / location / reminders / Apple Events is denied outright with
|
||||
no prompt, and cannot even be granted in System Settings. Declaring
|
||||
them mirrors what kitty and Kaku ship for exactly this reason: Mac
|
||||
TCC reads the responsible bundle's usage string, not the child's. -->
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access the camera.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access the microphone.</string>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access your contacts.</string>
|
||||
<key>NSCalendarsFullAccessUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access your calendar data.</string>
|
||||
<key>NSRemindersFullAccessUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access your reminders.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access your photo library.</string>
|
||||
<key>NSLocationUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access your location information.</string>
|
||||
<key>NSMotionUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access motion data.</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to access the local network.</string>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to use Bluetooth.</string>
|
||||
<key>NSSpeechRecognitionUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to use speech recognition.</string>
|
||||
<key>NSSystemAdministrationUsageDescription</key>
|
||||
<string>A program running inside tty7 requires elevated privileges.</string>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>A program running inside tty7 would like to control other applications via Apple Events.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
@@ -109,6 +143,18 @@ if [[ -n "$SIGN_ID" && -n "${APPLE_CERTIFICATE:-}" ]]; then
|
||||
<key>com.apple.security.cs.allow-jit</key><true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key><true/>
|
||||
<!-- Deliberately nothing beyond those three, and in particular no TCC
|
||||
entitlement to match the usage strings in Info.plist. Those strings
|
||||
are about a *child* process's request: macOS attributes it to tty7.app
|
||||
as the responsible process and reads the wording from its bundle. The
|
||||
hardened-runtime entitlement, by contrast, is checked against the
|
||||
process actually sending the request — the child, carrying its own
|
||||
signature, since entitlements are per-executable and never inherited.
|
||||
So camera / microphone / location / apple-events on tty7.app would do
|
||||
nothing for a pane, while widening what injected code could reach
|
||||
under tty7's identity; this bundle already carries
|
||||
disable-library-validation. Same reasoning the comments below use to
|
||||
keep the GUI's entitlements off the CLI. -->
|
||||
</dict>
|
||||
</plist>
|
||||
ENT
|
||||
|
||||
@@ -122,6 +122,25 @@ a brief pause; `prefix` + an unbound key passes straight through.
|
||||
- Hot paths are lock-free — a big `cat` never waits on drawing
|
||||
- The daemon buffers up to 16 MiB ahead of the window before backpressure applies
|
||||
|
||||
## macOS privacy
|
||||
|
||||
Panes are forked from the bundled executable, so macOS attributes a program's
|
||||
request for a protected resource to tty7.app. tty7 declares the matching TCC
|
||||
usage strings (camera, microphone, contacts, calendar, reminders, photos,
|
||||
location, local network, Bluetooth, speech recognition, Apple Events, system
|
||||
administration) so that program gets the normal one-time prompt instead of
|
||||
being denied outright with no prompt at all.
|
||||
|
||||
Not covered by usage strings:
|
||||
|
||||
- **Full Disk Access** — Apple defines no usage-string key for it. Reaching
|
||||
`~/Library/Mail`, `~/Library/Messages`, `~/Library/Safari` or
|
||||
`~/Library/Containers` needs a manual grant in System Settings.
|
||||
|
||||
Declaring a usage string is not the same as holding the permission: tty7.app
|
||||
itself is granted none of these resources. Every prompt you see belongs to
|
||||
whatever you ran in the pane, and you can revoke it under Privacy & Security.
|
||||
|
||||
## Localization
|
||||
|
||||
The GUI ships English and Simplified Chinese strings. Pick one in Settings →
|
||||
|
||||
@@ -118,6 +118,23 @@ Aider、Amp、OpenCode 等约 17 个)并在其外围加功能 —— 绝不包
|
||||
- 热路径全程无锁 —— 再大的 `cat` 也不会阻塞在渲染上
|
||||
- 触发背压前,守护进程最多可领先窗口缓冲 16 MiB
|
||||
|
||||
## macOS 隐私
|
||||
|
||||
窗格是从 app bundle 里的可执行文件 fork 出来的,所以程序申请受保护资源时,
|
||||
macOS 会把这次请求算到 tty7.app 头上。tty7 声明了对应的 TCC usage strings
|
||||
(摄像头、麦克风、通讯录、日历、提醒、照片、定位、本地网络、蓝牙、语音识别、
|
||||
Apple Events、系统管理),这样程序才能正常弹出一次性授权窗口,而不是连弹窗都
|
||||
没有就被直接拒绝。
|
||||
|
||||
不受 usage strings 覆盖的:
|
||||
|
||||
- **完全磁盘访问** —— 苹果没有为它定义 usage-string 键。要读写
|
||||
`~/Library/Mail`、`~/Library/Messages`、`~/Library/Safari` 或
|
||||
`~/Library/Containers`,需要在「系统设置」中手动授权。
|
||||
|
||||
声明 usage string 不等于持有权限:tty7.app 自己一项都没有拿到。你看到的每个
|
||||
授权弹窗都属于你在窗格里运行的那个程序,也可以在「隐私与安全性」中撤销。
|
||||
|
||||
## 本地化
|
||||
|
||||
GUI 目前提供英文和简体中文两套文案。在「设置 → 外观 → 语言」中选择,或直接改
|
||||
|
||||
Reference in New Issue
Block a user