Docs › EU Cyber Resilience Act
CRA 24/72/14 Reporting Lint (Article 14)
Reads your SECURITY.md against the EU Cyber Resilience Act reporting clock that started on 11 September 2026 — 24 hours, 72 hours, 14 days, to ENISA and your coordinating CSIRT.
What it checks (18 rules: 13 error, 5 warn)
| Rule | Level | What it flags | Cites |
|---|---|---|---|
art14_no_24h_early_warning | error | No 24-hour early warning step. The clock starts when you become aware, not when you finish triage. | CRA Art. 14(1)(a), Art. 14(4)(a) |
art14_no_72h_notification | error | No 72-hour notification step. The early warning does not discharge the obligation on its own. | CRA Art. 14(1)(b), Art. 14(4)(b) |
art14_no_14day_final_report | error | No final report step. The 14-day clock runs from the moment a corrective measure is available, not from disclosure. | CRA Art. 14(2)(c) |
art14_no_enisa | error | ENISA is never named. Every Article 14 report goes to ENISA as well as to a CSIRT. | CRA Art. 14(1) |
art14_no_csirt | error | No CSIRT named. Reports go to the CSIRT designated as coordinator for your main establishment in the Union. | CRA Art. 14(1), Art. 14(7) |
art16_no_single_reporting_platform | warn | The single reporting platform is not mentioned, so the runbook does not say where the report is actually filed. | CRA Art. 16 |
art14_no_actively_exploited_trigger | error | The trigger is not defined. The duty attaches to an actively exploited vulnerability, not to every vulnerability you receive. | CRA Art. 14(1), Art. 3(42) |
art14_no_severe_incident_trigger | error | The second trigger is missing. A severe incident affecting the security of the product is reportable on the same clock. | CRA Art. 14(3), Art. 14(4) |
annex1_no_cvd_policy | warn | No coordinated vulnerability disclosure policy is referenced, so reporters have no stated route in. | CRA Annex I Part II(5) |
annex1_no_sbom | warn | No SBOM is referenced. Without one you cannot answer 'which shipped versions contain the component' inside 72 hours. | CRA Annex I Part II(1) |
annex2_no_contact_point | error | No single point of contact. There is no address a finder or an authority can reach you at. | CRA Annex II(4) |
art13_no_support_period_date | error | No support period end date in ISO form. A prose promise of 'ongoing support' is not a declared support period. | CRA Art. 13(8) |
wrong_start_date_2027 | error | Wrong start date. The reporting obligation already applies; December 2027 is when the remaining obligations follow. | CRA Art. 71(2) |
wrong_recipient | error | Wrong recipient on the Article 14 path. This report does not go there. | CRA Art. 14(1) |
gdpr_clock_confusion | error | Two different 72-hour clocks are being treated as one. The personal-data breach duty is a separate obligation with a separate recipient. | CRA Art. 14 vs GDPR Art. 33 |
response_window_in_days | warn | A response window measured in days sits next to an obligation measured in hours. A reporter reading this will assume the slower number. | CRA Art. 14(1) |
support_period_lapsed | error | The declared support period has already ended, while the product is still published. | CRA Art. 13(8) |
support_period_under_five_years | warn | The declared support period is shorter than five years from today. | CRA Art. 13(8) |
Run it
ext install ReadyStack.cra-24-72-14-reporting-lint # VS Code · Cursor/VSCodium via Open VSX npx -y @readystack/cra-24-72-14-reporting-lint SECURITY.md # CLI, free, every rule npx -y @readystack/cra-24-72-14-reporting-lint --dir . --ci # whole repository, exit 1 on errors (licence) docker run --rm -v "$PWD:/w" getreadystack/cra-24-72-14-reporting-lint /w # Docker
MCP (Claude Code, Cursor, Windsurf): check_text and check_file are free, check_dir needs a key.
{ "mcpServers": { "cra-24-72-14-reporting-lint": { "command": "npx", "args": ["-y", "@readystack/cra-24-72-14-reporting-lint", "--mcp"] } } }Sample report
A deliberately wrong sample file, then the real output of npx @readystack/cra-24-72-14-reporting-lint SECURITY.md on it. Nothing here is mocked.
Sample input (SECURITY.md)
# Security Policy We take security seriously. If you find a vulnerability, please email [email protected]. We will respond as soon as possible and fix confirmed issues in a future release. ## Supported versions Only the latest minor release receives security fixes.
Output
/tmp/s152_flag/samples/SECURITY.md
1 warn No coordinated vulnerability disclosure policy is referenced, so reporters have no stated route in.
-> Link the coordinated vulnerability disclosure policy and say what a reporter can expect from you.
1 warn No SBOM is referenced. Without one you cannot answer 'which shipped versions contain the component' inside 72 hours.
-> Reference the SBOM location and format so the notification can list affected versions.
1 error No support period end date in ISO form. A prose promise of 'ongoing support' is not a declared support period.
-> Write the support period end date as YYYY-MM-DD next to the words 'support period' or 'end of support'.
1 error No final report step. The 14-day clock runs from the moment a corrective measure is available, not from disclosure.
-> Step 3: final report no later than 14 days after a corrective or mitigating measure is available.
1 error No 24-hour early warning step. The clock starts when you become aware, not when you finish triage.
-> Step 1 of the runbook: early warning to the coordinating CSIRT and ENISA within 24 hours of awareness.
1 error No 72-hour notification step. The early warning does not discharge the obligation on its own.
-> Step 2: vulnerability or incident notification within 72 hours, with severity, impact and any corrective measures taken.
1 error The trigger is not defined. The duty attaches to an actively exploited vulnerability, not to every vulnerability you receive.
-> Define 'actively exploited' in the runbook and say who decides that a report has crossed the line.
1 error No CSIRT named. Reports go to the CSIRT designated as coordinator for your main establishment in the Union.
-> Name the Member State and the coordinating CSIRT you report to, so the on-call engineer does not have to find it at 3am.
1 error ENISA is never named. Every Article 14 report goes to ENISA as well as to a CSIRT.
-> Name ENISA as a simultaneous recipient of the early warning, the notification and the final report.
1 error The second trigger is missing. A severe incident affecting the security of the product is reportable on the same clock.
-> Add the severe-incident trigger alongside the actively-exploited-vulnerability trigger.
1 warn The single reporting platform is not mentioned, so the runbook does not say where the report is actually filed.
-> State that reports are submitted through the single reporting platform and record the account that can file them.Free and licence
| Free | Checks the Markdown file you have open against all 18 rules, offline, with the article and the replacement line for every finding — no watermark, no counter, nothing withheld. |
|---|---|
| With a key ($29 once) | Sweeps every Markdown file in the workspace in one pass, works out which checks are answered nowhere in the repository rather than merely missing from one file, and writes one dated CRA-24-72-14-READINESS.md to hand to an auditor. |
The full run is free for the first 7 days. 7-day refund on every key. Worth it because: One hour of EU product-compliance consulting runs $150-250, and a first documentation review is rarely one hour.
Get the key, $29 once Team key, every linter, $149
What comes next
The same vendor then owes a CSAF advisory and an SBOM that names affected versions inside the 72-hour window.
Questions
What does this actually do?
It reads a Markdown file — SECURITY.md, a coordinated disclosure policy, an incident runbook — and names every line that will not survive EU Cyber Resilience Act Article 14. Eighteen rules cover the 24-hour early warning, the 72-hour notification, the 14-day final report, the recipients, the two triggers, and the supporting facts an auditor asks for. Each finding carries the article it comes from and one replacement line.
Who is it for?
Maintainers and compliance leads at vendors placing software on the EU market, who own the security documents. It is written for the person who will be woken at 3am by an actively exploited vulnerability and needs the runbook to say who to notify, by when, and through which platform. Open-source stewards carry a lighter duty under Article 24; the rules here flag the manufacturer path.
Why not just ask a chatbot or use a free checklist?
Because they get the two questions wrong that matter most. General assistants still quote 11 December 2027 as the reporting start date — that is when the remaining obligations apply, while reporting has applied since 11 September 2026. They also reuse the GDPR Article 33 runbook, which has a similar 72-hour number but a different recipient and a different trigger. This linter checks your actual file for both mistakes.
What is free and what needs a licence?
Checking the file you have open is free forever, for personal or commercial use, with the complete rule set and no limits. The licence widens the scope: it sweeps every Markdown file in the workspace at once, reports which checks are answered nowhere in the repository, and writes one dated readiness report. The free scope finishes the job of fixing one document.
What would this cost if a person did it?
One hour of EU product-compliance consulting runs $150-250, and reviewing a security policy against Articles 13, 14 and 16 is rarely a single hour. The licence is $29 once, with a 7-day full refund. The linter does not replace counsel on scope or product classification; it removes the mechanical errors before anyone bills you to find them.
A linter tells you what the rule says and where your file disagrees. It is not legal advice; the rule set carries its own date and is updated when the regulation moves.
Install free
Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.
VS Code MarketplaceOpen VSX (Cursor, VSCodium)npmMCP server (npx)Docker Hubext install ReadyStack.cra-24-72-14-reporting-lint npx @readystack/cra-24-72-14-reporting-lint <file> npx @readystack/cra-24-72-14-reporting-lint --mcp
Team? One key for every ReadyStack linter, 5 seats, $149 once