Skip to content

upstream(sync): Tier 1 security — mention auth + relay skills guard + RUSTSEC-2026-0258 - #306

Merged
oscarlehuu merged 7 commits into
mainfrom
devin/issue-281-mention-auth-relay-skills
Aug 23, 2026
Merged

upstream(sync): Tier 1 security — mention auth + relay skills guard + RUSTSEC-2026-0258#306
oscarlehuu merged 7 commits into
mainfrom
devin/issue-281-mention-auth-relay-skills

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 22, 2026

Copy link
Copy Markdown

Summary

Ports the Tier 1 security slice of the Buzz 0.5.18 sync (upstream block#5681, block#6224, block#6338, block#6394, block#6222) onto Crew, keeping Crew's architecture where it diverges from upstream.

  • Mention authorization at send boundaries (fix(desktop): enforce agent mention authorization at send boundaries block/buzz#5681). agentAutocompleteEligibility now answers a three-state admission (allow / deny / unknown) and unknown fails closed, so an agent pubkey that cannot be proven authorized never reaches a p tag. agentMentionRevalidation re-checks the requested agent mentions immediately before publication, and submitMessageEdit re-checks added mentions before an edit is saved — so an authorization revoked between compose and send (or between edit and save) drops the mention instead of pinging the agent. On the edit path the denied pubkey is also removed from the non-notifying mention reference tags, so a revoked agent is neither published nor rendered as an agent chip.
  • Bounded remote authorization (fix(desktop): bound remote agent mention authorization block/buzz#6224). New Tauri command revalidate_relay_agents(pubkeys, channel_id) in desktop/src-tauri/src/commands/mention_authorization.rs queries the relay with exact author filters for only the requested pubkeys, plus a kind:39002 membership filter narrowed by #p (viewer) and, when sending into a channel, #d (destination channel). Only role=bot membership admits an agent; a spoofed membership event without the bot role is rejected. No unbounded directory sweep.
  • Cross-owner relay mentions in owner-only builds (Fix cross-owner relay agent mentions in owner-only builds block/buzz#6338). Owner-only builds now admit a cross-owner relay agent when relay policy (respondTo allowlist / anyone) and channel membership authorize it, instead of rejecting it purely because the profile owner differs from the viewer.
  • Unrequested relay skills guard (fix(acp): guard against unrequested public relay skills block/buzz#6394). crates/buzz-acp/src/base_prompt.md forbids discovering/loading relay-backed skills unless the authorizing human names the skill, treats an explicitly requested relay skill's content as untrusted input that cannot override higher-priority instructions, and exempts bundled/local skills. Covered by a prompt regression test in crates/buzz-acp/src/lib.rs.
  • RUSTSEC-2026-0258 (fix: bump h2 for RUSTSEC-2026-0258 block/buzz#6222). h2 bumped to 0.4.16 in Cargo.lock.

Crew divergences from upstream (intentional)

  • Upstream reimplements mention auth inside its monolithic send path; Crew keeps its extracted hooks (useMentions, useMentionSendFlow, useMentionSendComplete, submitMessageEdit) and threads revalidation through them.
  • Crew has no upstream relay_directory.rs; the bounded authorization lives in a new sibling command module and Crew's inline list_relay_agents is untouched (also keeps the agent_discovery.rs file-size ratchet green).
  • Crew's RelayAgent type has no owner_pubkey, so the Fix cross-owner relay agent mentions in owner-only builds block/buzz#6338 port derives cross-owner admission from relay policy + membership rather than from an owner field.
  • The h2 bump applies upstream's lockfile change only; upstream's incidental windows-sys re-resolution churn is excluded to keep the lockfile diff scoped.
  • Channel-first IA is preserved: no Projects/Workbench navigation was restored (upstream(sync): Guardrail — preserve channel-first IA during 0.5.18 merge #278).

Related issue

Fixes #281. Part of the 0.5.18 sync stack tracked by #285. No duplicate PRs found.

Testing

TDD: RED logs captured before implementation (red-desktop-unit.log, red-acp-6394.log), then GREEN after.

Gates (all run individually — just ci not run, its mobile dart format leg hangs here):

Gate Result
pnpm --filter buzz check pass
pnpm --filter buzz typecheck pass
pnpm --filter buzz test pass — 5544 passed, 0 failed
just test-unit 6/8 suites pass; buzz-cli (3) + buzz-db (1) failures reproduce identically on unmodified main (baseline logs attached) — pre-existing, untouched by this diff
just check-compile pass
cargo test -p buzz-acp --lib 1023 passed
cargo test --lib mention_authorization (Tauri) 5 passed
Desktop E2E mentions.spec.ts 66 passed

Security before/after (cargo audit, same tree, only Cargo.lock differs):

  • before (main): h2 0.4.11 — RUSTSEC-2026-0258 "h2 unbounded empty DATA frames", solution >=0.4.16
  • after (this branch): RUSTSEC-2026-0258 absent (0 matches)

UI evidence, full-viewport via the E2E mock bridge (whole app: sidebar + channel + composer):

Cross-owner relay agent authorized by allowlist in an owner-only build — before (autocomplete) and after (sent with the mention p tag):

before: cross-owner agent offered in autocomplete

after: mention sent and agent engaged

Authorization revoked mid-send — before (mention selected in composer) and after (message published without the agent p tag):

before: revoked-case composer with mention selected

after: message sent with the revoked mention dropped


DONE

All five scoped upstream ports are implemented and locally verified.

Tests added: agentAutocompleteEligibility.test.mjs (unauthorized / unresolved / selected-agent filtering), submitMessageEdit.test.mjs (edit-save revalidation, upload-pause revalidation, denied/admitted reference-tag cases), 5 Rust tests in mention_authorization.rs (query bounds, channel narrowing, bot-role filtering, multi-channel accumulation), ACP prompt regression test, and E2E cases in desktop/tests/e2e/mentions.spec.ts.

Gates (run individually; full just ci not run — its mobile dart format leg hangs in this environment):

Gate Result
pnpm --filter buzz check pass
pnpm --filter buzz typecheck pass
pnpm --filter buzz test pass — 5544 passed, 0 failed, 1 skipped
just check-compile pass
cargo test -p buzz-acp --lib 1023 passed
cargo test --lib mention_authorization (Tauri) 5 passed
Desktop E2E mentions.spec.ts 66 passed
just test-unit buzz-cli (3) + buzz-db (1) failures — reproduce identically on unmodified main, pre-existing
cargo audit RUSTSEC-2026-0258 present on main, absent on this branch

Evidence (on the session VM, also attached to the session): RED/GREEN logs red-desktop-unit.log, red-acp-6394.log, green-acp-6394.log, red-edit-mention-tags.log, green-edit-mention-tags.log; gate logs gate-pnpm-check.log, gate-pnpm-typecheck.log, gate-pnpm-test.log, gate2-*.log, gate-just-test-unit.log, gate-just-check-compile.log; security cargo-audit-before-main.log, cargo-audit-after.log — all under /home/ubuntu/evidence/. Full-viewport adversarial E2E screenshots 01a06 and TEST-PLAN.md under /home/ubuntu/evidence-281/, plus recording /home/ubuntu/screencasts/pr306-mentions/pr306-mentions-edited.mp4.

IN PROGRESS

Nothing. The working tree is clean, the branch is pushed at fa7de1b32, and every scoped item is implemented with tests passing.

TODO / NEXT

  • CI: NuncioCrew CI runs on this branch were deliberately cancelled by the parent session (org Actions pool is serialized). No genuine CI failure was observed on this change; a re-run is still needed for a green signal. Do not treat the cancellation as a failure.
  • Not verified end to end: real-relay runtime behaviour of the kind:39002 #p/#d filters, and a real ACP agent actually replying to an admitted mention — both were exercised only through the E2E mock bridge and unit tests.
  • Merge-conflict risk: the branch already carries a merge of main including the sibling mobile parity work (upstream(sync): Mobile UI — upstream 0.5.12–0.5.18 parity #305). Further conflicts are most likely in desktop/src/features/messages/ui/ (send/edit hooks) and Cargo.lock if another sync PR bumps dependencies.
  • Out of scope, suggested separately: a .agents/skills/desktop-e2e-adversarial/SKILL.md update documenting the mention-authorization E2E recipe was sent as a skill-PR suggestion rather than included here.

Link to Devin session: https://app.devin.ai/sessions/d3b9f71580154edbbeef438e63ce6e57
Requested by: @oscarlehuu

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Author

DONE

All five scoped upstream ports are implemented and locally verified.

Tests added: agentAutocompleteEligibility.test.mjs (unauthorized / unresolved / selected-agent filtering), submitMessageEdit.test.mjs (edit-save revalidation, upload-pause revalidation, denied/admitted reference-tag cases), 5 Rust tests in mention_authorization.rs (query bounds, channel narrowing, bot-role filtering, multi-channel accumulation), ACP prompt regression test, and E2E cases in desktop/tests/e2e/mentions.spec.ts.

Gates (run individually; full just ci not run — its mobile dart format leg hangs in this environment):

Gate Result
pnpm --filter buzz check pass
pnpm --filter buzz typecheck pass
pnpm --filter buzz test pass — 5544 passed, 0 failed, 1 skipped
just check-compile pass
cargo test -p buzz-acp --lib 1023 passed
cargo test --lib mention_authorization (Tauri) 5 passed
Desktop E2E mentions.spec.ts 66 passed
just test-unit buzz-cli (3) + buzz-db (1) failures — reproduce identically on unmodified main, pre-existing
cargo audit RUSTSEC-2026-0258 present on main, absent on this branch

Evidence (on the session VM, also attached to the session): RED/GREEN logs red-desktop-unit.log, red-acp-6394.log, green-acp-6394.log, red-edit-mention-tags.log, green-edit-mention-tags.log; gate logs gate-pnpm-check.log, gate-pnpm-typecheck.log, gate-pnpm-test.log, gate2-*.log, gate-just-test-unit.log, gate-just-check-compile.log; security cargo-audit-before-main.log, cargo-audit-after.log — all under /home/ubuntu/evidence/. Full-viewport adversarial E2E screenshots 01a06 and TEST-PLAN.md under /home/ubuntu/evidence-281/, plus recording /home/ubuntu/screencasts/pr306-mentions/pr306-mentions-edited.mp4.

IN PROGRESS

Nothing. The working tree is clean, the branch is pushed at fa7de1b32, and every scoped item is implemented with tests passing.

TODO / NEXT

  • CI: NuncioCrew CI runs on this branch were deliberately cancelled by the parent session (org Actions pool is serialized). No genuine CI failure was observed on this change; a re-run is still needed for a green signal. Do not treat the cancellation as a failure.
  • Not verified end to end: real-relay runtime behaviour of the kind:39002 #p/#d filters, and a real ACP agent actually replying to an admitted mention — both were exercised only through the E2E mock bridge and unit tests.
  • Merge-conflict risk: the branch already carries a merge of main including the sibling mobile parity work (upstream(sync): Mobile UI — upstream 0.5.12–0.5.18 parity #305). Further conflicts are most likely in desktop/src/features/messages/ui/ (send/edit hooks) and Cargo.lock if another sync PR bumps dependencies.
  • Out of scope, suggested separately: a .agents/skills/desktop-e2e-adversarial/SKILL.md update documenting the mention-authorization E2E recipe was sent as a skill-PR suggestion rather than included here.

devin-ai-integration Bot and others added 7 commits August 23, 2026 01:20
… (upstream block#5681)

Ported from block/buzz bcf353c. Crew keeps its extracted
useMentionSendComplete hook, explicit-empty imeta edit save, removed-mention
diff and Project workspace resolution; upstream revalidation is layered on
top.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
…tream block#6224, block#6338)

Ported from block/buzz 3fdf289 and the block#6338 follow-up. Crew keeps its inline
list_relay_agents directory command and invoke.rs handler macro; the bounded
send-time check lands as a new commands::mention_authorization module instead of
upstream's relay_directory.rs rewrite. Cross-owner relay agents stay mentionable
in owner-only builds when relay policy plus bot-role membership authorize them;
Crew's RelayAgent has no ownerPubkey field, so admission is derived from
respondTo/allowlist and channel membership rather than owner identity.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
…ock#6394)

Ported from block/buzz d274a6e. Adds the base-prompt restriction plus a
regression test asserting the guard stays in the shared prompt.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
)

Ported from block/buzz cc8a8b0. Only the h2 entry is bumped; upstream's
incidental windows-sys re-resolution churn is left out to keep the lockfile
diff scoped.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
…test

The owner-only cross-owner case still surfaces the not-in-channel invite
prompt before publication, so the test must accept it to observe the
outgoing p tag.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Edit-save revalidation stripped denied agents from mentionPubkeys but the
non-notifying reference tags were built before revalidation, so a revoked
agent's pubkey was still published and rendered as an agent chip.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Main now requires ownerPubkey on RelayAgent. Restore the mapping that
lived in the previous merge resolution so send-time revalidation stays
type-correct after the rebase.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: oscarlehuu <oscarlehuu@users.noreply.github.com>
@cursor
cursor Bot force-pushed the devin/issue-281-mention-auth-relay-skills branch from ca39305 to 98ed7b4 Compare August 23, 2026 01:23
@oscarlehuu
oscarlehuu merged commit 33ad664 into main Aug 23, 2026
9 of 15 checks passed
@oscarlehuu
oscarlehuu deleted the devin/issue-281-mention-auth-relay-skills branch August 23, 2026 01:40
cursor Bot pushed a commit that referenced this pull request Aug 23, 2026
Main's #306 revalidation renamed the explicit-agent guard. The
source-inspection test still required the old local name after rebase.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: oscarlehuu <oscarlehuu@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 23, 2026
…303)

* feat(desktop): bounded selection + visible-page agent context (#272)

Port the upstream Projects agent-context payload builders (block#6368, block#6396)
onto Crew's channel-first composer: an explicit-agent send now carries a
bounded, injection-safe description of what the sender is looking at
(channel, thread, repository/branch, PR) as a hidden reference line.

Crew keeps its own chrome: the context is mounted by Crew-owned channel
and thread composer providers, not by upstream Projects overview tabs,
context pods, a Projects rail, or a Workbench.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* fix(desktop): scope visible-page context to pages with workspace selection

The channel dock and bare thread replies show nothing the agent cannot
derive from the message it already receives, so attaching hidden context
there changed the sent content of every agent mention (regressing the
mentions E2E contract). Visible-page context now requires the thread
chrome to contribute a repository/branch or PR selection.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* fix(desktop): match view-context wiring test to mention-auth guard

Main's #306 revalidation renamed the explicit-agent guard. The
source-inspection test still required the old local name after rebase.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: oscarlehuu <oscarlehuu@users.noreply.github.com>

---------

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Oscar Le <oscar.lehuu@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: oscarlehuu <oscarlehuu@users.noreply.github.com>
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.

upstream(sync): Tier 1 security — mention auth + relay skills + RUSTSEC (#5681, #6224, #6338, #6394, #6222)

2 participants