Only the latest release on the Releases page receives fixes. StreamTweak shows when a newer release is out.
Please do not open a public issue for a security problem.
Report it privately through GitHub: Report a vulnerability (Security tab → Report a vulnerability). Include the version, what an attacker can do, and the steps to reproduce it.
StreamTweak is maintained by one person, so there is no fixed response time — but a security report is read before anything else, and you will get an answer in the advisory thread. Fixes ship as a normal release, with the advisory published once users have had the update available.
StreamTweak runs on the PC you stream from. It is made of three parts:
StreamTweakUI.exe— the tray app, running as the signed-in user, without administrator rights.StreamTweakService.exe— a Windows service running as LocalSystem, which performs the few operations that need administrator rights.StreamTweak.Core.dll— shared code, loaded by the tray app.
Changing a network adapter's link speed needs administrator rights. Asking for them with a UAC prompt every time a stream starts — on a PC nobody is sitting at — would make the feature useless, so StreamTweak follows the usual Windows pattern: the administrator consents once, at installation, and a small service does the privileged work afterwards. It is not a way around UAC: the service can only be installed by an administrator, through the setup's own elevation prompt, and it is listed in Services as StreamTweak Speed Service.
The service accepts requests only through a local named pipe (StreamTweakService), never from the network, and it does not run arbitrary commands. It knows a fixed set of operations, each checked before it runs:
| Operation | What it may touch |
|---|---|
| Set the link speed | The *SpeedDuplex property of an existing network adapter — only to a value its driver lists — then restarts that adapter |
Write a streaming server's apps.json |
Only a file named apps.json inside a Sunshine, Apollo, Vibeshine or Vibepollo folder under Program Files or ProgramData |
| Swap / restore the host's tile pictures | Only desktop.png and steam.png in the assets folder of one of those servers, keeping a backup of the originals — and only with the two pictures StreamTweak installs beside the service |
| Scan for and install Windows updates | Through the Windows Update Agent, only when asked |
| Read GPU power | Read-only NVIDIA readings (NVML) for the session history; it never sets a limit |
| Restart the streaming server (10.0.0) | Only the service named SunshineService or ApolloService, only when its own binary is tools\sunshinesvc.exe inside the folder of the server whose apps.json StreamTweak writes, and only through the Service Control Manager — see Sync and restart below |
Only StreamTweak's own tray app may talk to it. Any signed-in user can open the pipe, but the service then asks Windows which process is on the other end and refuses every request unless that process is the StreamTweakUI.exe installed next to the service, in the Program Files folder that only administrators can write to. Paths are normalised before they are compared, so .. segments and look-alike folders (C:\Program FilesX) do not pass.
StreamLight, the client, talks to StreamTweak over TCP port 47998 on the local network (or Tailscale). The setup opens that port in Windows Firewall with a rule called StreamTweak Bridge, limited to StreamTweakUI.exe; the uninstaller removes it.
- Authentication is mandatory. Apart from
CAPS(which says that authentication is required) andENROLL(a request to be approved), every command must be preceded by an RSA-SHA256 signature made with the client's Moonlight certificate. The host verifies it against the certificate it approved, rejects timestamps outside ±60 seconds and rejects replays. - A client is approved once, by the person at the host. An
ENROLLrequest only puts a dialog on the host's screen with the client's name, address and a 4-digit PIN that the client shows too; nothing is trusted until someone compares the two and clicks Approve. An approved client can be revoked from the Clients page. - Commands that act on the PC — sleep, restart, shut down, Windows Update, link speed, clipboard — run only when the signature verifies.
- Host management (10.0.0) is a second, per-device permission, set on the Clients page and chosen at approval (Approve with host management / Approve / Deny; closing the dialog denies). Only a device that holds it can change this host's settings from StreamLight's host section, and what it can change is a short, fixed list of switches over state that already exists here: whether an app in Apps is managed (
SETAPP, naming the app by a 16-hex-digit hash of its path, so no path travels back), spatial audio on or off (SETAUDIO), NVIDIA Sentinel's auto-restore (SETSENTINEL, refused without a saved profile). No path, file or command line is ever accepted from a client, and the link-speed permission is not among the things a client can write. The section's reads (DASHBOARD,APPS,NVIDIA, and the session history:SESSIONS,SESSION,SERIES,COVER) are signed likeSTATSand change nothing; sessions are named by their short id, covers and app icons are sent as pictures, not as paths. Devices approved before 10.0.0 were given the permission on upgrade — they could already power the host off — and are listed once on the Clients page so it can be withdrawn. - Sync and restart (10.0.0) and pairing with a Hue bridge (10.1.0) are the two actions a client can ask for beyond those switches — see the next two sections. The Hue Sync rules (
SETHUE) are switches like the ones above. - The shared clipboard (can be switched off on the host) is encrypted with AES-256-GCM under a key made for each stream, sent to the client wrapped with RSA-OAEP for its certificate, and discarded when the stream ends.
StreamLight 8.0's Library tab can ask the host to sync its game library and restart the streaming server, because none of Sunshine, Apollo, Vibeshine or Vibepollo rereads apps.json while it runs. Restarting a program that runs as SYSTEM is the most sensitive thing a client can ask for, so it is fenced on three levels.
What the client can send. One fixed verb with no arguments, LIBSYNC, and one read: LIBRARY for the list and the progress, each game named by a 16-hex-digit hash of its name. No picture travels: StreamLight draws the covers it already has from the streaming server. No game, path, service name or command travels: the client cannot choose what is synced or which server restarts, only ask for the sync that the host would run on its own schedule. LIBSYNC runs only with a verified signature and the device's Host management; the host refuses it with a reason:
ERR_STREAMING— a stream is live from any client (the server's UDP sockets, the same probe that ends forgotten sessions): a restart would cut it;ERR_GAME_RUNNING— the server still has a game open, a paused session for instance: stopping the server closes the game it launched (proc.terminate()on exit, read in Vibeshine 2.0.1);ERR_BUSY— a sync or a restart is already under way, or one finished less than two minutes ago;ERR_NO_SERVER— no streaming server found, or its service does not pass the checks below.
What the sync does. The automatic sync, not the manual one: games excluded on the host stay excluded. It writes apps.json through the existing service operation, which accepts only that file in a server's folder.
What the service will restart. The tray app asks the service for a restart through the named pipe — as for every service operation, only StreamTweakUI.exe installed next to the service is answered. The request names one of two fixed services, SunshineService (Sunshine, Vibeshine) or ApolloService (Apollo, Vibepollo); the service then checks, itself and before touching anything, that:
- the service exists and runs as LocalSystem;
- its binary, read from the service's own configuration (
Win32_Service, which the Service Control Manager keeps), istools\sunshinesvc.exewithsunshine.exebeside thetoolsfolder, under Program Files or ProgramData — a service's configuration can be changed only by an administrator, which is what makes this binary trustworthy (ProgramData alone would not be: ordinary users may create folders there); - that folder holds a
config\apps.json. The tray app names the service whose folder holds theapps.jsonit just wrote, so with two servers installed the one that was synced is the one restarted; - no stream is live, checked again at this point.
It then stops the service and starts it again through the Service Control Manager only. The server's own service stops it gracefully and waits up to 20 seconds before forcing it; StreamTweak never kills sunshine.exe, which would also trip the crash-loop guard of Vibeshine and Vibepollo. A start is attempted even when the stop times out, so the server is not left down. Paired clients are kept by the server across the restart.
What the client sees. The progress (scanning → writing → stopping → starting → waiting for the server) through LIBRARY, which keeps answering during the restart because the bridge is not part of the streaming server. The restart is done when the service runs and the server answers again, within about 60 seconds; past that the client is told it failed and to look at the host. While it lasts, the host shows as offline to Moonlight-protocol clients; StreamLight knows why and says so.
If Vibeshine's or Vibepollo's own Steam sync is on, Steam games would be listed twice; the client warns before the sync, and the host does not override either program.
Clear library, on the host only. The Library page also has Clear library: the same job, whose first step takes every entry StreamTweak wrote out of apps.json (the server's own entries stay) and empties StreamTweak's list, followed by the same restart, the same checks and the same refusals. No bridge verb starts it: a client can only sync.
A Philips Hue bridge streams to one entertainment area at a time, and Hue Sync takes the lights as soon as it starts syncing. When the host is woken from a client whose Hue Sync is already syncing, the host's Hue Sync starts with Windows and takes the lights away, and the client's Hue Sync does not get them back by itself. StreamTweak 10.1.0 can start Hue Sync on the host itself, and only while no other device is syncing. StreamLight 8.4.0's Hue Sync tab shows it and sets it.
What StreamTweak does with the bridge: it only reads. Once paired it asks the bridge which entertainment areas exist, how many lights each has, which one is streaming and which app opened that stream — the app's name as the bridge lists it, for example Hue Sync#FOGGY-STREAM. It never turns a light on or off, never starts or stops a stream, never changes a scene, a light or an area, and never removes an app from the bridge.
- Pairing needs the bridge's button, pressed by someone in the room. Started from the host or from a client, StreamTweak asks the bridge for a key for 60 seconds and then stops. The key is kept in
config.json, encrypted with Windows DPAPI for the signed-in user (CryptProtectData, no extra library). Unpair on the host forgets it; the entry stays on the bridge until it is removed from the Hue app. - Only the bridge on the local network. Its address comes from Hue Sync's own settings on this PC or from mDNS (
_hue._tcp), never from a client. StreamTweak talks to it over HTTPS on the local network only, with no Hue account and no cloud. Before pairing, the bridge's certificate must chain to one of Signify's two Hue root CAs (root-bridgeandHue Root CA 01, built into StreamTweak) and name the bridge's id (10.1.1; until then the name was the only check). The certificate seen at pairing is pinned: a different one later stops StreamTweak talking to that bridge until it is paired again — unless it chains to Signify and names the same bridge, a certificate re-issued by a firmware update, which becomes the new pin. - What leaves the host, and only to an approved client: the area names, the number of lights in each, which one is streaming and the name of the app streaming to it; the bridge's model; whether Hue Sync is installed, running or waiting here, and whether it starts with Windows by itself; the rules, with the name of the device they give way to. Never a key, an address, or the bridge's list of apps.
What StreamTweak may start: only Hue Sync, as the signed-in user. Hue Sync is found where its installer registered it — the Windows Uninstall entry named Hue Sync, else its folder under Program Files — and started by the tray app, without administrator rights; the LocalSystem service has no part in any of this. It is started at three moments, each time only if the rule below lets it: when StreamTweak starts, when a session ends and StreamTweak reopens the apps it closed (Setup › Apps), and once a minute while it is waiting. StreamTweak never closes Hue Sync because of what the bridge says: closing it when a session starts is the existing Setup › Apps feature, unchanged. Hue Sync's own start with Windows (a startup task of its package) is never changed either; StreamTweak reads whether it is on and says so, because it would start Hue Sync before StreamTweak could check.
The rule. Wait while the lights are in use, off by default: Hue Sync is started only when no area of the bridge is streaming. Give way to: any device, so any stream holds it; or this device, so only a stream opened by Hue Sync on the device that chose the rule holds it. That device is matched by name — the name it enrolled with on this host against the computer name Hue Sync writes after # on the bridge. A wrong match can only make the host wait when it need not, or not wait; it gives no one access to anything.
What the client can send. One read, HUESYNC, signed like STATS. Three writes, each with a verified signature and the device's Host management:
HUEPAIR— start the 60-second pairing (ERR_BUSYwhile one is under way,ERR_NO_BRIDGEwhen no bridge is found);SETHUE HOLD ON|OFF— the first rule;SETHUE GIVEWAY ANY|THIS— the second;THISrecords the device that signed it.
No address, path, key, area name or command line is accepted from a client. Taking the lights back is done by the client on its own PC — StreamLight restarts its own Hue Sync, which then takes the lights — and asks nothing of the host: the host is never asked to close Hue Sync, and no verb can make it.
Installation:
- installs to Program Files and registers StreamTweak Speed Service (LocalSystem, automatic start, restarted by Windows if it stops) with its path quoted — unquoted before 10.1.1; a folder chosen outside Program Files is given Program Files' permissions, so only administrators can change what the service runs, and the system tools the setup calls are taken from Windows' own folder;
- adds the StreamTweak Bridge firewall rule for TCP 47998, and removes block rules that an earlier "Windows Security Alert" answer may have left on
StreamTweakUI.exe; - installs the .NET 10 runtime (.NET 8 before 10.2.0) and the Windows App SDK runtime if they are missing.
While running, and only for the features you turn on: the network adapter's link speed, spatial audio, the games listed by your streaming server, the server's Desktop/Steam tile pictures, closing and reopening the apps you list in Setup › Apps, starting Hue Sync only while the lights are free (Setup › Hue Sync, with the Hue bridge's key kept in config.json), start with Windows (a Run entry or a scheduled task), and — when an approved client asks — sleep, restart, shutdown, Windows Update and, with Host management, a library sync with a restart of the streaming server.
The uninstaller (Settings → Apps) stops and deletes the service and removes the firewall rule and the autostart entry or task. A link speed StreamTweak changed is restored by StreamTweak when a client asks for it or from the tray, so put it back before uninstalling.
Releases are built on GitHub Actions from this repository (.github/workflows/build-windows.yml); release assets carry a SHA-256 digest on the release page. Since 9.2.4 every file StreamTweak ships that is not its own is signed by Microsoft: SQLite is Windows' own winsqlite3.dll, and the tray icon is drawn with the Windows API directly instead of a third-party library.