Skip to content

Commit b0bb6c4

Browse files
authored
Merge branch 'main' into sm/fix
2 parents bfcc747 + d0edb58 commit b0bb6c4

3 files changed

Lines changed: 54 additions & 57 deletions

File tree

docs/macos-tcc-permissions.md

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,33 +33,29 @@ The skip list is hard-coded against the well-known TCC categories on
3333
modern macOS (anchored at the logged-in user's `$HOME`):
3434

3535
```
36-
~/Desktop ~/Library/Mail
37-
~/Documents ~/Library/Messages
38-
~/Downloads ~/Library/Safari
39-
~/Pictures ~/Library/Calendars
40-
~/Movies ~/Library/Reminders
41-
~/Music ~/Library/HomeKit
42-
~/Public ~/Library/Suggestions
43-
~/.Trash ~/Library/IdentityServices
44-
~/Library/Mobile Documents ~/Library/Metadata/CoreSpotlight
45-
~/Library/CloudStorage ~/Library/PersonalizationPortrait
46-
~/Library/Containers ~/Library/Application Support/AddressBook
47-
~/Library/Group Containers ~/Library/Application Support/CallHistoryDB
48-
~/Library/Application ~/Library/Application Support/CallHistoryTransactions
49-
Scripts ~/Library/Application Support/com.apple.TCC
50-
51-
/Volumes/.timemachine* (Time Machine local snapshots, prefix match)
36+
~/Desktop ~/Library
37+
~/Documents ~/.Trash
38+
~/Downloads
39+
~/Pictures /Volumes/.timemachine* (Time Machine local
40+
~/Movies snapshots, prefix match)
41+
~/Music
42+
~/Public
5243
```
5344

54-
The two parent skips that look broad (`~/Library/Containers` and
55-
`~/Library/Group Containers`) collapse per-app sandbox containers in
56-
one go. Apple gates many of those subtrees behind separate TCC
57-
services on modern macOS — Photos for `com.apple.Photos`, Media
58-
Library for `com.apple.Music`, and the Sonoma "App Management" /
59-
"Data from other apps" prompt for arbitrary `<app>/Data` subdirs. The
60-
contents (per-app sandbox state) aren't meaningful inventory data for
61-
the agent's purpose, so the broader skip avoids three distinct popup
62-
categories without losing useful coverage.
45+
`~/Library` is skipped wholesale rather than per-subpath. Every macOS
46+
release adds new Apple-managed subtrees behind new TCC services —
47+
Sonoma added "App Management" / "Data from other apps" for arbitrary
48+
`<app>/Data` containers, Sequoia hardened Photos / Media Library /
49+
Movies, Tahoe expanded Media Library to cover
50+
`~/Library/Application Support/com.apple.avfoundation/` — so a curated
51+
allowlist of `Library/X` entries goes stale on every upgrade and
52+
prompts start firing again at end users. `~/Library` is the wrong
53+
place for developer projects, lockfiles, or `.npmrc` files anyway. The
54+
detectors that DO need to read specific paths under `~/Library`
55+
(JetBrains plugins at `~/Library/Application Support/JetBrains/...`,
56+
Claude desktop MCP config, pip global config) use targeted
57+
`ReadDir`/`ReadFile` calls that don't consult the skipper, so they
58+
keep working unchanged.
6359

6460
If a search dir is explicitly named (`--search-dirs ~/Documents`) the
6561
walk root itself is honored — the skip only applies to TCC paths

internal/tcc/tcc_darwin.go

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,23 @@ import "path/filepath"
99
// - Files & Folders (Catalina+): Desktop, Documents, Downloads
1010
// - Removable / Network (Catalina+): handled via opt-in search dirs
1111
// - Photos / Music / Movies (Sequoia hardened): Pictures, Movies, Music
12-
// - Full Disk Access subtrees: ~/Library/Mail, Messages, Safari, etc.
13-
// - Cloud sync (Sonoma+): Mobile Documents, CloudStorage
12+
// - Everything under ~/Library: Mail, Messages, Safari, Mobile Documents,
13+
// CloudStorage, Containers, plus the long tail of Apple-private
14+
// subtrees that gain new TCC services with each macOS release.
15+
//
16+
// ~/Library is skipped wholesale rather than per-subpath. Every macOS
17+
// release adds new Apple-managed subtrees behind new TCC services
18+
// (Sonoma's App Management, Sequoia's hardened Pictures/Music/Movies,
19+
// Tahoe's expanded Media Library scope into
20+
// ~/Library/Application Support/com.apple.avfoundation/, and so on),
21+
// so a curated allowlist of "Library/X" entries goes stale on every
22+
// upgrade — at which point a previously-silent walk into one of those
23+
// subtrees starts firing a prompt at end users. ~/Library is the wrong
24+
// place for developer projects / lockfiles / npmrc files anyway; the
25+
// detectors that DO need to read specific paths under ~/Library
26+
// (JetBrains plugins, Claude desktop MCP config, pip global config)
27+
// use targeted ReadDir/ReadFile calls that don't consult this skipper,
28+
// so they're unaffected.
1429
var protectedSuffixes = []string{
1530
"Desktop",
1631
"Documents",
@@ -20,34 +35,7 @@ var protectedSuffixes = []string{
2035
"Music",
2136
"Public",
2237
".Trash",
23-
24-
"Library/Mail",
25-
"Library/Messages",
26-
"Library/Safari",
27-
"Library/Calendars",
28-
"Library/Reminders",
29-
"Library/HomeKit",
30-
"Library/Suggestions",
31-
"Library/Application Support/AddressBook",
32-
"Library/Application Support/CallHistoryDB",
33-
"Library/Application Support/CallHistoryTransactions",
34-
"Library/Application Support/com.apple.TCC",
35-
"Library/IdentityServices",
36-
"Library/Metadata/CoreSpotlight",
37-
"Library/PersonalizationPortrait",
38-
39-
// App sandbox containers — skipped wholesale because any descent into
40-
// these triggers per-service prompts (Photos for com.apple.Photos,
41-
// Media Library for com.apple.Music, the macOS Sonoma "App Management"
42-
// / "Data from other apps" prompt for arbitrary <app>/Data subdirs).
43-
// Nothing inside an app's sandbox is meaningful inventory data for
44-
// dev-machine-guard's purpose, so the broader skip is a clean win.
45-
"Library/Containers",
46-
"Library/Group Containers",
47-
"Library/Application Scripts",
48-
49-
"Library/Mobile Documents",
50-
"Library/CloudStorage",
38+
"Library",
5139
}
5240

5341
// protectedAbsolutePrefixes are matched with strings.HasPrefix. Time

internal/tcc/tcc_darwin_test.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ func TestSkipper_ShouldSkip(t *testing.T) {
1818
{"documents trailing slash", "/Users/alice/Documents/", "/Users/alice", true},
1919
{"downloads skipped", "/Users/alice/Downloads", "/Users/alice", true},
2020
{"desktop skipped", "/Users/alice/Desktop", "/Users/alice", true},
21-
{"library mail skipped", "/Users/alice/Library/Mail", "/Users/alice", true},
22-
{"icloud drive skipped", "/Users/alice/Library/Mobile Documents", "/Users/alice", true},
21+
{"library root skipped", "/Users/alice/Library", "/Users/alice", true},
2322
{"trash skipped", "/Users/alice/.Trash", "/Users/alice", true},
2423
{"random code dir not skipped", "/Users/alice/code", "/Users/alice", false},
2524
{"vscode dotdir not skipped", "/Users/alice/.vscode", "/Users/alice", false},
@@ -88,6 +87,20 @@ func TestEnabled(t *testing.T) {
8887
}
8988
}
9089

90+
// TestSkipper_RegressionAVFoundationMediaLibraryPrompt locks in the fix
91+
// for the macOS 26.x (Tahoe) "Apple Music, your music and video activity,
92+
// and your media library" prompt that fired when the project walker
93+
// descended into ~/Library/Application Support/com.apple.avfoundation/
94+
// looking for Python venvs / Node projects / .npmrc files. Without ~/Library
95+
// being skipped wholesale, the walker reaches that subtree and macOS pops
96+
// the kTCCServiceMediaLibrary prompt at the end user.
97+
func TestSkipper_RegressionAVFoundationMediaLibraryPrompt(t *testing.T) {
98+
s := New("/Users/alice")
99+
if !s.ShouldSkip("/Users/alice/Library", "/Users/alice") {
100+
t.Fatal("~/Library must be skipped to prevent walker from descending into Apple-managed TCC subtrees (e.g. Library/Application Support/com.apple.avfoundation/ → kTCCServiceMediaLibrary)")
101+
}
102+
}
103+
91104
func TestSkipper_CandidatesSorted(t *testing.T) {
92105
s := New("/Users/alice")
93106
cands := s.Candidates()

0 commit comments

Comments
 (0)