Skip to content

Trigger Junior from trusted GitHub issue requests #2207

Open

Description

@sentry-junior

Junior does not start work when assigned to a GitHub issue, so requests have to be relayed through Slack. Support requesting Junior work directly from GitHub. Only a tag or mention from a person in Junior's trusted-people database may start a flow. Tags from untrusted people must not start one.

Security requirements

From a security review of this proposal:

  • Deterministic gate before any run. Trust must be checked in code before a Run is created, not by the agent. Issue and comment Events today carry the author login only inside trustedSummary text, with no structured author field. Untrusted tags are dropped before any model call.
  • Match the immutable GitHub user id. Compare the webhook sender.id with a GitHub Identity linked to a User through the OAuth account-linking flow (providerSubjectId is the numeric id from GET /user). Never trust logins (rename/reuse), commit emails, or display names. Check the person who did the action (commenter or assigner), not the issue author.
  • Only the trusted comment is the instruction. Repos such as getsentry/junior are public, so the issue body and other comments are untrusted. They stay untrusted text, and action review judges against the trusted person's comment. Related: Audit actor/instruction provenance across plugins #773.
  • No private data in public output. Replies land on a GitHub issue that can be public, while Junior can read Slack, Notion, memory, and Sentry. Runs started from GitHub need limits on what they read or post publicly.
  • Revocation applies. A linked GitHub Identity persists after the person leaves. Re-check the linked Slack account's workspace membership when a tag arrives, as Slack ingress does.
  • Correct credentials. Issue and pull request writes use the GitHub App bot (Make Junior primary on GitHub issues and pull requests #780). Any delegated access belongs to the person who tagged Junior.
  • Edited comments. Decide whether issue_comment.edited can trigger a flow; handle it explicitly.

Existing controls to keep: webhook HMAC verification, installation id check, bot self-filtering, and delivery-id idempotency.

Design

GitHub starts the work, and Slack is the home.

A tag on GitHub only starts work. The work runs in a private Slack DM with the person who wrote the tag. Replies do not go to GitHub, except when Junior uses its normal GitHub tools as the App bot.

Flow

  1. The GitHub webhook receives issue_comment.created. Edited comments do not start work.
  2. The plugin stops at once unless the comment mentions the App (mentionsBot, feat(github): Add trusted sender and mention data to issue comments #2209).
  3. The plugin asks core to start a run for the GitHub Identity with the webhook sender.id. The plugin can only name an Identity of its own provider.
  4. Core starts the run only when all of these are true. If one is false, core drops the request and does not call the model.
    • A GitHub Identity with this numeric id is linked to a User through the OAuth linking flow.
    • That User has exactly one Slack Identity in the bot's workspace.
    • The Slack account is active (users.info: not deleted, not a bot).
  5. Core opens the DM and starts a dispatch with delegated credentials that are bound to that DM (private-direct-conversation). This contract already exists for plugin heartbeats.
    • Work that starts from a public repository is public work, even though Junior delivers it in a private DM. Step 4 adds this.
  6. Optional: the App bot replies "on it, details in Slack". Untrusted tags get no reply.

Instruction and context

  • The trusted comment is the instruction of that person. Action review treats it like a Slack message from that person.
  • The issue title, body, and other comments are untrusted context. This is the same rule as when a person pastes an issue link into Slack today.
  • GitHub writes use the App bot and the same action review as today.

DM threads

  • Each GitHub request is one top-level DM message. All work for that request stays in its thread.
  • Later: a new trusted tag on the same issue continues the same thread.

Known gaps

  • Dispatch runs turn off interactive sign-in today. If the person has not connected an account that the work needs, the run is blocked and reports it in the DM. Step 3 adds sign-in prompts in the person's DM.
  • Dispatch input is a bot-authored message. Step 3 must give action review the provenance of the person.

Tracking

This body replaces the older design comment (#2207 (comment)).

via @BYK.

--

View Junior Session [Sentry]

Activity

  1. sentry-junior commented on Oct 23, 2026

    @sentry-junior
    ContributorAuthor

    Design: GitHub starts the work, Slack is the home

    A tag on GitHub only starts work. The work runs in a private Slack DM with the person who wrote the tag. Replies do not go to GitHub, except when Junior uses its normal GitHub tools as the App bot.

    Flow

    1. The GitHub webhook receives issue_comment.created. Edited comments do not start work.
    2. The plugin stops at once unless the comment mentions the App (mentionsBot, feat(github): Add trusted sender and mention data to issue comments #2209).
    3. The plugin asks core to start a run for the GitHub Identity with the webhook sender.id. The plugin can only name an Identity of its own provider.
    4. Core starts the run only when all of these are true. If one is false, core drops the request and does not call the model.
      • A GitHub Identity with this numeric id is linked to a User through the OAuth linking flow.
      • That User has exactly one Slack Identity in the bot's workspace.
      • The Slack account is active (users.info: not deleted, not a bot).
    5. Core opens the DM and starts a dispatch with delegated credentials that are bound to that DM (private-direct-conversation). This contract already exists for plugin heartbeats.
    6. Optional: the App bot replies "on it, details in Slack". Untrusted tags get no reply.

    Instruction and context

    • The trusted comment is the instruction of that person. Action review treats it like a Slack message from that person.
    • The issue title, body, and other comments are untrusted context. This is the same rule as when a person pastes an issue link into Slack today.
    • GitHub writes use the App bot and the same action review as today.

    DM threads

    • Each GitHub request is one top-level DM message. All work for that request stays in its thread.
    • Later: a new trusted tag on the same issue continues the same thread.

    Known gaps

    • Dispatch runs turn off interactive sign-in today. If the person has not connected an account that the work needs, the run is blocked and reports it in the DM.
    • Dispatch input is a bot-authored message. Step 3 must give action review the provenance of the person.

    Steps

    1. feat(github): Add trusted sender and mention data to issue comments #2209: trusted senderId and mentionsBot on issue comment Events.
    2. Core: resolve a provider Identity to a current linked Slack member, and let plugin webhook routes start a DM dispatch for that person.
    3. Core: instruction provenance for dispatches started by a person, so action review uses the comment as that person's instruction (Audit actor/instruction provenance across plugins #773).
    4. GitHub plugin: connect the webhook to step 2, and add the optional reply.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions