Repository navigation
fix(stereo-camera): delegation never outranks the OS camera switch or a stored Deny - #1836
Merged
Merged
Conversation
… a stored Deny Follow-up to PR #1819 (R3 consent). As built, a registered consent- delegating client was allowed at step 4 of the consent decision, before the OS camera privacy switch (step 5) and before a stored per-app Deny (step 6), and tests_camera_consent pinned that order. Once a browser's installer registered it, it would get the 3D camera with the OS switch off and a Deny the user had stored silently ignored. Roadmap §B.3 and the pre-R3 spec say the opposite, and no rationale for the order was recorded; "the browser enforces the OS switch itself" cannot hold, because the service, not the browser, opens the camera, so the OS never sees the browser as a camera user. New order (spec §7.1 is the one statement of it): sharing off / DXR_STEREO_CAMERA=0 -> DISABLED; dev override; no identity; OS switch -> PERMISSION_INSUFFICIENT; stored Deny -> CONSENT_REFUSED; delegating -> allowed; stored Allow; Allow once; prompt. Delegation keeps meaning exactly "no runtime prompt and no stored decision needed". The decision's `delegating` flag is now reported from step 3 on whatever the verdict. `displayxr-cli camera trust <exe>` over a stored Deny clears the Deny and says so (the user's newer explicit word, like `allow` over `deny`); an installer's machine-wide registration never touches the user's store. `camera deny` on a delegating exe notes that the Deny wins. Explicit <exe> arguments are stored the way the service sees the peer: resolved with realpath on POSIX; on Windows read from the UTF-16 command line (argv is the ANSI code page) and made absolute with GetFullPathNameW. Windows store reader (u_camera_consent_store.c), both bugs verified: - it used the ANSI registry API while the runtime compares UTF-8 paths (QueryFullProcessImageNameW -> CP_UTF8), so a non-ASCII install path could never match an installer's UTF-16 entry. Every read, write, delete and enumeration (HKLM and HKCU, Apps, Delegating, Sharing, Secret, the ConsentStore webcam keys) now uses the wide API with explicit UTF-8 conversion. - fixed 256-char name / 1024-byte data buffers turned one oversized value into ERROR_MORE_DATA and `break`, hiding every later entry. Buffers are now sized from RegQueryInfoKeyW; an entry that still does not fit, has the wrong type or does not convert is skipped, never ends the scan. The matching is the pure u_camera_consent_list_find() over an abstract enumerator plus u_camera_consent_path_equal(), both unit-tested on every OS. Tests: the delegation-first assertions are rewritten; new cases for delegating + OS switch off, + stored Deny, + sharing off / kill switch, + nothing stored (allowed, no prompt, nothing written), unregistered neighbour unchanged, path rules, and skip-not-stop enumeration. Mutation: restoring the old order fails 2 cases / 7 assertions; making the list scan stop on a skipped entry fails the enumeration case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfattal
force-pushed
the
fix/camera-consent-order
branch
from
October 6, 2026 08:03
986b531 to
54ef035
Compare
Collaborator
Author
Windows check — PASS (SR laptop, run by the Windows session, 2026-10-06)
One naming note from that run: for the OS-switch refusal the CLI prints the IPC-level name, Mergeable from the Windows side; merge is the project owner's call. |
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.
Follow-up to #1819 (R3 consent). Not a release blocker (no installer registers a delegating client today), but it must land before one does.
The defect
As built,
u_camera_consent_evaluate()allowed a registered consent-delegating client at step 4 — before the OS camera privacy switch (step 5) and a stored per-app Deny (step 6);tests_camera_consentpinned that order. Once a browser's installer registers it, it gets the 3D camera with the OS switch off, and a Deny the user stored for it is silently ignored. Roadmap §B.3 and the pre-R3 spec (OS consent applies to every consumer; delegation replaces only the DisplayXR prompt) say the opposite. No rationale was recorded, and "the browser enforces the OS switch itself" cannot hold: the service opens the camera, so the OS never sees the browser as a camera user.The fix
Order (spec §7.1, the one statement of it): sharing off /
DXR_STEREO_CAMERA=0→ DISABLED · dev override · no identity · OS switch → PERMISSION_INSUFFICIENT · stored Deny → CONSENT_REFUSED · delegating → allowed · stored Allow · Allow once · prompt. Delegation means exactly "no runtime prompt and no stored decision needed". Result codes are unchanged per refusal.camera trust <exe>over a stored Deny clears the Deny and says so (user's newer explicit word, asallowoverdeny); an installer's registration never touches the user store.camera denyon a delegating exe notes the Deny wins.<exe>args are stored as the service sees the peer:realpathon POSIX; on Windows read from the UTF-16 command line andGetFullPathNameW'd (argv is ANSI).RegQueryInfoKeyW, and an oversized / wrong-type / unconvertible value is skipped, never ends the scan. Matching is the pureu_camera_consent_list_find()+u_camera_consent_path_equal(), unit-tested on every OS.Verification
tests_camera_consent(macOS): 18 cases / 161 assertions pass.scripts/build-mingw-check.sh aux_utilpasses (the Windows store compiles); the CLI's Windows argv snippet compiles + links under MinGW with-lshell32.XDG_CONFIG_HOME:deny→trust(clears Deny) →deny(note printed).Not run (Windows box)
Registry code is compile-checked only. On Windows: copy
displayxr-cli.exe(+ its DLLs) into a non-ASCII directory (e.g.C:\Tëst\浏览器\displayxr-cli.exe) — the probe is the consumer; writeHKLM\Software\DisplayXR\CameraConsent\Delegatingwith a 5000-char junk REG_SZ value first and then a REG_SZ whose data is that path;displayxr-cli camera consentmust list the path;camera proberun from that copy must be allowed without a prompt; turn Settings → Privacy → Camera → desktop apps off → it must be refused with PERMISSION_INSUFFICIENT; turn it back on,displayxr-cli camera deny "C:\Tëst\浏览器\displayxr-cli.exe"→ refused with CONSENT_REFUSED;camera trustit → "cleared the stored Deny".🤖 Generated with Claude Code