Repository navigation
windows: narrow the profile read grant to a listed set - #767
Merged
Merged
Conversation
ig-ant
marked this pull request as ready for review
October 22, 2026 20:14
The walk no longer grants a directory whole unless it is beneath an inclusion: a built-in list of where per-user tools install themselves and what they need to run, plus what configuration adds. A directory on the way to an inclusion or an exclusion stays a container, so the way down to both is open; any other directory gets no entry at all, and a session can still open it with a read grant of its own. Files in a container are granted only inside an inclusion; the files of the profile root are still granted by name. An inclusion follows a link as an exclusion does. The list version goes from 3 to 4. include_refusal says which paths may not be added as inclusions: an exclusion, anything inside one, the temporary directory or anything inside it.
`srt-win profile grant --include <PATH>` (repeatable; `--replace-includes` drops the ones earlier runs recorded) adds a directory or file of the profile to what the grant makes readable. An inclusion that is an exclusion, lies inside one, or is or lies inside the temporary directory is refused; one recorded by an earlier run is looked at again, as the built-in exclusions may have grown since. The added inclusions are kept in the marker (ProfileInclude) and reported by `profile status` as `extra_inclusions`. grant() takes its added paths as one `Added`. The library passes `include` / `replaceInclusions` (WindowsProfileGrantOptions) and `profileInclude` (the install, `--profile-include`), reads `extraInclusions` from the status, and its notice says what the grant now opens. The README section is rewritten for the listed shape.
`.local` stands for a listed directory and `Documents` for one the list does not name: the rows that read, deny and write under "a granted child" use the former; the new R5 shows the latter gets no entry and is still open to a session's own read grant; N and E use a new child of a listed container rather than a new top-level directory; I exercises `--include`, `--replace-includes` and the refusals. The notice test of the library reads the new wording.
… tree A failed or partial walk beneath a directory no longer reads as revoked, and empty directories the grant made are removed when they leave it. Objects that no longer exist are dropped, and unreachable volumes are retried and reported.
A release that narrows the list now takes effect at the next session start, and a session does not start while anything it was to revoke stays readable.
…e retried A refresh that finishes starts the session and lists those paths as a warning. Each later session start tries them again, on those paths alone.
A revoke killed mid-walk is now finished by the next run, and a repeated failure stays reported. Retries at session start are bounded and no longer keep a starting session out. scoop, .local and uv leave the read list.
A killed profile grant records every planned path before writing any. A path it never wrote and cannot write stayed recorded as granted, which made later session read denies fail on it. Check the object's access list before keeping such a row.
mvn expands MAVEN_ARGS unquoted, so literal quotes reached Maven as part of the path. A path that needs them now uses its 8.3 name, or the variable is withheld.
…ad grant It unlocks the passwords settings.xml stores encrypted, so the file is denied and MAVEN_ARGS no longer points at it.
… done Each revoke is now recorded before any walk and cleared only after the whole tree is checked, so an interrupted or failing run cannot lose its warning or its retry. A first grant that was cut short is no longer finished automatically.
An interrupted first install no longer leaves every session refused until the install is run again. An interrupted forget is still never re-granted.
A folder excluded and then included again kept warning about an entry that was now the one wanted.
New folders under Programs now get a list entry, and their files their own.
…sion ends A folder under Programs goes back to a list entry, not an inheriting one.
… closed Paths that left the grant are re-read from their access lists before it reads as current, and a refresh runs under initialize()'s guard with the install's 30-minute limit. Only .config\git and .config\pip stay readable under .config.
…takeown icacls /setowner cannot open a file that denies reading its access list, so the row's clean-up failed and the grant rightly kept reporting the entry.
… and .m2 is read whole Status now reads pending revokes, so copies left beneath a directory keep their warning. A reset() kills a running refresh, and a conflicting initialize() is refused. Maven's master password files are readable by design again.
The library's signal handler now cancels initialize(), so the run ended with that cancellation's message instead of naming the signal.
ig-ant
force-pushed
the
ig/windows-profile-include-list
branch
from
November 9, 2026 22:55
96b3baa to
bff04eb
Compare
dylan-conway
approved these changes
Nov 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Narrows the Windows profile read grant from "the whole profile minus exclusions" to a built-in list of tool directories, because 0.0.81 left Documents, Desktop and most of AppData readable to sandboxed commands.
initialize()now upgrades an older grant by itself, revoking what left the list.Summary
srt-win profile grant --includeadds paths. Tools only inscoop,.local, uv's folders or elsewhere under.configstop working unless added. Links are not followed.LIST_VERSIONgoes to 4.initialize()refreshes an older grant and finishes any interrupted one, as the user, with a 30-minute limit and an optional progress callback. It never re-grants after an interrupted forget, a newer record or a different profile.profile_stale_allowand is retried; that path may stay readable until then.reset()cancels a runninginitialize(), and an overlapping call with a different config is rejected.Accepted trade-off:
.m2is readable whole, including Maven's master password files, so sandboxed code can decrypt passwords stored insettings.xml. Otherwise those builds would run outside the sandbox.Test plan
CI passes on all platforms, including
smoke-profile-read.ps1. On Windows 11 ARM64, an earlier revision upgraded a real 0.0.81 grant: 487 entries removed, judged from the ACLs, in about 70 s, and no run ended current with an unwarned entry. The latest fixes have only run in CI.Known:
forgetcan leave an inert inherited deny. A write root under a folder with inheritedRESTRICTED:(M)loses per-session isolation; that also affectsmain.