From 94b7a834cb844266ab194aa7dd0cd29df5cc9d1d Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Mon, 27 Jul 2026 12:26:47 +0200 Subject: [PATCH] fix(installer/windows): GameStream is opt-in, not on by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A user found this in their log and had never been offered a choice: WARN GameStream/Moonlight compat ENABLED (--gamestream): its pairing runs over plain HTTP and its legacy control encryption can reuse GCM nonces (security-review #5/#9) — an on-path LAN attacker could MITM pairing or recover input. Enable only on a TRUSTED network. They were right. The `gamestream` task carried no `Flags: unchecked`, so it was pre-ticked; and since a silent install takes the wizard's own task defaults (1839d756), a winget install turned it on with no checkbox ever shown. The host warns that this plane is a security downgrade on every single start, so having the installer enable it by default cannot be squared with our own advice — least of all on the path where nobody sees a wizard. Now unchecked, matching `allowpublicfw`, the other task with a security consequence. A default install therefore lands `PUNKTFUNK_HOST_CMD=serve`, the native-only host; Punktfunk's own clients are unaffected, since the native punktfunk/1 plane is always on. Unattended opt-in is `/MERGETASKS=gamestream`. Scope, deliberately: this changes FRESH installs only. `GamestreamParam` already omits the flag entirely unless `FreshHostInstall`, so no existing host has its choice touched by an upgrade, and anyone relying on Moonlight today keeps it. `DEFAULT_HOST_CMD` (the service's fallback when host.env carries no PUNKTFUNK_HOST_CMD line at all) is deliberately NOT flipped here: the installer always writes the line explicitly, so it does not affect a normal install, and inverting it would silently disable Moonlight for anyone whose host.env lost that line — a runtime regression that belongs in its own change, if at all. Docs corrected everywhere they stated the old default, since three of them now told users the opposite of what ships: the winget Agreement shown BEFORE install (it said "enabled by default" and gave the opt-OUT override), the Windows packaging README, and host.env.example. The `--override` example in the installer manifest is inverted with it (`/MERGETASKS=gamestream` to add, `!` to remove). Verified: [Tasks] + [Code] compile with ISCC 6.7.1 on the windows-amd64 runner (all optional features defined), and the winget catalogue rebuilds and passes 29/29 with the edited manifests. --- packaging/windows/README.md | 12 ++++++++---- packaging/windows/punktfunk-host.iss | 16 ++++++++++++++-- .../winget/unom.PunktfunkHost.installer.yaml | 7 +++++-- .../winget/unom.PunktfunkHost.locale.en-US.yaml | 13 +++++++------ scripts/windows/host.env.example | 14 +++++++++----- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/packaging/windows/README.md b/packaging/windows/README.md index 235d5217..07b8d7ce 100644 --- a/packaging/windows/README.md +++ b/packaging/windows/README.md @@ -60,10 +60,14 @@ parse breakage that silently failed installs on non-English boxes. **`PunktfunkWeb`** scheduled task (boot, SYSTEM, restart-on-failure → `web-run.cmd` → `bun` on `:47992`), opens TCP 47992, and starts it. It proxies the host's loopback mgmt API with the host's own `%ProgramData%\punktfunk\mgmt-token`. -- **GameStream (Moonlight) compatibility is a wizard task** (checked by default): the choice is passed - to `service install --gamestream=on|off`, which writes `PUNKTFUNK_HOST_CMD=serve --gamestream` (or - `serve`, the secure native-only host) into `host.env`. Upgrade-safe: a hand-customized - `PUNKTFUNK_HOST_CMD` is never overwritten. +- **GameStream (Moonlight) compatibility is a wizard task** (**unchecked** by default — it pairs over + plain HTTP, so it is opt-in like the Public-firewall task): the choice is passed to + `service install --gamestream=on|off`, which writes `PUNKTFUNK_HOST_CMD=serve --gamestream` (or + `serve`, the secure native-only host) into `host.env`. Unattended, add it with + `/MERGETASKS=gamestream`. Upgrade-safe: a hand-customized `PUNKTFUNK_HOST_CMD` is never + overwritten, and on an upgrade the task is inert entirely (the flag is omitted, so `host.env` + keeps whatever it already says) — change an existing host with + `punktfunk-host service install --gamestream=on|off` plus a service restart. - **Branded, modern wizard**: `WizardStyle=modern dynamic windows11` (Inno ≥ 6.6 — Windows-11-style controls following the system light/dark theme; pre-6.6 compilers fall back to plain `modern`), with the punktfunk lens mark on the side panel / header tile and a multi-size `punktfunk.ico` diff --git a/packaging/windows/punktfunk-host.iss b/packaging/windows/punktfunk-host.iss index 2ba052c8..cdd72fc7 100644 --- a/packaging/windows/punktfunk-host.iss +++ b/packaging/windows/punktfunk-host.iss @@ -160,8 +160,20 @@ Name: "installhdrlayer"; Description: "Install the HDR Vulkan layer (lets Vulkan #endif ; Host-config choice, applied via `service install --gamestream=on|off` (writes PUNKTFUNK_HOST_CMD ; in host.env; a hand-customized value is left alone). Checked = the Moonlight-compatible unified -; host (the common Windows setup); unchecked = the secure native-only host (Punktfunk clients only). -Name: "gamestream"; Description: "Enable GameStream (Moonlight) compatibility - lets stock Moonlight clients connect (uses legacy plain-HTTP pairing; for trusted LANs)" +; host; unchecked (DEFAULT) = the secure native-only host (Punktfunk clients only). +; +; OPT-IN, like allowpublicfw below and for the same reason: the host itself WARNs on every start +; that this plane pairs over plain HTTP and its legacy control encryption can reuse GCM nonces +; (security-review #5/#9), so an on-path LAN attacker could MITM pairing or recover input. A +; default-on security downgrade cannot be squared with that warning - least of all on the silent +; path, where the wizard never appears and 1839d756 makes an unattended install take these very +; defaults. Reported by a user who found the warning in their log and had never been shown a +; choice, because they installed through winget. +; +; Turning it on unattended is `/MERGETASKS="gamestream"`; on an UPGRADE this task is inert either +; way (GamestreamParam omits the flag unless FreshHostInstall), so an existing host keeps whatever +; host.env already says - changing it afterwards is `service install --gamestream=on|off`. +Name: "gamestream"; Description: "Enable GameStream (Moonlight) compatibility - lets stock Moonlight clients connect (uses legacy plain-HTTP pairing; for trusted LANs)"; Flags: unchecked ; Firewall scope, forwarded as `--allow-public-network` to `service install` / `web setup`. Unchecked ; (default) = accept connections on Private + Domain networks only (the trusted-network profiles ; punktfunk is meant for). Check ONLY for a network you trust that Windows classifies as Public (e.g. diff --git a/packaging/winget/unom.PunktfunkHost.installer.yaml b/packaging/winget/unom.PunktfunkHost.installer.yaml index 16e771d8..ad8e64b8 100644 --- a/packaging/winget/unom.PunktfunkHost.installer.yaml +++ b/packaging/winget/unom.PunktfunkHost.installer.yaml @@ -29,8 +29,11 @@ InstallerSwitches: # disclosures the wizard puts on screen are carried by Agreements/InstallationNotes in the # locale manifest instead. # - # To opt out of individual tasks, callers use Inno's ! negation via --override, e.g. - # winget install unom.PunktfunkHost --override "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /MERGETASKS=!gamestream" + # To CHANGE individual tasks, callers pass Inno's /MERGETASKS via --override: a bare name adds a + # task, a `!` prefix removes one. GameStream is opt-in (its plane pairs over plain HTTP), so + # enabling it unattended is the additive form: + # winget install unom.PunktfunkHost --override "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /MERGETASKS=gamestream" + # and dropping a default-on task is the negated form, e.g. /MERGETASKS=!trayicon # Task names: installdriver, installgamepad, installaudiocable, installhdrlayer, # gamestream, allowpublicfw, startservice, trayicon Silent: /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- diff --git a/packaging/winget/unom.PunktfunkHost.locale.en-US.yaml b/packaging/winget/unom.PunktfunkHost.locale.en-US.yaml index 8d0aaeef..67d33b3a 100644 --- a/packaging/winget/unom.PunktfunkHost.locale.en-US.yaml +++ b/packaging/winget/unom.PunktfunkHost.locale.en-US.yaml @@ -46,13 +46,14 @@ Agreements: redistributed under VB-Audio's bundling grant; the full notice is installed to %ProgramFiles%\punktfunk\licenses\VB-CABLE-NOTICE.txt. AgreementUrl: https://vb-audio.com/Cable/ - - AgreementLabel: GameStream (Moonlight) compatibility is enabled by default + - AgreementLabel: GameStream (Moonlight) compatibility is OFF by default Agreement: >- - The default install enables GameStream so stock Moonlight clients can connect. GameStream uses - legacy plain-HTTP pairing and is intended for trusted LANs only. To install without it, use - --override "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /MERGETASKS=!gamestream", or run - --interactive and clear the GameStream checkbox. It can also be changed later via - PUNKTFUNK_HOST_CMD in %ProgramData%\punktfunk\host.env. + Punktfunk's own clients work out of the box. Support for stock Moonlight clients is a separate, + opt-in plane, because it pairs over legacy plain HTTP and is intended for trusted LANs only. To + install WITH it, use --override "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + /MERGETASKS=gamestream", or run --interactive and tick the GameStream checkbox. It can also be + turned on later with `punktfunk-host service install --gamestream=on` (or via + PUNKTFUNK_HOST_CMD in %ProgramData%\punktfunk\host.env), followed by a service restart. AgreementUrl: https://docs.punktfunk.unom.io/docs/windows-host # Displayed after the install completes. The console password is generated per install, so it can diff --git a/scripts/windows/host.env.example b/scripts/windows/host.env.example index d7c8b20c..cd444fcc 100644 --- a/scripts/windows/host.env.example +++ b/scripts/windows/host.env.example @@ -33,11 +33,15 @@ PUNKTFUNK_SECURE_DDA=1 # Log level (info | debug | trace). Logs land in %ProgramData%\punktfunk\logs\. RUST_LOG=info -# The host subcommand the service launches. Default: `serve --gamestream` (native punktfunk/1 host -# ALWAYS on + the GameStream/Moonlight-compat planes). Use `serve` for a SECURE native-only host -# (no plain-HTTP pairing / legacy GCM nonce reuse — security-review #5/#9). The installer's -# "Enable GameStream (Moonlight) compatibility" task sets this; a custom value you write here is -# never overwritten by a reinstall/upgrade. +# The host subcommand the service launches. The native punktfunk/1 host is ALWAYS on; `--gamestream` +# adds the GameStream/Moonlight-compat planes, which pair over plain HTTP and reuse legacy GCM +# nonces (security-review #5/#9) — so `serve` alone is the SECURE native-only host. +# +# A Windows install writes this line explicitly from the installer's "Enable GameStream (Moonlight) +# compatibility" task, which is OPT-IN (unchecked) — so a default install lands `serve`. Only if +# this line is absent altogether does the service fall back to its built-in `serve --gamestream`. +# Change it later with `punktfunk-host service install --gamestream=on|off` + a service restart; a +# custom value you write here by hand is never overwritten by a reinstall/upgrade. #PUNKTFUNK_HOST_CMD=serve --gamestream # Multi-GPU boxes only: force the NVENC/Desktop-Duplication GPU by Description substring. Leave