Skip to content

Automation  ·  IT and security

How to build vulnerability to ticket routing

The scanner reports eleven thousand findings and the team fixes the ones at the top of the list. Here is how ranking that reflects real risk actually works, the prompts that build it, and what running it demands.

Built with Tray Headless

  1. System Scanner
  2. Step Resolve asset
  3. Step Rank on exploitability
  4. Step Group by fix
  5. System Jira
Also Slack

Findings are grouped by the fix instead of by the finding, so one dependency bump closes forty items instead of opening forty tickets.

The short answer

What is vulnerability to ticket routing?

Vulnerability routing breaks into four parts: ranking on exploitability and exposure rather than on CVSS alone, grouping findings by the fix instead of by the finding, routing to the team that ships the patch instead of to security, and tracking remediation against an agreed target. The mistake that costs most is ranking on severity. A critical on an internal test box outranks nothing, and a medium on an internet-facing service with a known exploit outranks everything.

What matters here

  • Rank on exploitability and exposure, not CVSS. A critical on a test box is not a critical.
  • Group by the fix. One dependency bump closing forty findings is one ticket, not forty.
  • Route to whoever deploys the fix. Security raising a ticket for security is a queue that never empties.
  • Set targets by risk band and report the ones about to breach, not the ones that already have.
  • Track accepted risks with an expiry. A permanent acceptance is a decision nobody revisits.

Who this is for

You run security engineering or platform. Scanners produce more findings than anybody can action, and the backlog grows faster than remediation.

How it works in practice

The path from a scanner firing to a fix shipping.

  1. 1

    Findings are resolved to an asset and an owner

    A finding on an unidentified host cannot be ranked or routed, so that is the first problem to solve.

  2. 2

    Ranking uses exploitability and exposure

    Known exploited, internet-facing, data classification, and whether a fix exists.

  3. 3

    Findings are grouped by the fix

    Forty findings resolved by one dependency upgrade is one piece of work.

  4. 4

    Work routes to the team that ships

    The service owner, in their tracker, with the fix already identified.

  5. 5

    Targets are set by band and warned before breach

    A warning is actionable and a breach report is an apology.

  6. 6

    Accepted risks carry an expiry

    So an acceptance made under pressure is revisited rather than becoming permanent.

What vulnerability routing is made of

Four parts, though the second is what makes the backlog tractable.

Exploitability ranking

Known exploited, internet-facing, data held, fix available. CVSS describes the flaw and says nothing about your exposure to it.

Grouping by fix

One upgrade that closes forty findings is one ticket. Grouping by finding is why backlogs look unfixable.

Routing to the shipping team

Whoever deploys the service, in the tracker they already use. Security cannot patch what it does not deploy.

Targets with expiring acceptances

Remediation targets by band, and any accepted risk carrying an expiry so it comes back for a decision.

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 resolve findings to owners

    An unattributed finding cannot be ranked or routed.

    Headless skills build-workflow

    Use build-workflow. The systems in play are Datadog, GitHub, Jira,
    Okta, Slack, Vanta 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.
    
    The detail that matters most is the scanners and our asset
    inventory. I need findings with their CVE, affected component and
    host, plus the asset register with owner, environment, exposure and
    data classification.
    
    Report findings that cannot be resolved to a known asset. That number is
    usually large and it is the first thing to fix, because an unattributed
    finding cannot be ranked, routed or closed. It just sits in the count
    making the backlog look worse than it is.
  2. 2

    Rank on exploitability, not severity

    CVSS describes the flaw and says nothing about your exposure.

    Headless skills build-workflow

    Use build-workflow. Compute a rank from:
    
      Is it on a known exploited vulnerabilities list, which outweighs
      everything else
      Is the affected asset internet-facing
      What data classification does that asset hold
      Is it in production
      Does a fix actually exist yet, because a finding with no patch is a
      mitigation task instead of a patch task
      Is the vulnerable code path reachable, where the scanner can tell
    
    Then band into fix-now, fix-this-sprint, fix-this-quarter and accept.
    
    A critical on an internal test instance outranks nothing. A medium on an
    internet-facing service with a published exploit outranks everything, and
    severity alone gets that exactly backwards.

    Known-exploited should dominate the ranking. A vulnerability being actively used is a different category from one that is theoretically severe.

  3. 3

    Group by the fix, not by the finding

    Forty findings closed by one upgrade is one ticket.

    Group before creating any ticket:
    
      Same package upgrade across many services
      Same base image across many containers
      Same CVE across many hosts
      Same configuration change across an environment
    
    Create one ticket per fix, listing every finding it closes, with the
    specific version to upgrade to.
    
    This is the difference between a backlog that looks impossible and one
    that is a fortnight of work. Eleven thousand findings is frequently a few
    hundred actual fixes, and presenting the raw count is why nobody starts.
  4. 4

    Route to whoever ships the fix

    Security raising tickets for security is a queue that never empties.

    Headless skills tray-gotchas

    Use tray-gotchas, then route each grouped fix to the team that owns and
    deploys the affected service, in the tracker they already work in, with
    the target version and the affected services listed.
    
    Do not route to a central security queue. Security cannot patch a service
    it does not deploy, and a queue of tickets waiting to be handed on is a
    queue that only grows.
    
    Handle: a service with no owner, which is an ownership problem to
    escalate rather than a ticket to file; a finding in a third-party
    component with no available fix, which becomes a tracked mitigation; a
    false positive, which needs suppressing with an expiry so it does not
    hide a real finding later; and a fix that requires a breaking upgrade,
    which is a planning conversation rather than a patch.
  5. 5

    Warn before a target breaches, and expire acceptances

    A breach report is an apology and a warning is an action.

    Set remediation targets per band and alert before they breach instead of 
    after:
    
      fix-now: 7 days, alert at day 4
      fix-this-sprint: 30 days, alert at day 21
      fix-this-quarter: 90 days, alert at day 70
    
    Accepted risks always carry an expiry, maximum 90 days, with an owner and
    a written reason. On expiry the acceptance lapses and the finding returns
    for a decision.
    
    A permanent acceptance is a decision nobody revisits, usually made under
    release pressure by somebody who has since changed team.
    
    Report: findings by band, grouped fixes open and their age, time to
    remediate by band, acceptances expiring, and findings with no owner.
  6. 6

    Test it, then hand the ranking to security

    Because the risk model changes with the estate.

    Run the per-step schema checks and the whole-workflow audit before this
    touches production. Run it read-only for a fortnight and compare the
    ranking against what the team actually chose to fix.
    
    Then open the same workflow in Tray Build so security engineering can
    adjust the ranking weights, the targets and the grouping rules in the
    visual canvas.

What it connects to

Findings come from scanners and fixes ship from engineering, and the asset register connects them.

ServiceNow

Read the CMDB to resolve an affected host to its configuration item and owner, then raise the remediation record against it.

Reads and writes

Datadog

Read vulnerability findings with their CVE, component and affected host.

Reads

GitHub

Read dependency findings and the services affected, and open the pull request where the fix is a version bump.

Reads and writes

Jira

Create one ticket per grouped fix in the team's own tracker, with every finding it closes listed.

Writes

Okta

Resolve service owners to real people, so a fix routes to somebody rather than a team name.

Reads

Slack

Warn before a target breaches, and escalate a service with no owner.

Writes

Vanta

Push remediation evidence in, so the vulnerability management control is answerable from where audits are.

Writes

Snowflake

Land findings and remediation times, so time to remediate by band is 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, Azure Active Directory, Jira Service Desk, Databricks or Google Chat.

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 is a security control an auditor tests and an attacker benefits from you neglecting.

This runs as infrastructure, not as a script

Scanner ingestion, grouping and target warnings run continuously on the same engine, including for the finding published on a Friday night.

Every decision is recorded

Which ranking produced which band, who accepted a risk and until when. That record is the vulnerability management control an audit asks to see.

Credentials are managed, never written into the build

Scanner and asset inventory access describes every weakness in your estate. Read-only, scoped, and held in your workspace.

Security engineering own the ranking

Weights, targets and grouping rules open in Tray Build, tuned against what the team actually prioritises, not against a formula.

Acceptances always expire

Maximum 90 days with an owner and a reason. A permanent acceptance is a decision made under pressure that nobody ever revisits.

Questions people ask

Why not rank on CVSS?

Because CVSS describes the flaw and says nothing about your exposure to it. A critical on an internal test box outranks nothing; a medium on an internet-facing service with a published exploit outranks everything.

Why group by fix?

Because eleven thousand findings is frequently a few hundred actual fixes. One dependency upgrade closing forty findings is one piece of work, and presenting the raw count is why nobody starts.

Why route to engineering, not security?

Because security cannot patch a service it does not deploy. A central security queue is a place tickets wait to be handed on, and it only ever grows.

Why must accepted risks expire?

Because a permanent acceptance is a decision nobody revisits, usually made under release pressure by somebody who has since changed team. Ninety days maximum, with an owner and a reason.

What is the first thing to fix?

Findings that cannot be resolved to a known asset. They cannot be ranked, routed or closed, and they inflate the backlog while contributing nothing to it.

Vibe-coding app guides

Vibe-code an entire app with Helix

This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.

How to build a bug triage queue (opens helix.tray.ai in a new tab)

Last reviewed September 2026.