Skip to content

fix(acp): trust relay workflow attribution only when allowlisted - #9503

Open
Giszmo wants to merge 1 commit into
block:mainfrom
Giszmo:carol/acp-relay-attribution-optin
Open

Giszmo wants to merge 1 commit into
block:mainfrom
Giszmo:carol/acp-relay-attribution-optin

Conversation

@Giszmo

@Giszmo Giszmo commented Nov 14, 2026 •

Copy link
Copy Markdown

Summary

The relay signs workflow messages and names the workflow owner in a tag. Since #6953 the respond-to gate takes that tag as the owner speaking, so whoever holds the relay key can prompt an agent with any text, as its owner.

This makes that trust an explicit operator opt-in with its own flag, --trust-relay-workflow-attribution (BUZZ_ACP_TRUST_RELAY_WORKFLOW_ATTRIBUTION), default off. Without it, a relay-signed message is judged by its raw signer, as for any other author. The flag does not touch the author allowlist, so opting in does not make the relay an allowed author.

Behaviour change: operators relying on workflows to wake agents must set the flag. Desktop does not pass it today.

Related

#4068 proposed the same opt-in (--honor-workflow-attribution) but conflicts with main and has been stale since 2026-08-19. #6953 made the trust the default. #3858 is the "workflows don't wake agents" side. #2737 is the owner-signed alternative.

Testing

cargo test -p buzz-acp (1091 passed), cargo clippy -p buzz-acp --all-targets -- -D warnings, cargo fmt --check. New tests: default-off (owner-only, and relay listed in the allowlist), and a relay-signed message with a p tag but no buzz:workflow-mention stays dropped even with the flag on.

🤖 Generated with Claude Code

@Giszmo
Giszmo requested a review from a team as a code owner November 14, 2026 21:23
@github-actions

github-actions Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 69742376a9b1b15da62295f54a053913540722c1...fe8bdcd25a595be09d36112d224e037e0059a70b.
A new review must complete for this exact range. When manual authorization
is required, a user with write access must comment exactly
@buzz-security-review fe8bdcd25a595be09d36112d224e037e0059a70b to authorize a new review.
Any previous review applies only to its recorded range.

@Giszmo
Giszmo force-pushed the carol/acp-relay-attribution-optin branch from 0cd4693 to 65168e4 Compare November 14, 2026 21:25

@joahg joahg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Leaving comments rather than approving. This changes who can wake every agent, so it needs a sign-off from a Buzz maintainer. Two things to settle first:

  1. The default changes. RespondTo::default() is OwnerOnly, so once this merges, every agent on default settings stops waking for workflows. That reverses the default #6953 chose on purpose. It needs a maintainer's call, plus a release note or migration for operators who use workflows today.
  2. The opt-in grants more than attribution. Listing the relay key in BUZZ_ACP_RESPOND_TO_ALLOWLIST also makes the relay an allowed author. That's because author_allowed checks allowlist.contains(author). effective_prompt_author also falls back to the raw signer whenever verified_workflow_owner returns None. So with the opt-in on, any relay-signed event without verified attribution wakes the agent. That includes the cases where NIP-11 is unavailable and where the key was rotated away (if the old key is still listed).
    • The tests for those two cases used to assert !allowed. They now assert only on effective_author, which hides the change.
    • Suggestion: keep "trust relay attribution" separate from "allow this author". For example, pass author_allowed an allowlist without the relay key, or use a dedicated setting like the one #4068 proposed. Then restore the !allowed assertions.

The gate change itself, filtering relay_self through the allowlist, is small and correct for the owner-only case.

The relay signs workflow messages and names their owner in a tag, and
the author gate took that tag as the owner speaking. Anyone holding the
relay key could therefore prompt an agent as its owner.

Attribution now needs --trust-relay-workflow-attribution
(BUZZ_ACP_TRUST_RELAY_WORKFLOW_ATTRIBUTION), off by default. It is
separate from the author allowlist, so opting in no longer makes the
relay an allowed author: relay-signed events without verified
attribution are still judged as the relay. Tests cover the default-off
gate and a substituted mention that carries a p tag but no
buzz:workflow-mention tag.

Opus 5.5 helped authoring this commit.

Signed-off-by: Leo Wandersleb <leo@leowandersleb.de>
@Giszmo
Giszmo force-pushed the carol/acp-relay-attribution-optin branch from 65168e4 to fe8bdcd Compare November 14, 2026 22:52
@Giszmo

Giszmo commented Nov 14, 2026

Copy link
Copy Markdown
Author

Thanks @joahg, both points were right. I pushed a revision:

  • Relay attribution now has its own flag, --trust-relay-workflow-attribution (BUZZ_ACP_TRUST_RELAY_WORKFLOW_ATTRIBUTION), default off. It no longer touches the author allowlist, so opting in doesn't make the relay an allowed author.
  • The NIP-11-unavailable and rotated-key tests assert !allowed again.
  • New test: a relay-signed workflow message with a p tag for the agent but no buzz:workflow-mention (a webhook payload containing @agent) doesn't wake the agent, even with the flag on.

That leaves your first point, which I can't settle in code: what's the intended trust model for the relay key?

As I read #6953, a message signed by the relay's NIP-11 self key counts as coming from whichever owner its buzz:workflow-owner tag names. ACP can check the signature and tags, but not that the workflow exists or targets this agent; only the relay knows that. So whoever holds or compromises the relay key can prompt any agent as its owner, and the key comes from the relay it vouches for.

If that's the intended model ("the relay operator is trusted to speak for owners"), I'd flip the default back to on and keep the flag as a way to opt out, with a line in the docs. If it isn't, default-off needs a release note, and Desktop would need to pass the flag for agents that use workflows, since today it doesn't. Longer term, the owner-signed approach in #2737 or a pinned relay key (#4068) would remove the trade-off.

Happy to go either way once a maintainer picks the default.

@joahg joahg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Thanks, both code points are fixed on this head.

  • --trust-relay-workflow-attribution now gates only the attribution. author_allowed gets the operator's allowlist unchanged, and the new test shows that listing the relay key doesn't turn attribution on.
  • The NIP-11-unavailable and rotated-key tests are back to main's !allowed assertions.
  • The substituted-mention test covers the webhook @agent case.

On your question: the default is a call about the relay's trust model, and it belongs to a Buzz maintainer, so I'm leaving it to them rather than approving. Whichever way it goes, please ship it together with the matching Desktop change. Desktop doesn't pass this flag today, so default-off on its own would quietly stop workflows from waking every Desktop agent. That needs a release note. If maintainers choose default-on, keeping the flag as an explicit opt-out seems right.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants