Allow restricted data writes to its own restricted gatekeeper - #310
Draft
Maximo-Guk wants to merge 13 commits into
Draft
Allow restricted data writes to its own restricted gatekeeper#310Maximo-Guk wants to merge 13 commits into
Maximo-Guk wants to merge 13 commits into
Conversation
Preview:
|
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 04:01
18f44d4 to
2ac9a92
Compare
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 04:46
2ac9a92 to
513e542
Compare
darrinm
added a commit
to darrinm/cloudflare-os
that referenced
this pull request
Aug 24, 2026
Opening a Bot crashes the page: hook after an early return (cloudflare#310)
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 13:45
513e542 to
7be8dca
Compare
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 14:27
7be8dca to
dcf5c50
Compare
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 16:10
dcf5c50 to
ae7a3ff
Compare
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 19:19
ae7a3ff to
83d06ba
Compare
The restricted-data latch used to block every action once any sensitive
(containsRestrictedData) observation occurred. Carve out writes-to-self:
a latched workspace may still submit actions targeting the connections
that produced its restricted data -- sending the data back where it came
from reveals nothing new to that system -- while any other target, and
all web fetches, stay blocked.
Provenance is derived, not persisted: restrictedProducerIds() already
scans the never-deleted action log for restricted observations (under
either of the flag's names), with the invariant that the latch and the
producing record are written in one synchronous block, so a latched
workspace always yields a non-empty set. That makes the earlier design's
persisted producer-set singleton and its backfill migration unnecessary
-- the same scan IS the backfill, run on demand. If the set is ever
empty under the latch anyway, every target fails the membership check
and all actions are refused (conservative fallback).
Latched actions are never auto-approved: the human approving each write
is the interim mitigation for hidden-instruction injection riding in the
restricted data. The auto-approval gate, previously duplicated between
submitAction and the drainer, is factored into one exported predicate
autoApprovalRule() -- author verdict + user rule + not latched.
setAutoApprovedActionKind refuses to store a rule while latched (it
would never fire) and listPreApprovableActions offers nothing.
Accepted residual: with producers {A, B}, data observed from A may be
written back to B -- the carve-out is set-based, not per-producer. Every
such write is human-approved, and gatekeeper.ts's TODO(someday) already
flags the restricted mode's bluntness.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixture gatekeeper's doThing() now tags its poke with an actionKind and takes a per-action autoApprovable verdict, getAutoApprovableActions offers the kind, and applyAction succeeds, so tests can drive the real submit -> auto-approve -> apply round trip. The post-latch action test flips by design: the actor IS the producer, so its doThing() now pends (writes-to-self) while a second connection on the same account is still refused. New auto-approval-policy tests cover the happy auto-approve path and that a pre-latch rule stops firing once the workspace reads sensitive data -- the action pends, the rule surface refuses, and manual approval remains the path through. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…warnings Gatekeeper-authored warnings addressed to the human approver, for context the action's own content can't show -- e.g. "this conversation has read data from other accounts, which could leak into this write." - New optional `ActionDescription.operatorWarnings: string[]`. - A warning exists precisely to be read by a human, so autoApprovalRule() refuses any action carrying one, even with the author's verdict and a matching user rule; the drainer therefore stops at a warned action without skipping ahead. - Both approval surfaces (chat action card and the Activity panel) render the warnings as a prominent warning strip ahead of the description, and suppress the always-approve affordance on warned actions. - Unit tests for the predicate and drainer gates; integration test drives a warned poke through the real submit -> pend -> manual approve -> drain round trip via the test gatekeeper fixture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Brings in the MCP portal hidden-servers passthrough (MCP_PORTAL_HIDDEN_SERVER_IDS), which downstream deployments already pin, so a submodule pointing at this branch is a strict superset of that pointer rather than a rewind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Maximo-Guk
force-pushed
the
restricted-data-writes-to-self
branch
from
August 24, 2026 21:06
83d06ba to
fef8519
Compare
An in-flight facet RPC can outlive removeGatekeeper (the same race the restricted-observation refusal in authorizeObservation guards), so submitAction could persist a pending action naming a removed connection. Such a record can never be resolved: approveAction and rejectAction both dereference it through getGatekeeperFacet, which throws, and an awaitDecision agent turn then suspends forever. Require a live gatekeeper record before any write (refused ahead of the id allocation, so no record is left behind). This also closes the latched case: restrictedProducerIds deliberately survives removal, so carve-out set membership alone must not admit a write to a dead connection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The carve-out's prior rationale ("sending the data back where it came
from reveals nothing new") over-claims for the multi-producer and
broad-connection cases: the check is per-connection set membership, not
data provenance, so with producers {A, B} data observed from A may be
written back to B, and one broad connection can reach audiences beyond
where the data was read. State that residual in the
containsRestrictedData JSDoc and at the carve-out itself, naming the
mandatory human approval of every latched action as the interim
mitigation. The existing TODO(someday) policy framework remains the
full fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A latched workspace never auto-approves (autoApprovalRule refuses,
setAutoApprovedActionKind throws, listPreApprovableActions returns
nothing), but the UI still offered "Always approve" on pending actions
-- which could only error -- and rendered pre-latch rules as applying.
Thread the live GadgetMetadata.containsRestrictedData (already pushed by
the metadata subscription) into ChatInterface and Activity: restricted
workspaces no longer offer the always-approve affordance in either
surface, and the auto-approvals panel annotates each rule as suspended
("won't apply -- actions always require manual approval") with enabling
blocked while disabling stays possible, so a standing grant remains
revocable. Presentation-only: the backend gates are unchanged, and rules
are kept rather than cleared so revocation history stays intact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WIP ( DO NOT MERGE )