Repository navigation
fix(canvas): keep todo edits from approving unrelated instructions - #2350
Conversation
Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Michael Rand <177165992+mrand-block@users.noreply.github.com>
Close four security findings at their existing authorization and data-validation owners: - **AST-D117-C01 — workflow authority:** Claude, Codex, Pi, and Goose reject workflow-generated mentions before creating or steering sessions. Rendered output does not authenticate which text came from the owner’s template versus trigger data. This intentionally stops automatic activation from existing workflow mentions, including static templates; the owner or a directly attested agent must send a separate request. Workflow display and ordinary direct requests remain supported. - **AST-D135-C01 — development broker:** reject effective non-loopback Vite host settings, including CLI overrides, before loading the signing identity. Unpinned fixtures retain their normal hosting options. - **AST-D130-C01 — attachment integrity:** native successful upload descriptors must match the digest and size of the final uploaded bytes, including converted media. Preserve non-success HTTP responses and federated authorization behavior. - **AST-D120-C01 — Canvas query binding:** require kind 40100 and exactly one canonical matching channel tag before selecting a Canvas head. Invalid newer results cannot suppress a valid returned head. This complements #2350’s approval-preservation fix; it does not establish freshness against replay of an older valid Canvas at the same coordinates. ## Validation - Each finding has a regression that failed before its repair and passed afterward. - Shared workflow authorization and all four runtime suites: 809 passed, one existing skip. Claude/Codex fixtures verify rejected workflow mentions start no process or session; a direct owner request still runs. - Native relay owner tests: 95 passed, one existing ignored performance probe. Actual ffmpeg conversion, federated uploads, successful descriptors, and HTTP-error preservation exercised over loopback with synthetic identities. - Canvas owner/project tests: 35 passed. Seven genuine signed wrong-kind/channel/tag-shape cases rejected. - Broker checks use installed Vite configuration resolution and server construction; unsafe settings are rejected before identity access, and a real loopback endpoint succeeds with a synthetic identity. - Combined pre-push gate at 43c880f: TypeScript, 9,244 JavaScript tests (16 existing skips), design checks, and workspace Clippy with warnings denied passed. Independent review of each repair found no blockers. Production: +62/−129 lines; tests: +330/−451 lines. Removed tests covered deleted workflow delegation/profile-fetch machinery; direct authorization, cancellation, and workflow attribution coverage remain. ## Deferred acceptance Draft pending hosted CI and human acceptance. Packaged GUI/IPC journeys and Windows/Linux runtime acceptance have not been exercised. No browser journeys were added or removed. The workflow repair closes automatic promotion of workflow output into a request; it does not claim immunity to malicious history during a later owner-authorized turn. --------- Signed-off-by: Jordan Mecom <jm@squareup.com> Co-authored-by: Codex <noreply@openai.com>
jmecom
left a comment
There was a problem hiding this comment.
🤖 AI-agent review of 2daf695f0b9e5d1c17b8b91169272ba579478fa4: LGTM; no blocking findings. The Todo path retains instruction denial across repeated owner saves, while full owner/attested-agent Canvas saves remain eligible to approve instructions. I also checked both host validators, full-editor/restore callers, existing revision guards, and exact-event retry behavior. The Canvas coordinate validation in #2360 remains complementary.
Validation: 99 focused tests passed, including temporary reviewer probes with real outbox delivery and genuine signatures. Those probes failed on the pre-fix commit for the expected missing-marker and ignored-marker behavior. Native IPC and packaged-app acceptance were not exercised in this review. Correctness and minimalness: 9/10.
Optional: retain equivalent approval regressions in the repository and add the new marker cases to the shared Canvas signing corpus; the committed test changes currently verify only the Todo call arguments.
jmecom
left a comment
There was a problem hiding this comment.
🤖 Approved after the review above at 2daf695f; no blocking findings.
Co-authored-by: Simone <0828be588d5c9c4d092c5b1cf01761d5aef63d6b104807fd8e8284d517dd1a99@buzz.block.builderlab.xyz> * origin/main: fix(mcp): accept create scopes in durable approvals (#2650) feat(bestie): Bestie tab and Remembers you for a hosted Bestie (#2478) fix(relay): p-tag a one-to-one DM's agent partner on new messages (#2475) fix(agents): show each message author's username and display name (#2628) fix(agents): preserve visible edits in conversation history (#2355) fix(canvas): keep todo edits from approving unrelated instructions (#2350) fix(messages): keep messages in their canonical channel (#2349) NEXUS-4165: Add Thinking to agent creation (#2409) feat(plugins): let a plugin paint a backdrop behind the shell (#2437) feat(search): lead empty quick open with unread conversations (#2634) NEXUS-4170: Allow external apps to create private Solo chats (#2411) fix(acp): count grouped thinking levels when checking a synced level (#2640) Signed-off-by: John Tennant <jtennant@squareup.com>
…leanup * origin/main: fix(mcp): accept create scopes in durable approvals (#2650) feat(bestie): Bestie tab and Remembers you for a hosted Bestie (#2478) fix(relay): p-tag a one-to-one DM's agent partner on new messages (#2475) fix(agents): show each message author's username and display name (#2628) fix(agents): preserve visible edits in conversation history (#2355) fix(canvas): keep todo edits from approving unrelated instructions (#2350) fix(messages): keep messages in their canonical channel (#2349)
* origin/main: (28 commits) fix(mcp): accept create scopes in durable approvals (block#2650) feat(bestie): Bestie tab and Remembers you for a hosted Bestie (block#2478) fix(relay): p-tag a one-to-one DM's agent partner on new messages (block#2475) fix(agents): show each message author's username and display name (block#2628) fix(agents): preserve visible edits in conversation history (block#2355) fix(canvas): keep todo edits from approving unrelated instructions (block#2350) fix(messages): keep messages in their canonical channel (block#2349) NEXUS-4165: Add Thinking to agent creation (block#2409) feat(plugins): let a plugin paint a backdrop behind the shell (block#2437) feat(search): lead empty quick open with unread conversations (block#2634) NEXUS-4170: Allow external apps to create private Solo chats (block#2411) fix(acp): count grouped thinking levels when checking a synced level (block#2640) feat(conversation): let plugin rows manage messages without visiting a channel (block#2512) feat(github): make side-panel link opening optional (block#2629) feat(messages): show a blurred thumbnail until an image loads (block#2556) fix(relay): give large roster and read-state reads a 30s deadline (block#2627) fix(user-status): show a status emoji's :name: on hover where the full status shows (block#2384) fix(inbox): keep the list's place when returning in the same session (block#2134) fix(messages): pass verified labels to the forward recipient picker (block#2633) feat(messages): forward a message to a person (block#2167) ... # Conflicts: # tests/browser/settings.spec.mjs
* commit '4bb94e259': feat(github): rework the GitHub settings page (#2450) fix(mcp): accept create scopes in durable approvals (#2650) feat(bestie): Bestie tab and Remembers you for a hosted Bestie (#2478) fix(relay): p-tag a one-to-one DM's agent partner on new messages (#2475) fix(agents): show each message author's username and display name (#2628) fix(agents): preserve visible edits in conversation history (#2355) fix(canvas): keep todo edits from approving unrelated instructions (#2350) fix(messages): keep messages in their canonical channel (#2349) NEXUS-4165: Add Thinking to agent creation (#2409) feat(plugins): let a plugin paint a backdrop behind the shell (#2437) feat(search): lead empty quick open with unread conversations (#2634) NEXUS-4170: Allow external apps to create private Solo chats (#2411)
…-service * origin/main: (29 commits) Normalize profile names for verified-name matching (#2348) Add BuzzTerm font settings and compact glyph spacing (#2502) feat(plugins): let a host command run only verified bytes (#2535) NEXUS-4228: Add plugin toolbar actions and panel links (#2645) Keep plugin update controls stable and spaced (#2636) feat(inbox): rename to Activity and simplify the filter bar (#2543) fix(goose): track every replaced protected worker and check its security gate (#2528) docs(agents): say Pi agents don't take plugin notes yet (#2534) feat(agents): reorder agent cards with hold and drag (#1837) fix(messages): keep own sends from before the loaded history off the timeline (#2525) feat(github): rework the GitHub settings page (#2450) fix(mcp): accept create scopes in durable approvals (#2650) feat(bestie): Bestie tab and Remembers you for a hosted Bestie (#2478) fix(relay): p-tag a one-to-one DM's agent partner on new messages (#2475) fix(agents): show each message author's username and display name (#2628) fix(agents): preserve visible edits in conversation history (#2355) fix(canvas): keep todo edits from approving unrelated instructions (#2350) fix(messages): keep messages in their canonical channel (#2349) NEXUS-4165: Add Thinking to agent creation (#2409) feat(plugins): let a plugin paint a backdrop behind the shell (#2437) ... # Conflicts: # src/bundled/goose/runtime.ts
Follows block#2350: a todos_update write tags the canvas unapproved unless the owner's side approved the head it edits, as the panel's partial saves do. Uses the 256 KiB live Canvas limit from block#2318. Co-authored-by: Clod <c7b21872e9ddb79ca62967d0e21e6a4518a669eb04648e963cdfb2426e62fafb@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: LordMelkor <kray@squareup.com>
Why
Changing a Todo saved the entire Canvas under the person making the change. Content added elsewhere by another collaborator could then become that person’s standing agent instructions, even though the Todo view had not shown it. The agent could follow instructions that the owner had never approved.
What changed
Preserve instruction approval when saving partial Todo changes, including repeated edits. Text inherited from another participant stays unapproved until the owner or an attested agent saves the full Canvas. Existing approved instructions remain usable after a Todo-only change.