Remediations
A remediation is the tracked fix for a security issue: who owns it, when it is due, what was done, and how it was verified. Frameworks that require monitoring also require acting on what monitoring finds, and a documented issue that was never addressed is a process gap auditors will note. A well-run remediation has an owner, a deadline derived from severity, and verifiable artifacts such as a merged pull request or a configuration change.
Auditors test this chain by sampling. A typical request is "show me a critical finding from the review period and walk me through what happened to it." Answering well requires the finding, the remediation that addressed it, who owned it, when it was due, when it completed, and how the fix was verified, all connected. Remediation records exist to hold that join between the security issue, the engineering work, and the verification, which a ticketing system alone typically cannot reconstruct.
Remediation is also not the only valid outcome. Some issues get fixed, some get mitigated by a compensating control, and some get consciously not fixed because the cost outweighs the exposure. The last category is legitimate when it is documented: risk acceptance needs a rationale, an owner, and periodic review.
How Remediations Work in Openlane
A remediation record tracks one corrective effort from plan to verification. Status follows the corrective lifecycle: open, in progress, then an in-review step for independent verification before completion. A deliberate decision not to fix is recorded as won't-do with the rationale documented, which is a defensible answer at audit time where a silently closed record is not.
The record carries the plan itself (intent, summary, explanation, and step-by-step instructions) alongside the engineering trail: a ticket reference, the repository URI, and the pull request URI, so the security record and the code change point at each other. Each record carries a due date and completion date, giving you an unambiguous overdue query and a provable time-to-fix.
Relationships are what make the record useful. A remediation links to the findings and vulnerabilities it resolves, the scans involved in verifying it, the risks it reduces, and the controls, tasks, and action plans it supports. Attached files hold before-and-after evidence. Per the exposure pipeline, completed remediations are the events that verify fixes and update risk posture. The full field list is in the API reference.
Working with Remediations
Turn Triage into Assigned Work
When triage validates a finding or vulnerability, create a remediation linked to it with an owner reference, a ticket reference, and a dueAt derived from the issue's remediation service level agreement (SLA). Put the fix approach in the intent and instructions fields rather than only in the ticket, so the security record stands on its own when the ticketing system is out of scope for an auditor.
Run a Weekly Overdue Review
Query remediations where dueAt has passed and status is not COMPLETED or WONT_DO. That list is your escalation agenda: items stuck in OPEN need an owner decision, items stuck in IN_REVIEW need a verifier. Doing this weekly keeps SLA breaches an internal finding you caught instead of an audit finding someone else did.
Verify Before You Close
Move a remediation to IN_REVIEW when the fix lands, and attach the pull request URI and any evidence files. We recommend verification independent of the implementer where possible: a re-run scan showing the issue gone, or the source integration now reporting the finding inactive. Only then set COMPLETED with completedAt, update the linked vulnerability or finding, and revisit the linked risk to record the reduced exposure.
Document What You Will Not Fix
Use WONT_DO with the rationale in the explanation field, and pair it with the corresponding decision on the source record, such as a dismissal reason on the vulnerability. If the acceptance is significant or recurring, link the remediation to a risk so the exposure is owned in the register rather than closed out of sight.
FAQ
How is a remediation different from a task or action plan?
A remediation is a corrective action tied to a specific security issue: it exists because a particular finding, vulnerability, or scan result needs resolving, and it carries the engineering artifacts of the fix. Tasks and action plans cover broader work that may have nothing to do with a discovered issue. A remediation can link to tasks and action plans when the fix decomposes into multiple pieces of work.
What belongs in the IN_REVIEW stage?
Verification that the fix worked, ideally by someone other than the implementer. Attach the pull request, then confirm through a re-run scan or the source integration reporting the issue resolved. Moving straight from IN_PROGRESS to COMPLETED on the implementer's word is the pattern auditors flag, because unverified fixes are how issues reopen.
Is marking a remediation WONT_DO the same as accepting the risk?
WONT_DO documents the decision on the work item; risk acceptance is the governance judgment behind it. For low-stakes cases the documented rationale on the remediation may be enough. For significant exposure, also record the decision where it belongs: a dismissal reason on the vulnerability, or a linked risk in the register with an accountable owner. See risk management for treatment decisions.
Examples
- CSV
- GraphQL
- Go Client
- CLI
# Create
Title,State,DueAt,OwnerReference,TicketReference,RepositoryURI,PullRequestURI
Rotate exposed credentials,pending,2026-02-20T00:00:00Z,Security Platform,SEC-4821,https://github.com/acme/app,
Harden TLS policy,in_progress,2026-02-18T00:00:00Z,Infra Team,INF-992,https://github.com/acme/infrastructure,https://github.com/acme/infrastructure/pull/224
# Update
ID,State,CompletedAt,PullRequestURI,TicketReference
RMD01J9REMD1111111111111,completed,2026-02-16T14:32:00Z,https://github.com/acme/infrastructure/pull/224,INF-992
RMD01J9REMD2222222222222,in_progress,,https://github.com/acme/app/pull/811,SEC-4821
mutation {
createRemediation(
input: {
title: "Rotate exposed credentials"
state: "pending"
intent: "Revoke and replace exposed credentials"
ticketReference: "SEC-4821"
}
) {
remediation {
id
title
}
}
}
mutation {
updateRemediation(
id: "RMD01J9REMD1111111111111"
input: {
state: "completed"
pullRequestURI: "https://github.com/acme/infrastructure/pull/224"
}
) {
remediation {
id
state
}
}
}
ctx := context.Background()
title := "Rotate exposed credentials"
state := "pending"
_, err := client.CreateRemediation(ctx, graphclient.CreateRemediationInput{
Title: &title,
State: &state,
})
if err != nil {
return err
}
updatedState := "completed"
_, err = client.UpdateRemediation(ctx, "RMD01J9REMD1111111111111", graphclient.UpdateRemediationInput{
State: &updatedState,
})
if err != nil {
return err
}
openlane remediation create \
--title "Rotate exposed credentials" \
--state pending \
--intent "Revoke and replace exposed credentials" \
--finding-ids "FIND01J9FIND1111111111111"
openlane remediation update \
--id "RMD01J9REMD1111111111111" \
--state completed