Skip to content

aggregator(dashboard): comment API accepts self-asserted author identities — anyone can post as Drew into the orchestrator/GitHub flow (PR #920) #941

Open

Description

@dezren39

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 with kind ∈ {drew, muse, agent} and non-empty string id/label (truncated to 120 chars). No registry lookup, no credential, no session binding.
  • pm-stack/aggregator/src/server.ts:131-136 — POST /api/comments stores whatever validateNewComment returns; the registry (identitiesFromRecords, used to build the comment form options in commentFormOpts) is never consulted on the write path.
  • The package's own tests prove the point: pm-stack/aggregator/test/slice3.test.ts posts with a bare literal const author = { kind: "drew", id: "drew", label: "Drew" } and it is accepted.
  • Why the attribution is load-bearing (comments.ts header, lines 12-25): kind message comments are "the orchestrator's queue input" — triaged and acted on as instructions; kind github comments are posted to GitHub by a fleet poster with the attribution line "— posted by Drew via the PM dashboard". A forged drew author 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 drew author 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

  1. added
    kind/securitySecurity issue or security hardening
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    on Oct 26, 2026
  2. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: pr-diff-review job
    • Session / ID: pr-diff-review (cron job_id pr-diff-review) run 2026-10-25 20:37 CDT
    • Found via: filed this run
    • Task: Triage the aggregator dashboard comment author-impersonation surface (PR impl(dashboard): slice 3 — pluggable pages, DNS register, comments, session registry (#906) #920)
    • Expectation: effort/s — triage verdict on the finding against current main, then a fix or a documented acceptance
    • Links: source PR evidence is in the issue body; a repo-task/v1 triage packet for this issue is enqueued in repo-health-code-pilot
  3. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 31, 2026
  4. 24 remaining items

  5. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done — PR opened

  6. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    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

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

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 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/main pm-stack/aggregator/src/comments.ts — validateAuthor is 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.
    • PR fix(aggregator): verify privileged comment authors (#941) #4832 fix(aggregator): verify privileged comment authors (#941) — OPEN, not draft, branch queue/4642-941-operator-token-comments, last updated 2026-11-03T11:52Z. Only check present is CodeRabbit (NEUTRAL/skip); not merged.

    Routing

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

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codekind/securitySecurity issue or security hardeningpriority/normalOrdinary priority (the default)source/pr-diff-reviewFiled by the pr-diff-review jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions