Skip to content

web-client: any same-origin context can make an engine-less leader respawn its worker on demand #1354

Description

@FSM1

The gap

An engine-less leader gives the cipherbox-engine lock up when a port greeting names an account it cannot serve (#1337). The greeting arrives on the private MessagePort, which is untrusted input — the trust boundary is same origin, and same origin is not the same account.

So any same-origin context can dial the courier and send cb:portHello with an invented accountId, and the leader stands down, re-queues, is elected again, and spawns a fresh WASM engine worker. One postMessage buys a worker teardown plus a WASM instantiation, unauthenticated and unthrottled. Each stand-down also broadcasts cb:leaderGone, so every other tab rejects its in-flight work retryably.

What bounds it today

  • Only a leader with no login of its own ever stands down, so a signed-in tab cannot be made to give up a live engine. No session is disturbed and no vault data is reachable.
  • The no-attacker version of this loop is fixed: a tab whose own sign-in gave up stops greeting under that account (feat: derive web auth state from the engine and let an engine-less leader yield #1342), so ordinary tabs no longer drive it.
  • A same-origin context can already deny the engine outright by squatting the lock, and can spawn workers directly. What is new is the amplification, not the capability.

That is why this is a hardening item rather than a defect: it is CPU churn inside a trust boundary the design already grants.

Shape of the fix

Options, cheapest first:

  • Throttle the stand-down: at most one per elected term plus a cooldown before the same tab yields again, so a greeting flood costs one hand-off rather than one per message. Needs the injected clock rather than a direct Date.now.
  • Defer the worker spawn until a leader actually needs one. An engine-less leader has no engine to host, so a stand-down would cost only the lock hand-off and the amplification disappears. This is the deeper fix and the larger change: promote currently installs a LocalTransport unconditionally, and start on the leader path expects it.

Gate

packages/client unit suite: a greeting flood against an engine-less leader must not spawn a worker per greeting.

Related

Raised by the /security-review and /crypto-privacy-review gates on #1342 and accepted as residual there.

Part of #655

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp:webpackages/client + apps/web — WASM host, browser seams, React UIv2-buildv2 rewrite build slice

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions