Skip to content

security: authenticate the V1 pipe surface and hook.event/agent.activity (fixes #72) - #73

Merged
amirlehmam merged 1 commit into
amirlehmam:masterfrom
Rajveerx11:fix/72-pipe-auth
Jul 7, 2026
Merged

security: authenticate the V1 pipe surface and hook.event/agent.activity (fixes #72)#73
amirlehmam merged 1 commit into
amirlehmam:masterfrom
Rajveerx11:fix/72-pipe-auth

Conversation

@Rajveerx11

Copy link
Copy Markdown
Contributor

Fixes #72.

Any local process could spoof agent status, notifications, and diff refreshes through three tokenless pipe paths: every V1 text command, hook.event, and agent.activity. Since wmux already injects WMUX_PIPE_TOKEN into every shell it spawns, all legitimate telemetry senders (shell integration, Claude Code hooks, the CLI, the opencode plugin via the CLI) already have the token — keeping these paths tokenless only benefited processes that were never supposed to write state.

Changes

  • src/main/pipe-server.ts
    • PUBLIC_V2_METHODS trimmed to the two genuinely read-only methods (system.identify, system.capabilities). hook.event and agent.activity now require the per-instance token like every other V2 method.
    • V1 lines accept an auth <token> prefix (validated with the existing timing-safe tokensMatch). All V1 commands mutate UI state (notify, report_pwd, report_pr, shell state, …), so every command except the read-only ping now requires it. Unauthenticated lines get unauthorized back and are not forwarded to renderers.
  • src/cli/wmux.tssendV1 prepends the auth prefix (token already resolved from WMUX_PIPE_TOKEN / the APPDATA token file).
  • src/shell-integration/wmux-powershell-integration.ps1Send-WmuxMessage prepends the prefix, and the PR-polling background job receives the token via -ArgumentList and prefixes its report_pr line.
  • tests/unit/pipe-server.test.ts — new coverage: V1 rejected without/with wrong token (and not emitted), ping still public, hook.event/agent.activity rejected tokenless and accepted with the token.

No client migration needed: wmux-hook.ts and the CLI's sendV2 were already sending the token — it was just being ignored for these methods.

Not included (deliberately)

  • Per-surface ownership check on agent.activity — the token is per-instance, so the server can't verify which surface a caller owns without per-surface credentials. Requiring the token removes the anonymous spoofing this issue is about; per-surface tokens would be a separate, larger change.
  • Restrictive DACL on the pipe — Node's net.Server doesn't expose a security descriptor for named pipes, so this needs a native module or a different pipe implementation. The token now gates every state write, which was the load-bearing gap.

Testing

  • npm test — 162/162 pass (13 in pipe-server.test.ts, 4 new).
  • npm run build:main — clean.

🤖 Generated with Claude Code

…ivity (amirlehmam#72)

Any local process could previously spoof agent status, notifications, and
diff refreshes through three tokenless paths: all V1 text commands,
hook.event, and agent.activity. The legitimate senders (shell integration,
Claude Code hooks, the CLI) all run inside wmux-spawned shells and already
carry WMUX_PIPE_TOKEN, so tokenless access only benefited processes that
were never supposed to write state.

- Trim PUBLIC_V2_METHODS to the read-only system.identify /
  system.capabilities; hook.event and agent.activity now authenticate
  like every other V2 method.
- Require an "auth <token>" prefix on V1 lines; only the read-only ping
  stays public. Unauthenticated V1 state updates get "unauthorized" and
  are not forwarded to renderers.
- Send the prefix from the CLI sendV1 and the PowerShell integration
  (prompt reporting + the PR-polling background job).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@amirlehmam

Copy link
Copy Markdown
Owner

Merged and released in v0.17.0 — thank you for a genuinely well-scoped security PR.

What I especially appreciated on review: the allowlist got smaller instead of the auth getting bolted on per-method, the PowerShell integration's background PR-poller job was not forgotten (easy to miss — it opens its own pipe connection), and the tests cover the exact spoofing scenario from the issue (notify … agent needs your passwordunauthorized). All 162 tests green after merge.

The ownership check on agent.activity and the pipe DACL from your issue write-up are welcome as follow-ups.

tawman added a commit to tawman/wmux that referenced this pull request Jul 7, 2026
Syncs the fork with upstream master (release v0.17.0) — the first sync
carrying third-party code, security-gate reviewed before merge (PASS):

- amirlehmam#73 (Rajveerx11) pipe auth — security-positive: V1 commands now require
  an "auth <token>" prefix (ping stays public) and hook.event/agent.activity
  leave the tokenless V2 allowlist; timing-safe compare reused, clients
  (CLI sendV1, PowerShell integration) updated coherently, +4 auth tests.
  Closes the unauthenticated-local-pipe-write gap our own review flagged.
- amirlehmam#74 + maintainer CI commits — SignPath signing wired behind secrets (only
  egress is app.signpath.io with the repo's own secrets; inert on the fork),
  publisherName pinned via win.signtoolOptions, README updater-security docs,
  asarUnpack narrowed to node-pty prebuilds.
- Our merged amirlehmam#75 content (cli-bin OOTB, orchestrator resolver, skills
  lessons) arrives as no-ops; electron-builder cli-bin extraResources lands.
- No dependency changes (lock diff = version fields only).

Base bump 0.16.0 -> 0.17.0; fork version resets to 0.17.0-local.1.
Conflicts resolved: version files; .gitattributes (fork superset);
README.md + orchestration-state.sh (fork copies kept — hardening superset).
Fork CI repo-guard on release.yml survived the auto-merge (verified).

Verified: build:main + vite build clean, 169/169 tests, 0 vulns (full +
--omit=dev), security-touched files byte-identical to upstream.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants