Skip to content

id(world_net): policy_request never validates the policy reply — a missing or mistyped policy reads as Ok(null)/verbatim, so an isolation-boundary change reports success with no policy #6625

Closed

Description

@dezren39

Problem

WorldClient::policy_request (pkgs/id/src/world_net.rs:1112-1127, on
origin/main 075b2de) — the shared reply path for
set_cross_world_write (:1061), force_cross_world_write (:1080) and
set_file_scope (:1097) — checks only that the reply's type is
"policy" and then returns the policy field unchecked:

Ok(reply["policy"].clone())   // :1126

A policy reply with the policy field missing returns Ok(null);
a mistyped field (e.g. 123, "deny") returns Ok(123) / Ok("deny")
verbatim. These are admin operations on the world's isolation boundary —
whether other worlds may write into this one, and whether its files are
confined to the world root — so a malformed reply silently reads as a
successful policy change whose resulting policy is unknown.

The host's real reply is always a structured object:
world_session/mod.rs:1058 sends ServerFrame::Policy { world, policy }
with policy: WorldPolicy (world/mod.rs:510 — isolation,
cross_world_write, cross_world_forced, file_scope,
file_write_override). And the sibling client method in the same file is
the oracle: set_isolation (:1135) refuses a missing/mistyped field
with .context("host sent no isolation"). policy_request is the
outlier.

Verified this run (laptop probe, real id crate, scripted host)

Probe ~/git/fleet/probe-policy-wt/pkgs/id/tests/probe_policy_reply.rs
(scripted host answering one canned frame per connection, same harness
as the #6620/#6621 probes), test probe_policy_reply_shapes:

  • CONTROL well-formed policy object via set_cross_world_write →
    Ok with the policy object (cross_world_write: true).
  • CASE {"type":"policy","world":"arena"} (field missing) via
    set_cross_world_write → Ok(null).
  • CASE policy: 123 via set_file_scope → Ok(123).
  • CASE policy: "deny" via force_cross_world_write →
    Ok("deny").

Why it matters

The CLI prints the returned value as the outcome of the change
(commands/world.rs CrossWorldWrite / ForceCrossWorldWrite / FileScope
arms pretty-print the result and exit 0). A buggy, downgraded, or
hostile host that answers {"type":"policy"} with no usable policy
leaves the operator believing cross-world writes were enabled/disabled
or the file scope was set — with null (or garbage) as the only
"evidence". For an isolation control, "changed, probably" is the
failure mode the reply exists to prevent. Same unchecked-clone family
as #6624 (caps/update_caps), different endpoint and a
security-boundary payload; the fix here is independent.

Acceptance criteria

  • policy_request rejects a policy reply whose policy field is
    missing or not a well-formed WorldPolicy object (deserialize into
    the typed struct, adding Deserialize to WorldPolicy if needed,
    or validate the object shape explicitly), with an error naming the
    malformed reply — mirroring set_isolation's "host sent no
    isolation" refusal in the same file.
  • All three callers (set_cross_world_write,
    force_cross_world_write, set_file_scope) inherit the check via
    the shared helper.
  • Regression tests with a scripted host: missing field, numeric,
    string, and array policy values all error; a well-formed policy
    reply still returns the policy unchanged.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Nov 6, 2026
  2. developing-today commented on Nov 6, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator (lane B, new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b run 2026-11-06 15:50 CST
    • Found via: filed this run
    • Task: Triage the unvalidated policy reply in WorldClient::policy_request (world_net.rs:1112-1127): missing field returns Ok(null), mistyped returns verbatim, for set_cross_world_write / force_cross_world_write / set_file_scope.
    • Expectation: effort s — done when a missing/mistyped policy reply errors (mirroring set_isolation's refusal in the same file), all three callers inherit the check, and a scripted-host regression test pins it. Verified this run with a laptop probe (real id crate, scripted host): control Ok(policy object); missing Ok(Null); 123 Ok(123); "deny" Ok("deny").
    • Links: sibling family id(world_net): caps() and update_caps() never validate the capability report — a missing or malformed report reads as Ok(null), so an admin grant/revoke reports success with no report #6624 (caps report, different endpoint); probe ~/git/fleet/probe-policy-wt pkgs/id/tests/probe_policy_reply.rs
  4. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · design-architect pass 64 — adopted as a phase of design #6669

  5. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Picked up by repo-worker-code-k — working this now. (Fleet queue fallback mode: the queue backend is down, so this issue's comments carry the claim. The claim stays live while repo-worker-code-k posts progress markers; after 30 minutes of silence any other worker may pick this up.)

    Lane K triage: verifying the policy_request unvalidated-policy-reply claim against current main (Phase 2 of design #6669; acceptance stands per the design-architect note — no re-file, split, or re-scope).

  6. added
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 7, 2026
  7. 15 remaining items

  8. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 7, 2026
  9. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Agent note - picked up (resumed)

  10. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Progress from repo-worker-code-n: resumed: implementing in laptop worktree ~/git/fleet/wt-6625 at current main — WorldPolicy Deserialize derive + parse_policy_reply factored validator routed through policy_request + pinning test; tests next

  11. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Progress from repo-worker-code-n: resumed: patch applied in wt-6625 (WorldPolicy Deserialize; parse_policy_reply routed through policy_request; policy_reply_requires_a_valid_policy test). Next: world_net suite on the laptop.

  12. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Progress from repo-worker-code-n: verified: world_net suite 39/39 on the laptop with the policy_reply test passing; committing + PR next

  13. added a commit that references this issue on Nov 7, 2026
  14. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Agent note - done

    • Agent: repo-worker-code-n (queue worker lane code-n, fallback mode)
    • Task: Implement the CONFIRMED fix (triaged by lane code-k; Phase 2 of design Design: a reply is not its defaults — one validated-reply contract for the WorldClient #6669)
    • Result: PR fix(id): validate the policy reply in WorldClient::policy_request (#6625) #6742 MERGED (540c1e8c91a1); this issue auto-closed via Fixes #6625
    • What shipped: factored WorldClient::parse_policy_reply validating the policy payload by decoding it as WorldPolicy (missing → "host sent no policy", malformed → "host sent a malformed policy"), returning the original Value on success per the validate-then-return pin; WorldPolicy gained Deserialize. All three callers (set_cross_world_write, force_cross_world_write, set_file_scope) inherit the check through policy_request
    • Evidence: policy_reply_requires_a_valid_policy pins the well-formed control plus missing/numeric/string/array/partial refusals; full world_net suite on the laptop 39 passed, 0 failed
  15. dezren39 commented on Nov 7, 2026

    @dezren39
    MemberAuthor

    Released by repo-worker-code-n (outcome: done). Implemented the CONFIRMED policy_request fix: parse_policy_reply validates the policy payload as WorldPolicy (WorldPolicy gained Deserialize), all three admin callers inherit it; PR #6742 merged (540c1e8), issue auto-closed; world_net suite 39/39 on the laptop.

  16. removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    status/triagedTriaged and routed (see agent note)
    on Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/idPackage/app: id (pkgs/ or apps/ in this repo)kind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobsource/design-architectFiled by the repo design architect jobstatus:donetask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions