APS-81Recommended
Fix each finding within the time its severity allows
Triage every reported vulnerability within 2 working days. Fix a critical one within 7 days, high within 30, medium within 90 and low within 180, or record a dated risk acceptance.
How to do it
Count from the moment a person, a scanner or a researcher reports it. Triage means reproduce it, rank it as rank findings by harm says and name one owner. A hole that attackers already use, or that is on a known-exploited list such as CISA KEV, counts as critical. In a product under the Cyber Resilience Act, an actively exploited hole also starts the 24-hour early warning in report exploited vulnerabilities. Keep the severity, owner and due date in the issue tracker, where a job can read them. A finding that cannot be fixed in time goes into the risk register with a workaround and a new date. This is the one home of these deadlines. Security updates to software you run follow them too, as keep software current and quiet says.
Examples
JavaScript example
const FIX_DAYS = { critical: 7, high: 30, medium: 90, low: 180 };
const DAY_MS = 86_400_000;
export const dueDate = (reportedAt, severity, isKnownExploited) =>
new Date(new Date(reportedAt).getTime() + FIX_DAYS[isKnownExploited ? 'critical' : severity] * DAY_MS);
export const overdue = (issues, now = new Date()) =>
issues.filter(issue => !issue.riskAccepted && dueDate(issue.reportedAt, issue.severity, issue.knownExploited) < now);
Python example
from datetime import datetime, timedelta
FIX_DAYS = {"critical": 7, "high": 30, "medium": 90, "low": 180}
def due_date(reported_at: datetime, severity: str, is_known_exploited: bool) -> datetime:
return reported_at + timedelta(days=FIX_DAYS["critical" if is_known_exploited else severity])
def overdue(issues: list[dict], now: datetime) -> list[dict]:
return [i for i in issues
if not i.get("risk_accepted") and due_date(i["reported_at"], i["severity"], i["known_exploited"]) < now]
How to check
A daily job reads every open issue labelled security. Each has a severity, an owner and a due date that matches the table. The job fails on an issue past its due date without a risk register entry, or untriaged after 2 working days.
Sources
Related rules
- SEC-6 Rank findings by harm in Adversarial testing
- CMP-73 Publish an advisory for every fixed vulnerability in Compliance and governance
- IOT-37 Make every report and advisory name the model and firmware version in Connected devices
- OSS-22 Send private reports to at least two people in Open source maintenance
- OSS-24 Agree the publication date with the reporter in Open source maintenance
- OSS-28 Publish a cybersecurity policy as an open source steward in Open source maintenance
- OSS-35 Answer every new issue and pull request within a set time in Open source maintenance
- APS-67 Keep software current and quiet in Application security
- APS-106 Say which known holes do not affect you with VEX in Application security
- CMP-49 Report exploited vulnerabilities in your products in Compliance and governance
- CMP-39 Keep a risk register with treatment dates in Compliance and governance
- APS-107 Publish a vulnerability disclosure policy in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/application-security/errors-logs-and-vulnerabilities/fix-deadlines">Agent Wranglers application security playbook</a>. In code you write, add a comment next to it with the same link.