feat: least-privilege VSS elevation helper broker + secured IPC#96
Open
pmaxhogan wants to merge 1 commit into
Open
feat: least-privilege VSS elevation helper broker + secured IPC#96pmaxhogan wants to merge 1 commit into
pmaxhogan wants to merge 1 commit into
Conversation
Rebuild VSS elevation as a narrow privileged broker that elevates ONLY the shadow-copy operation (DESIGN s5.3.1), replacing the removed whole-app elevation. New driven-vss-helper crate: - protocol: length-prefixed, capped, 1-byte-kind framing (control JSON + raw data chunks) so streamed file bytes carry no base64 overhead. - validate: boundary input validation (volume normalise + configured allowed-roots + `..`-traversal + component-wise within-root). - auth: pipe DACL SDDL (user + admins only) + process-image identity (caller PID -> image, sibling-install-dir check) both directions. - server (Windows): accept -> authenticate client -> validate -> create or reuse a per-volume VssSnapshot -> stream the locked file's bytes. The un-elevated client never opens the \?\GLOBALROOT device. - client + BrokeredVssProvider: streams bytes into an app-owned temp copy and returns that path, fitting the existing executor read_path seam; degrades to Unavailable off Windows / when the helper is absent. - launch + driven-vss-helper.exe: ShellExecute runas + argv/pipe-name. Elevated integration test proves a real exclusively-locked file streams through a real VSS snapshot and that the boundary rejects out-of-root + traversal requests (gate-skips when not elevated; verified via sudo). Adds the windows.vss_helper setting, a get_vss_helper_status command, and a Settings banner shown when locked-file backup is degraded. The production launch/provider-swap lifecycle (build_vss wiring + on- demand elevated launch) is deferred and documented in CODEX_NOTES. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014fLmkjpFkiuky72eLBijL4
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.
What
Rebuild VSS elevation as a narrow privileged broker that elevates ONLY the shadow-copy operation (DESIGN s5.3.1), replacing the whole-app elevation removed pre-V1. The main backup app stays un-elevated; a small
driven-vss-helper.execreates the VSS snapshot and streams the locked file's bytes back over a secured Windows named pipe.Closes #25.
Trust boundary + IPC (DESIGN s5.3.1)
\.\pipe\driven-vss-<uuid>), length-prefixed 1-byte-kind framing (control JSON + raw data chunks, so streamed bytes carry no base64 overhead), tiny vocabulary (Hello/OpenLocked/Read/CloseFile/EndCycle/Shutdown).BUILTIN\Administrators; per-connection caller PID -> image-path check (must be a sibling in the helper's install dir). The client also verifies the server's image before sending any path...-traversal reject + component-wise within-configured-roots (lexical AND after canonicalising the directory chain) -> a compromised app can only ever read files the user already configured Driven to back up.\?\GLOBALROOTshadow device; the helper streams the bytes.BrokeredVssProviderlands them in an app-owned temp copy and returns that path, fitting the existing executorread_pathseam unchanged.Lifecycle
On-demand elevated broker (not a persistent SYSTEM service): the app launches the helper elevated via
ShellExecute runas(one UAC prompt) with the pipe name + configured roots on its command line; the helper serves for the session and exits onShutdown. A Windows service install remains a documented alternative under the same IPC + auth + validation contract.Tested
tests/helper_integration.rs, gate-skips when not elevated, NOT#[ignore]-faked): spins the real server + client, snapshots a genuinely exclusively-locked file via real VSS, asserts the streamed bytes match, and asserts the boundary rejects out-of-root + traversal requests. Also proves theBrokeredVssProvidertemp-copy path. Verified locally elevated viasudo- both cases PASS.windows.vss_helpersetting round-trip +get_vss_helper_statuslogic (backend tests); the degraded-backup banner show/hide (vitest).cargo fmt --all --check,cargo clippy --workspace --all-targets(0 warnings),cargo-deny check bans,vue-tsc, the full UI vitest suite, eslint.Deferred (documented in CODEX_NOTES)
The production launch/provider-swap lifecycle -
assembly::build_vssconstructing theBrokeredVssProviderwhen the setting is enabled, coordinating one session pipe name across accounts, and the on-demand elevated launch on first locked-file need - is a follow-up. Its only untestable piece is the literal UAC prompt (argv is unit-tested); the provider/launch/server/client are all tested. Until it lands,build_vssstill returns the in-processRealVssProvider(default app behaviour unchanged) and the banner is informational.🤖 Generated with Claude Code