cloudflare / cloudflare/agents

WebSockets state sync: clients can write state by default; consider a read-only mode

Open
#2,269 0 comments 0 reactions 1 assignee Claimed by @threepointone View on GitHub
enhancement
Dominant language
TypeScript
Stars
5.6k
Forks
711
Avg merge
1d 20h
Merged PRs (30d)
53

Description

## Problem

With `WebSockets({ state })`, any connected client can send a `cf_agent_state` frame and replace host state unless the host's `validateStateChange` rejects it, or the connection was marked readonly via the `readonly` policy or `setReadonly()`. Enabling sync therefore enables writes by default.

This matches Agent, where `validateStateChange` has always been the gate and `shouldConnectionBeReadonly` the per-connection switch, so #2257 kept parity deliberately. Devin flagged it on #2257 (`applyStateFrame`) as an easy way to expose writes unintentionally when a host only wanted to push state down.

## Possible shapes

- A `state: { sync: State, writable: false }` option (or `readonly: () => true` shorthand) that makes every connection readonly for state without touching the validator.
- Or accept the status quo and document the read-only recipe: `validateStateChange: (_, source) => { if (source !== "server") throw new Error("read-only"); }`, which works today and is already covered by tests.

Whichever is chosen should apply to Agent the same way, so the two hosts do not diverge.

## Where

- `packages/agents/src/websockets/options.ts`: `state`, `readonly`
- `packages/agents/src/websockets/websockets.ts`: `applyStateFrame`
- `docs/agents/lifecycle.md`: the `state` bullet

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.