Skip to content

feat(streamdeck): a named pipe instead of a port, and no token at all - #55

Merged
DarrellVS merged 1 commit into
devfrom
streamdeck-named-pipe
Sep 23, 2026
Merged

DarrellVS merged 1 commit into
devfrom
streamdeck-named-pipe

Conversation

@DarrellVS

Copy link
Copy Markdown
Owner

The Stream Deck connection is now a named pipe instead of 127.0.0.1:43120, and the token is gone.

  • A browser cannot open a pipe, so the Host/Origin/DNS-rebinding checks are removed.
  • Windows only lets this account (plus admins/SYSTEM) write to the pipe, so the token, which any same-user program could already read, is removed.
  • Still HTTP over the pipe (socketPath), so every route and reply is unchanged.
  • The pipe name carries the profile; GoodBit writes it into the installed plugin (connection.json).
  • Settings drop the address/token rows; the plugin drops its connection inspector.

Gates: npm run check 860; streamdeck-check.mjs 15/15 (no token needed, no TCP port, the profile gets its own pipe, all key rules); streamdeck validate OK. Not benched: another Windows account being refused (needs a second account).

🤖 Generated with Claude Code

The Stream Deck server listened on `127.0.0.1:43120` behind a bearer token
and a hand-written Host and Origin check, because a loopback port is
reachable by any web page the user has open. It now listens on a named
pipe, the move the internal API already made:

- **A browser cannot open a pipe**, so the Host, Origin and DNS-rebinding
  checks have nothing left to stop, and are gone.
- **Windows decides who can write to it.** The default security
  descriptor gives write access to this account, administrators and
  SYSTEM only; a request is a write, so another account cannot send one.
- **So the token is gone too.** It only ever stopped web pages and other
  machines: anything running as the user could read it out of the
  plugin's settings, and that is exactly who can still reach the pipe.

Still HTTP, spoken over the pipe with `socketPath`, so every route and
reply is unchanged. **The pipe name carries the profile** (`pipe.ts`,
unit-tested): the default profile gets `\.\pipe\goodbit-streamdeck`, a
profile moved with `GOODBIT_USER_DATA` gets a hashed suffix, and GoodBit
writes which into the installed plugin's `connection.json`, so a dev build
never answers for the installed app.

Settings lose the address and token rows, the copy buttons and the
`streamDeckPort` / `streamDeckToken` keys. The plugin loses its connection
property inspector; the tag key keeps only its tag.

Gates: `npm run check` 860; `streamdeck-check.mjs` rewritten for the pipe,
15 checks, exit 0: the plugin gets in with no token, the app under test
listens on no TCP port, the profile's pipe is its own, and every key rule
as before. `streamdeck validate` successful; plugin 0.3.0. Not benched:
that another Windows account cannot write to the pipe, which needs a
second account and rests on the default descriptor.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@DarrellVS DarrellVS added this to the 3.5.0 milestone Sep 23, 2026
@DarrellVS DarrellVS added enhancement New feature or request stream-deck The Elgato plugin security Code scanning and hardening labels Sep 23, 2026
@DarrellVS DarrellVS self-assigned this Sep 23, 2026
@DarrellVS
DarrellVS merged commit 325c17d into dev Sep 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request security Code scanning and hardening stream-deck The Elgato plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant