Tighten WebView permission handler: allow only media/notifications from our own origin #22

Closed
opened 2026-09-27 16:57:15 -04:00 by jared · 1 comment
Owner

Tighten WebView permission handling (Linux and Windows)

Found during the Linux-calls research (2026-09-27), in src-tauri/src/lib.rs:

  • Linux (WebKitGTK): connect_permission_request calls request.allow() for every permission request, of every kind (camera, microphone, geolocation, notifications, …), from any frame.
  • Windows (WebView2): PermissionRequested auto-allows microphone, camera and notifications, but doesn't check which frame or origin is asking.

Current exposure is limited: our third-party frames (URL-preview embeds, room widgets) are created without camera/microphone in their allow= attribute, so the engine's Permissions Policy blocks those requests before they reach the handler. The call frame is the only one allowed media. Still, the handler is the last line of defence and shouldn't grant everything.

Proposal

  • Linux: allow only UserMediaPermissionRequest (mic/camera/screen) and NotificationPermissionRequest, and only when the requesting origin is the app itself (the tauri-plugin-localhost origin). Deny everything else.
  • Windows: additionally check args.Uri() against the app's origin.
  • Tests: a room widget or embed asking for the mic gets denied; calls, screenshare and notifications keep working.

Low priority; defence in depth.

## Tighten WebView permission handling (Linux and Windows) Found during the Linux-calls research (2026-09-27), in `src-tauri/src/lib.rs`: - **Linux (WebKitGTK):** `connect_permission_request` calls `request.allow()` for **every** permission request, of every kind (camera, microphone, geolocation, notifications, …), from any frame. - **Windows (WebView2):** `PermissionRequested` auto-allows microphone, camera and notifications, but doesn't check which frame or origin is asking. **Current exposure is limited:** our third-party frames (URL-preview embeds, room widgets) are created without `camera`/`microphone` in their `allow=` attribute, so the engine's Permissions Policy blocks those requests before they reach the handler. The call frame is the only one allowed media. Still, the handler is the last line of defence and shouldn't grant everything. ### Proposal - **Linux:** allow only `UserMediaPermissionRequest` (mic/camera/screen) and `NotificationPermissionRequest`, and only when the requesting origin is the app itself (the tauri-plugin-localhost origin). Deny everything else. - **Windows:** additionally check `args.Uri()` against the app's origin. - **Tests:** a room widget or embed asking for the mic gets denied; calls, screenshare and notifications keep working. Low priority; defence in depth.
jared added the enhancementpriority: lowarea: native labels 2026-09-27 16:57:15 -04:00
Author
Owner

Fixed by #26, merged. The permission handler grants mic/camera/notifications only to the app's own origin, and media only to the call page's origin. Everything else is denied (Linux) or left to WebView2's own prompt (Windows).

Windows smoke test on the published nightly 4.12.371: the real installer, installed and driven on the windows runner (run 2292), passed 9/9:

check result
boots to the login screen ✅
local server listening ✅ 127.0.0.1 (was ::1 only before #27)
microphone for the app ✅
call page from its own origin ✅ http://127.0.0.1:44548
call page reading the app's storage ✅ SecurityError
call page gets the microphone ✅
microphone for a foreign page ✅ NotAllowedError (http://localhost:9333/)
Credential Manager round trip ✅ supported, round trip, restored
Fixed by #26, merged. The permission handler grants mic/camera/notifications only to the app's own origin, and media only to the call page's origin. Everything else is denied (Linux) or left to WebView2's own prompt (Windows). **Windows smoke test on the published nightly 4.12.371**: the real installer, installed and driven on the `windows` runner (run 2292), passed **9/9**: | check | result | |---|---| | boots to the login screen | ✅ | | local server listening | ✅ `127.0.0.1` (was `::1` only before #27) | | microphone for the app | ✅ | | call page from its own origin | ✅ `http://127.0.0.1:44548` | | call page reading the app's storage | ✅ **SecurityError** | | call page gets the microphone | ✅ | | microphone for a foreign page | ✅ **NotAllowedError** (`http://localhost:9333/`) | | Credential Manager round trip | ✅ supported, round trip, restored |
jared closed this issue 2026-09-30 21:07:46 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny-desktop#22