Skip to content

Windows hardening batch: shared WebView2 profile across all tinyjs apps, named pipe without ACL, WINOPEN absolute paths + universal file access, full env honored in built apps #29

Closed

Description

@slabbdev

Second batch from the same pass as #22/#24/#26 — these four are code-read only
(no Windows machine here), each with the fix direction. Filing together because
they're the same surface class; happy to split them out.

1. One WebView2 profile shared by every tinyjs app on the machine

The launcher keeps its WebView2 user-data folder at
%APPDATA%\..\Local\launcher.exe-derived path — shared across all tinyjs-built
apps
. Consequences: cookies/localStorage/session state leak between unrelated
tinyjs apps; one compromised app reads (or poisons) every other app's web
storage; tinyjs build apps can't isolate from each other.
Fix: derive the profile dir from the app id (<app-id>\\EBWebView), like Electron
does per-app.

2. Single-instance named pipe: fixed name, no ACL (asymmetry with the #12 fix)

The Linux single-instance socket got a private, fail-closed path in v0.42.2
(#12, linuxInstanceSock) — good. The Windows twin still uses a fixed-name
named pipe with no ACL
, so any process in the session can connect and
impersonate/forge to it (same class of bug #12 fixed on Linux; the asymmetry is
the point — the fix pattern already exists in this codebase). Fix: per-app pipe
name + a DACL limited to the user's SID, matching the Linux posture.

3. WINOPEN from a wrapper: arbitrary absolute path + universal file:// access

A page-reachable win.open accepts absolute filesystem paths for its page
parameter, and pages opened that way get allow_universal_access_from_file_urls-
equivalent treatment — a wrapped page can open file:///C:/… content and read
it across origins. Fix: restrict WINOPEN page paths to the app bundle (like
macOS win.open needs an absolute page path within the app), or require the
same manifest opt-in as other filesystem surfaces.

4. Built apps honor TINYJS_HTML and the full environment

In built (packaged) apps on Windows/Linux, TINYJS_HTML and other launcher
environment variables are read from the process env first — a parent process
(or anything that can set the env of a launched app) can replace the app's page
or inject content without touching the bundle. Same class: TINYJS_INJECT,
UA overrides ride the env in built apps (macOS dev-only equivalents are
documented as dev-only). Fix: in built apps, ignore debug/supply env unless a
manifest flag enables it; read injection sources only from app resources.

Verification status

Honest labels: items 1, 2, 4 verified by code reading (current main 5bb2311);
item 3's components verified in code, the full runtime chain needs a Windows box.
If you want, point me at a Windows VM/CI and I'll turn 2 and 3 into repros the
way #22/#26 were done on macOS.

Activity

  1. tarwin commented on Oct 3, 2026

    @tarwin
    Owner

    Thanks @slabbdev — items 1 (per-app WebView2 profile) and 4 (built apps ignore inherited TINYJS_/WEBVIEW2_ env) are fixed in v0.45.0. Leaving this open for 2 (pipe ACL) and 3 (WINOPEN absolute paths).

  2. added 6 commits that reference this issue on Oct 3, 2026
  3. tarwin commented on Oct 3, 2026

    @tarwin
    Owner

    Thanks @slabbdev — items 2 (per-user, ACL-locked instance pipe with an owner check on every hand-off) and 3 (a page's win.open confined to the frontend dir or http(s)) are fixed in v0.46.0, along with a related one found on the way: the bridge↔launcher session pipe now requires a one-time token. With 1 and 4 in v0.45.0, that's all four.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions