Fix-by SLA
Every open finding (SAST, dependencies, container images, malware) carries an inline SLA pill next to its severity. The pill is computed from one input — how old the finding is — and one config — your org’s severity-SLA policy.
Defaults
Out of the box, every org gets these targets:
| Severity | Default SLA |
|---|---|
| Critical | 7 days |
| High | 30 days |
| Medium | 90 days |
| Low | no SLA |
These defaults align with common enterprise patching cadences cited in NIST SP 800-40r4 and similar frameworks. Tighten them if your audit posture demands it.
States the pill can show
- Within (green) — under the SLA, less than 80% of the way to the deadline.
- Approaching (amber) — between 80% and 100% of the deadline. Plan a fix this week.
- Breached (red) — past the deadline. Counted in the weekly digest and the overview “SLA breaches” tile.
- No SLA (grey) — severity has no policy attached (the default for
low).
The 80%-of-deadline threshold for approaching is deliberate — most fixes take real work to dispatch, review, and roll out, and surfacing the warning before the deadline gives you that runway.
Setting per-org policy
The per-org SLA is editable under Security › Prioritise › Fix-by SLA (/<org>/_admin/security/prioritise/sla). Pick a tighter deadline per severity — the breach calculation reads the per-tenant security_sla_policy row immediately, no re-scan needed. The defaults above apply until you override them. If you need a custom non-time-based SLA shape (e.g. business-day clocks, holiday calendars), open a support ticket.
Findings that are not reachable (opt-in multiplier)
For dependency and container-image findings, fremforge computes a reachability verdict. Your org can stretch the SLA of findings whose verdict is not reachable (unreachable) by a whole factor from 1 to 4, with the multiplier on the same page, Security › Prioritise › Fix-by SLA. The default, 1, is off.
| Verdict | SLA |
|---|---|
No call path (unreachable) | The full SLA × the multiplier |
| Reachable, unknown, or not analysed | The full SLA, always |
| Known exploited: listed by EU (ENISA EUVD) or US (CISA KEV) | The full SLA, at any severity and whatever the verdict |
| Critical with EPSS in the top 10 % | The full SLA, whatever the verdict |
The deadline is always counted from when the finding was first seen. If a later scan finds a call path, or cannot decide, the full SLA applies again at once, so a finding can go straight to Breached. A stretched pill shows ×2 (or ×3, ×4), and its tooltip gives both deadlines; with the multiplier on, a full-SLA pill’s tooltip says why it is not stretched. SAST, licence, secret and malware findings have no verdict and keep the full SLA.
The multiplier changes deadlines only. What blocks a pull request is unchanged, and no finding is hidden or dismissed.
Findings on protected release branches show a fix-by date from this policy too, but they are not counted in SLA breaches, the SLA tile or any SLA metric.
Note on SLA scope. The table above is the finding-remediation clock — how long you have to close a finding raised against your code. That’s distinct from two other SLAs documented elsewhere on fremforge:
- The platform CVE patch SLA (Critical 48h / High 72h / Medium 7d) covers how fast fremforge patches its own stack — see the platform-security commitments on Security and supply chain.
- The vulnerability disclosure SLA (Critical fix in 24h / disclose 30d after fix, etc.) covers researcher-reported vulnerabilities in fremforge itself — see Vulnerability disclosure.
Via REST API
The severity-SLA policy can be set on the public API surface — useful when you want to enforce a consistent posture across many orgs from a configuration script or compliance pipeline.
- Update policy
PUT /_app/api/v1/orgs/:slug/security/sla-policybody:{ "critical_sla_days": 3, "high_sla_days": 14, "medium_sla_days": 60, "low_sla_days": null, "unreachable_sla_multiplier": 2 }
Each day field accepts 1–365 days, or null to leave a severity without an SLA; an absent day field is null. unreachable_sla_multiplier accepts a whole number from 1 (off) to 4; unlike the day fields, leaving it out keeps the stored value. GET /_app/api/v1/orgs/:slug/security returns the policy. Every change is audited as code-security.sla_policy.updated, with the previous multiplier when it changed. Requires a Personal Access Token (PAT) with the policy:write scope:
curl -X PUT \
-H "Authorization: Bearer ${FREMFORGE_PAT}" \
-H "Content-Type: application/json" \
-d '{"critical_sla_days":3,"high_sla_days":14,"medium_sla_days":60,"low_sla_days":null}' \
https://frem.sh/_app/api/v1/orgs/acme/security/sla-policySee the public REST API reference for the full OpenAPI specification.
The compliance report measures SLA compliance over a period you choose: findings fixed within their SLA, fixed after it, and still open past it, per severity. With the multiplier on, it measures each finding against the same deadline as its pill and shows the policy SLA next to the stretched one.
How breaches feed other pages
- Open security PRs widget on
/<org>/_admin/overviewhighlights the highest-severity breached recommendation first. - Weekly digest counts breaches in the headline summary.
- SIEM forwarding emits
code-security.sla.breachedaudit events the first time a finding crosses the line. With the multiplier on, a stretched finding’s event also carriesfull_sla_daysandunreachable_sla_multiplier.
The digest count, the overview tile and the SIEM event all use the same deadlines as the pills, the multiplier included. The findings API returns them too, as an sla object on every dependency and image finding (state, sla_days, due_at, full_sla_days, full_due_at, unreachable_multiplier, exempt). exempt is known_exploited (with exempt_sources: euvd, cisa_kev) or exploit_likely (critical, EPSS in the top 10 %) when an opted-in multiplier was not applied for that reason, else null.
See also
- OSV recommendations — the fix list that closes the loop.
- Push protection — secrets get pre-receive treatment instead of an SLA clock.