Skip to content

Automation  ·  IT and security

How to build bug bounty report triage

A valid report waited three weeks for somebody to own it, and the researcher wrote about it first. The design behind triage that gets every report an owner and an answer, the prompts that build it, and what running it takes.

Built with Tray Headless

  1. System HackerOne
  2. Step Check for duplicates
  3. Step Find the owner
  4. Step Size the impact
  5. System Jira
Also Slack

Duplicates are caught before a person reads the report, and every valid one reaches the team that owns the code, with the clock the researcher is watching attached.

The short answer

What is bug bounty report triage automation?

Bug bounty report triage has four parts: checking each new report against past and open ones so duplicates are caught before anybody reads them in full, finding the team that owns the affected code or service, sizing the report on what an attacker could really do with it, and keeping the researcher updated against the response times the program promises. The part that breaks is ownership. Security can confirm a report, but only the owning team can fix it, and a report with no owner waits until the researcher loses patience.

Stage 7 of 7: Bug bounty report triage. Part of Security operations, end to end : every stage, the systems it runs on and the guide that builds it.

What matters here

  • Check for duplicates first. A large share of reports describe something already reported or already fixed.
  • Find the owner from the affected asset, not from whoever is on the security rota.
  • Size on what an attacker could really do here, not on the severity the researcher picked.
  • Track the program's promised response times and warn before they slip, not after.
  • Close the loop with the researcher. The ones who hear back send the next good report to you, not to a blog.

Who this is for

You run product security or a bug bounty program. Reports arrive faster than the team can read them, and the hard part is getting engineering to own the valid ones.

How it works in practice

From a researcher submitting a report to the fix shipping and the researcher being paid.

  1. 1

    A new report arrives

    With the affected asset, the steps to reproduce and the researcher's suggested severity.

  2. 2

    It is checked against past and open reports

    Same asset and same kind of issue, or the same steps, flagged as a likely duplicate for a person to confirm.

  3. 3

    The owning team is found

    From the asset: the repository, the service and the team that deploys it.

  4. 4

    The report is sized on real impact

    What data or actions it reaches, whether it needs a signed-in user, and whether it is exposed to the internet.

  5. 5

    A ticket goes to the owning team

    In their tracker, with the steps, the sizing and the date the fix is due.

  6. 6

    The researcher hears back on time

    First response, confirmation, fix and payout, each against the time the program promises.

What report triage is made of

Four parts, and the second is the one that decides whether valid reports get fixed or just confirmed.

Duplicate checks

Each report compared with open and past ones on asset, type and steps. Likely duplicates go to a person to confirm, not straight to closed.

Ownership from the asset

Domain or endpoint to service to repository to team. A report with no owner is escalated as an ownership gap.

Sizing on impact

What it reaches, who can trigger it, and whether it is exposed. The researcher's severity is a starting point.

Response time tracking

First response, confirmation and fix, each against the program's promise, with a warning before any of them slip.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    Set up, then map assets to owners

    A confirmed report with no owner never gets fixed.

    Headless skills build-workflow

    Use build-workflow. The systems in play are HackerOne, GitHub or
    GitLab, Jira, ServiceNow for the service catalogue, Slack and
    Snowflake, or whatever we run in those seats. Before you plan anything,
    tell me which of them are already authenticated in the workspace,
    because I do not want a connector stubbed that I have not
    authenticated.
    
    Build the map from each domain, endpoint and app in the program's
    scope to the service, the repository and the team that deploys it.
    List anything in scope that maps to nobody. That list is the first
    thing to fix.
  2. 2

    Catch duplicates before anyone reads in full

    Duplicates eat the team's reading time.

    Headless skills build-workflow

    Use build-workflow. For each new report, compare it with open and
    closed reports on: the affected asset, the kind of issue, and the steps
    to reproduce. Also check open Jira tickets for the same asset and issue,
    since the team may already be fixing it.
    
    Flag a likely duplicate with the matching report linked, for a person
    to confirm. Do not close reports as duplicates on your own: a near
    match is sometimes a second, different issue on the same page.
  3. 3

    Size on real impact

    The researcher's severity is a starting point, not the answer.

    Size each confirmed report on:
    
      What data or actions it reaches
      Whether it needs a signed-in user, and what kind
      Whether the asset is exposed to the internet
      Whether the issue is being used against us now, from our own logs
    
    Record both the researcher's severity and ours, with the reason for
    any difference. The researcher will ask, and a reason keeps the
    conversation short.
  4. 4

    Route to the owning team, with a due date

    Security can confirm a report but can't ship the fix.

    Headless skills tray-gotchas

    Use tray-gotchas, then open a ticket in the owning team's Jira project
    with: the steps to reproduce, our sizing, the affected service and
    repository, and a due date from the program's fix target for that
    size.
    
    Post the ticket to the team's Slack channel. If a fix needs a change
    in GitHub, link the repository. If the asset maps to nobody, escalate
    to the security lead as an ownership problem instead of filing the
    ticket into a void.
  5. 5

    Keep the researcher updated on time

    Researchers who hear back send the next report to you.

    Track each report against the program's promised times: first
    response, confirmation, fix and payout.
    
    Warn the security lead in Slack before any of them slips, with the
    report and the owner. Post updates to the researcher in HackerOne as
    the ticket moves: confirmed, fix in progress, fixed, ready to retest.
    
    Report monthly: reports received, share duplicates, time to first
    response, time to fix by size, and promised times missed.
  6. 6

    Validate it, then hand the rules to product security

    Because sizing and due dates are policy, owned by people.

    Run the per-step schema checks and the whole-workflow audit before this
    touches production. Run it alongside the team for two weeks, flagging
    duplicates and suggesting sizes and owners, with every decision made by
    a person, and compare.
    
    Then open the same workflow in Tray Build so product security can
    change the asset map, the sizing rules and the due dates in the visual
    canvas.

What it connects to

Reports come from researchers, and fixes ship from engineering.

HackerOne

Read new reports with their steps and asset, and post status updates back to the researcher.

Reads and writes

GitHub

Find the repository and team behind an affected service, and link the fix when it ships.

Reads

GitLab

Find the repository and team where the code lives in GitLab.

Reads

ServiceNow

Read the service catalogue to map a domain or endpoint to the service and its owner.

Reads

Jira

Open the ticket in the owning team's project with the steps, sizing and due date, and check for open duplicates.

Reads and writes

Slack

Post new tickets to the owning team, and warn the security lead before a promised time slips.

Writes

Snowflake

Land every report and its timings, so duplicates, time to fix and missed promises are measurable.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against Google BigQuery, Microsoft Teams, Jira Service Desk, Databricks, Google Chat or Zendesk.

Connections in this build

Field mapping, templates and common problems for each pairing: HackerOne + GitHub, GitHub + GitLab, HackerOne + Jira and GitHub + Jira.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This sits between outside researchers and your engineering teams. Both are watching the clock.

It runs where production runs, not on a laptop

Reports are checked and routed as they arrive, with every decision and update recorded.

People decide duplicates and sizing

The workflow flags and suggests. Closing a researcher's report is a person's call, because a wrong close costs trust you can't buy back.

Managed credentials, not secrets in a config file

Report details describe weaknesses before they are fixed. Access is a scoped authentication in your workspace, never written into the build.

Product security own the rules

The asset map, sizing rules and due dates open in Tray Build, owned by the team that runs the program.

Run it alongside the team first

Two weeks of suggestions next to human decisions. That comparison shows where the duplicate check and the sizing can be trusted.

Questions people ask

Should duplicates be closed automatically?

No. Flag them with the matching report for a person to confirm. A near match is sometimes a second, different issue on the same page, and wrongly closing it costs the researcher's trust.

Why size reports ourselves?

Because the researcher sees the bug and you see the asset. What it reaches, who can trigger it and whether it is exposed decide the real impact.

Why route to engineering instead of security?

Because security can confirm a report but can't ship the fix. A ticket in the owning team's tracker, with a due date, is what gets it fixed.

What if a report maps to no team?

Escalate it to the security lead as an ownership gap. Filing it into a general queue is how valid reports wait for weeks.

Which response times should we track?

The ones the program promises researchers: first response, confirmation, fix and payout. Warn before each one slips.

Last reviewed October 2026.