GitHub
11/08/2026, 10:40 AM/private/ and /System/Volumes/Data/ as their unaliased form, so /private/etc/shadow touches /etc/shadow. But the alias roots and their parents (/private, /System/Volumes/Data, /System/Volumes, /System) did not touch anything. A recursive carve of /private would copy /etc/shadow through the alias for a user below full carve tier.
2. The carve list panicked on a huge page number. When sensitive paths are hidden, the carve list pages in memory. (page-1)*pageSize could overflow to a negative value for a huge ?page=, and slicing the list then panicked. Go's HTTP server recovers the panic per request, so it only affected authenticated users below full carve tier, but it shouldn't happen.
What changes
• `environments.PathTouches`: an alias root, or any parent of one, touches whenever the environment's sensitive list is non-empty. /System/Library is still allowed, and so is /private when the list is empty.
• `CarveListHandler`: the in-memory paging branch compares the page number against the page count before multiplying. A page past the end returns an empty page.
Security and operational impact
• Closes a path-check bypass on macOS endpoints for users below full carve tier. It only adds refusals.
• No schema or API changes. osctrl-tls is not changed.
Validation
• TestPathTouchesMacAliases now also checks /private, /PRIVATE/, /System/Volumes/Data, /system/volumes and /System (all touch), /system/library (does not touch), and /private with an empty list (does not touch).
• TestCarveListSearchNoOracle now also requests ?page=4611686018427387904&page_size=4 and expects 200.
• Both failed before the fix: the alias parents were not caught, and the page request panicked with slice bounds out of range [-4:].
• go test ./... passes.
jmpsec/osctrlGitHub
11/08/2026, 10:51 AM