Repository navigation
feat(stereo-camera): delegation hardening — signer match, per-user first-use notice, DECLINE_DELEGATION (spec v3) - #1838
Merged
Conversation
…rst-use notice, DECLINE_DELEGATION (spec v3) Three hardening items for the ADR-043 consent model (spec §2a, §7.1, §7.1.1): - Signer match for user-writable delegating entries (Windows). An entry whose executable is not under %ProgramFiles%, %ProgramFiles(x86)% or %SystemRoot% (SHGetKnownFolderPath, case-insensitive, separator boundary, no "..") is applied only when it records a signer CN (sibling REG_SZ "<valueName>.signer") and the executable has a valid Authenticode signature by that signer (WinVerifyTrust GENERIC_VERIFY_V2, no UI, WTD_REVOKE_NONE, cache-only URL retrieval). Otherwise step 6 is skipped as if not delegating, with one WARN per exe per run. Admin-protected paths keep path-only trust; POSIX is path-only for now (documented). - First-use notice for USER-level (HKCU / user JSON) delegation: WARN + tray balloon (new ipc_server_stereo_camera_set_notice_provider), once per exe per service run. HKLM stays silent. - XR_STEREO_CAMERA_CLIENT_DECLINE_DELEGATION_BIT_DXR (0x2), spec v2 -> v3, plumbed XrStereoCameraClientInfoDXR -> xrt_application_info .stereo_camera_client_flags -> IPC -> u_camera_consent_evaluate(flags). A skipped delegation also drops the foreground-rule exemption (new decision.delegated / stream.delegated) but never the RAW refusal, which keys on registration alone. Store op is_delegating -> get_delegation (scope + signer); the policy takes path_user_writable / exe_signer / user_delegation_notice through the env vtable (NULL path classifier fails closed), so it stays unit-testable with fakes. CLI: `camera trust <exe> [--signer CN]`, `camera signer <exe>|--self` (exit 3 = not validly signed), `list|calib|probe --decline-delegation`. Tests: tests_camera_consent 25 cases / 272 assertions; 7 mutations of the new rules each fail at least one case. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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
Three hardening items for the ADR-043 stereo-camera consent model (normative text: spec §2a, §7.1 row 6, new §7.1.1; ADR-043 Amendment 3).
Software\DisplayXR\CameraConsent\Delegating) whose executable is not under%ProgramFiles%,%ProgramFiles(x86)%or%SystemRoot%(SHGetKnownFolderPath, ASCII case-insensitive, separator boundary, any..component = not under) is applied only if the entry records a signer CN, as a siblingREG_SZnamed<valueName>.signer, and the exe has a valid Authenticode signature whose leaf subject CN matches it (case-insensitive, trimmed). The check isWinVerifyTrustwithWINTRUST_ACTION_GENERIC_VERIFY_V2, no UI,WTD_REVOKE_NONEandWTD_CACHE_ONLY_URL_RETRIEVAL, so it never touches the network. If the check fails, step 6 is skipped exactly as if the exe were not delegating: stored decision, then prompt. One WARN per exe per service run names the reason. Admin-protected paths keep path-only trust. POSIX stays path-only (u_camera_consent_path_user_writable()returns false; documented).ipc_server_stereo_camera_set_notice_provider, whichservice_tray_win.cimplements. It fires once per exe per run. HKLM entries stay silent. macOS logs the WARN only for now.XR_STEREO_CAMERA_CLIENT_DECLINE_DELEGATION_BIT_DXR(0x2), spec v2 → v3. The header text matches the brief exactly. The flag travelsXrStereoCameraClientInfoDXR.flags→xrt_application_info.stereo_camera_client_flags(IPC wire) →consent_evaluate()→u_camera_consent_evaluate(..., flags, ...), which then skips step 6. Unknown bits are ignored.Design notes
is_delegatingis replaced byget_delegation(scope SYSTEM/USER + signer). The policy gets the platform facts through the env vtable (path_user_writable,exe_signer,user_delegation_notice), so it stays pure and testable with fakes. Ifpath_user_writableis NULL, every path counts as user-writable (fails closed).decision.delegatingstill means registered, and the RAW refusal keys on it, so an untrusted or declined entry can only narrow what a client gets. The newdecision.delegated/stream.delegatedmeans "allowed by delegation". Only those streams keep the foreground-rule exemption. A registered client that declined, or whose entry was untrusted, is treated as an ordinary window-bearing app.xrt_application_infogrows oneuint64_t, which changes the client↔service wire layout. Client and service ship together, and the git-tag gate already enforces that.%SystemRoot%(Temp, Tasks) and any install directory whose ACL an installer loosened are writable anyway.CLI
camera trust <exe>|--self [--signer "<CN>"]writes or replaces the.signercompanion and warns when the entry will not apply.untrustremoves both values.camera signer <exe>|--selfprints the path class and the valid Authenticode signer. Exit 3 means it is not validly signed.camera list|calib|probe ... --decline-delegationdeclares the new bit, so the owner can test without a browser.camera consentshows each delegating entry's signer.Tests
tests_camera_consenthas 25 test cases / 272 assertions, all pass (MSVC Release). The new cases cover: DECLINE (falls to stored Allow / Allow once / prompt, stored Deny still wins, unknown bits ignored, unregistered exe unaffected), user-writable entry without a signer / unsigned / wrong signer → not delegated, matching signer → delegated, admin path → path-only (signer never queried), host without classifiers fails closed, user-level notice once per exe (none for SYSTEM / declined / Deny), seen-set bounded,path_is_under,signer_equal.oxr_session.c:5562C4090.gen_extensions_index.py --checkpasses. Theindex.jsonsummary is unchanged.camera signer):C:\Windows\explorer.exeis admin-protected, signed "Microsoft Windows".%LOCALAPPDATA%\Programs\cursor\Cursor.exeis USER-WRITABLE, signed "Anysphere, Inc.". The dev_package\bin\displayxr-cli.exeis USER-WRITABLE and unsigned (exit 3).Not hardware-verified. The owner session runs the panel / service checks.
🤖 Generated with Claude Code