From finding to fixed: tickets, SLAs, and a workflow that isn't a spreadsheet
Part of my series on RiskRancher, the open-source vulnerability manager I build. Source: github.com/Kuebiko-LLC/risk-rancher-core.
Intro
Ingesting and deduping findings gets you a clean list. But a clean list is still just a list, and the reason most teams’ “system of record” is a spreadsheet is that nobody built the part where findings turn into tracked, deadlined work. That’s the part that actually reduces risk, so in RiskRancher every finding becomes a ticket with a lifecycle and an SLA. This post is about that workflow.
I. A finding is a ticket with a status
Once a finding lands, it’s a ticket, and it moves through a small, honest set of states. It starts life as Waiting to be Triaged, and ends up either Patched (you fixed it) or Risk Accepted (you decided, on purpose, to live with it).
That last state matters more than it looks. Real security work isn’t “fix everything,” it’s “fix what’s worth fixing and consciously accept the rest.” Having “Risk Accepted” as a first-class status means the decision to not fix something is recorded and visible, instead of a finding quietly rotting unaddressed. The open-work views then exclude both Patched and Risk Accepted, so your active queue is only the things that still need a decision or a fix.
II. SLAs by category and severity
A deadline is what turns a ticket from a suggestion into an obligation. RiskRancher attaches an SLA to each ticket based on two things: what kind of issue it is, and how severe. The defaults look like this:
| Category | Severity | Deadline | Extensions |
|---|---|---|---|
| Vulnerability | Critical | 14 days | allowed |
| Vulnerability | High | 30 days | allowed |
| Privacy | Critical | 3 days | none |
| Incident | Critical | 24 hours | none |
Two design points there. First, category matters as much as severity: a critical privacy issue (3 days, no extensions) is treated more strictly than a critical vuln (14 days), because the clock on a privacy or incident obligation is often legal, not just operational. Second, some SLAs explicitly forbid extensions. A 24-hour incident deadline you can quietly extend isn’t a deadline. These are defaults you configure, but the shape of the policy is the point: urgency is a function of what the thing is, not only how bad it is.
III. Grouped by asset, because that’s how fixes happen
Tickets are grouped by asset. When you’re actually remediating, you don’t fix “finding #4,812,” you fix a host, an image, or a repo, and knock out everything wrong with it while you’re in there. So the dashboard gathers a ticket’s siblings by its asset identifier, and the practitioner view is “here is everything wrong with this asset,” which maps to how the work really gets done.
Conclusion
The gap between a scanner and a safer system isn’t storage, it’s workflow: a status that includes the honest option of accepting risk, an SLA whose urgency depends on category and severity, and a view organized by asset so fixes happen in batches. That’s the difference between a list of problems and a system that closes them. Thanks for reading, and may your tickets reach Patched before their SLA does.