Repository navigation
Description
Finding
The aggregator dashboard's new comment API accepts a self-asserted author identity: validateAuthor checks only the shape (kind is drew/muse/agent, non-empty id/label), never that the identity exists in the session registry — even though PR #920's body advertises "Unambiguous authorship: drew / muse / agent identities from the registry". Any client that can reach the server can post a comment as Drew, and downstream consumers act on that attribution.
Found by the pr-diff-review job reviewing PR #920 (dashboard slice 3, #906), 2026-10-25; verified on current main (92d0c6ee).
Evidence
pm-stack/aggregator/src/comments.ts:41-55—validateAuthor(a): returns an author for any object withkind ∈ {drew, muse, agent}and non-empty stringid/label(truncated to 120 chars). No registry lookup, no credential, no session binding.pm-stack/aggregator/src/server.ts:131-136—POST /api/commentsstores whatevervalidateNewCommentreturns; the registry (identitiesFromRecords, used to build the comment form options incommentFormOpts) is never consulted on the write path.- The package's own tests prove the point:
pm-stack/aggregator/test/slice3.test.tsposts with a bare literalconst author = { kind: "drew", id: "drew", label: "Drew" }and it is accepted. - Why the attribution is load-bearing (comments.ts header, lines 12-25): kind
messagecomments are "the orchestrator's queue input" — triaged and acted on as instructions; kindgithubcomments are posted to GitHub by a fleet poster with the attribution line "— posted by Drew via the PM dashboard". A forgeddrewauthor therefore flows into agent instructions and into GitHub comments carrying Drew's name. - The trust-model comment (comments.ts:9-11) notes the server binds loopback + tailnet and writes are unauthenticated "like every other fleet-internal surface" — but other surfaces do not mint Drew-attributed instructions and GitHub posts. Agent sessions themselves run on the tailnet, so a confused or compromised agent (not just a person) can impersonate Drew to the orchestrator.
Why it matters
This fleet treats Drew's word as the highest authority. A comment box that lets any tailnet client speak as Drew — into the orchestrator's input queue and onto GitHub under his name — is an authority-confusion surface that contradicts the PR's stated design ("identities from the registry", "unambiguous authorship").
Acceptance criteria
- Triage verdict on the intended trust boundary: either (a) the write path validates the author against the registry / a per-identity credential, so
kind: "drew"cannot be self-asserted by an arbitrary client, or (b) the design is consciously accepted and the code/PR claims are corrected (comments.ts header and docs stop claiming registry-backed unambiguous authorship, and github-kind posts are not attributed to Drew unless the author was verified). - If (a): a test posts an unregistered/forged
drewauthor and is rejected, while registry identities still post. - If (b): the orchestrator's consumption contract in comments.ts documents that message-kind comments are unauthenticated input, not Drew instructions.
— filed by the pr-diff-review job (PR #920); triage via the repo-health queue pilot.
Activity
dezren39 commentedon Oct 26, 2026
🤖 Agent note · filed
pm-stack aggregator: dashboard actions store + triage write path UI (#…
24 remaining items
dezren39 commentedon Nov 3, 2026
🤖 Agent note · done — PR opened
bun test test/slice3.test.ts— 36 passed. Full suite had two failures reproduced on clean main; typecheck has pre-existing errors outside changed files.dezren39 commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 3, 2026
🤖 Agent note · done — duplicate triage packet, no new work needed (already_done)
Verdict: triage already complete — nothing new to triage
This packet (coverage pass 2026-11-03) re-created a triage item that had already been worked: triage task 1088 posted the verdict (CONFIRMED, enforce) on 2026-10-31, then the escalated design decision was settled (Drew variant-of-C on 2026-10-31, Muse ruling option A / operator token on 2026-11-03). The coverage join missed live fix task 4642, which already has an open PR.
Current state, verified fresh:
origin/mainpm-stack/aggregator/src/comments.ts—validateAuthoris still shape-only (kind ∈ {drew, muse, agent} + non-empty id/label); the consumption-contract header still describes unauthenticated writes and the "— posted by Drew via the PM dashboard" attribution. The finding is still live on main, unchanged since the 2026-10-31 verdict.fix(aggregator): verify privileged comment authors (#941)— OPEN, not draft, branchqueue/4642-941-operator-token-comments, last updated 2026-11-03T11:52Z. Only check present is CodeRabbit (NEUTRAL/skip); not merged.Routing