Running CRA Article 14 reporting from a spreadsheet: a free template, and where it breaks
- article-14
- deadlines
- templates
- vulnerability
- incident
You can run CRA Article 14 reporting from a spreadsheet. For a small vendor with one or two products and a named owner, it is a reasonable starting point. This post gives you a free CRA reporting template, the columns a vulnerability tracker needs, and the exact Excel and Google Sheets formulas for every deadline. It also lists the five places a spreadsheet tends to break. You can download the CSV template and follow along.
Can you run CRA Article 14 reporting from a spreadsheet?
Yes, if three conditions hold. One person owns the sheet and has a deputy. Someone checks exploitation feeds against what you ship every day, including weekends. And the sheet records facts, not just deadlines: when you became aware, who decided, and when each filing was submitted. Without those, the sheet looks like a process but cannot prove one.
Article 14 has two families of report, and the sheet must handle both. An actively exploited vulnerability in your product triggers the duty in Article 14(1).Art. 14(1) A severe incident having an impact on the security of your product triggers Article 14(3).Art. 14(3) Each has an early warning, a notification and a final report, all submitted through ENISA's Single Reporting Platform to the CSIRT designated as coordinator and to ENISA. The platform has no API, so someone fills in the form by hand and the sheet records the reference it returns.
What columns does a CRA vulnerability tracker need?
One row per case, with 26 columns. A case is any signal you assessed, including those you decided were not reportable. The CSV template uses these columns, in this order, so the formulas below can refer to them by letter.
| Columns | Group | What goes in them |
|---|---|---|
| A–D | Case | case_id, product, affected_versions, case_type (vulnerability or incident) |
| E–F | Signal | signal (what arrived: a KEV listing, a researcher's email, a customer ticket), signal_received_utc |
| G–J | Triage | triage_status (assess, not reportable, reportable), triage_decided_by, triage_decided_utc, triage_reasoning |
| K | Awareness | aware_utc, filled only when the case is decided reportable |
| L–N | Early warning | early_warning_due_utc, early_warning_submitted_utc, early_warning_srp_ref |
| O–Q | Notification | notification_due_utc, notification_submitted_utc, notification_srp_ref |
| R–U | Final report | fix_available_utc, final_report_due_utc, final_report_submitted_utc, final_report_srp_ref |
| V–X | Report content | member_states, csirt_coordinator, unlawful_or_malicious (incidents only) |
| Y–Z | Record | aware_amendments, notes |
Three columns deserve a word. signal_received_utc and aware_utc are different on
purpose: the first is when information arrived, the second is when your company concluded
the product was affected. What becoming aware actually means
explains why the gap between them is what you will be asked to explain.
unlawful_or_malicious answers a question the incident early warning must address:
whether the incident is suspected of being caused by unlawful or malicious acts.Art. 14(4)(a)
csirt_coordinator records which CSIRT you report to, which where to report
helps you work out.
The two example rows are marked "EXAMPLE – delete". Their products, people and references are fictional. Delete them before you use the sheet.
The CRA deadline formulas for Excel and Google Sheets
Each deadline is a fixed offset from one recorded fact. Excel and Google Sheets store a
date-time as a number of days, so 24 hours is +1 and 72 hours is +3. Paste these into
row 2 and fill down. Every column holds UTC, and the formulas never convert.
| Report | Deadline | Clock starts at | Formula (row 2) |
|---|---|---|---|
| Early warning, both families | 24 hours | Awareness | =IF(K2="","",K2+1) in L |
| Notification, both families | 72 hours | Awareness | =IF(K2="","",K2+3) in O |
| Final report, vulnerability | 14 days | Fix available | see below, in S |
| Final report, incident | 1 month | Notification submitted | see below, in S |
The early warning and notification rules are in Article 14(2)(a) and (b) for vulnerabilities and Article 14(4)(a) and (b) for incidents.Art. 14(2) The final report needs one formula that chooses the rule by case type:
=IF(D2="vulnerability",IF(R2="","waiting for a fix",R2+14),IF(D2="incident",IF(P2="","record the notification submission time",EDATE(P2,1)+MOD(P2,1)),""))
It is on one line because pasting a multi-line formula into a sheet splits it across rows.
The vulnerability branch counts 14 days from fix_available_utc, not from awareness.Art. 14(2)(c)
The incident branch counts one month from notification_submitted_utc, not from the
72-hour deadline.Art. 14(4)(c) If the fact the clock depends on is
missing, the cell says so in words rather than showing a date.
Format L, O and S as yyyy-mm-dd hh:mm. Otherwise Excel shows a serial number such as
46284.69: the first example row's early-warning deadline, correct and unreadable. The
CSV uses the same format, which both programs read as a date-time on import.
Why the incident final report is not "30 days"
"One month" is a calendar month. EDATE(P2,1) moves the date to the same day of the next
month, and to the last day of the month when that day does not exist. Adding 30 lands on a
different day whenever the months involved are not 30 days long:
| Notification submitted | One month (EDATE) | Plus 30 days | Error with +30 |
|---|---|---|---|
| 1 October 2026 | 1 November 2026 | 31 October 2026 | 1 day early |
| 1 December 2026 | 1 January 2027 | 31 December 2026 | 1 day early |
| 30 January 2027 | 28 February 2027 | 1 March 2027 | 1 day late |
| 31 January 2027 | 28 February 2027 | 2 March 2027 | 2 days late |
One more trap. EDATE returns a date with no time of day, so a notification submitted at
17:45 would get a deadline of midnight. +MOD(P2,1) adds the time back. The full rules,
with their asymmetry, are in
why the final report isn't due 14 days after the bug.
Overdue flags
Add conditional formatting to colour a row when a deadline has passed with nothing
submitted. For the early warning, the rule is =AND($L2<>"",$M2="",NOW()>$L2). Repeat it
for the notification ($O2, $P2) and the final report ($S2, $T2). Read the first
failure mode below before you trust NOW().
Where a CRA spreadsheet breaks
A spreadsheet stores numbers well and enforces nothing. These five failures are the ones the column design above cannot prevent on its own.
- Time zones. A date-time in a cell has no time zone. If someone in Berlin types the
awareness time in local time, every deadline in that row is two hours off until 25
October 2026, then one hour off. Our own form had
the same bug, two hours apart. In Google Sheets, set
the spreadsheet's time zone to GMT without daylight saving (File, then Settings), so
NOW()is UTC too. Excel has no time zone setting, andNOW()is your computer's local time. Keep the UTC offset in a cell and compare withNOW()-offset/24, and change that cell when the clocks change. - Nobody watched the feeds today. The sheet holds cases only once someone enters them. Someone must check the CISA KEV catalogue and the ENISA EUVD against what you ship every day, and your own product names against them too. The 24 hours do not pause for a holiday. The free KEV check compares an SBOM with the catalogue, but only when someone runs it.
- The awareness time gets overwritten.
aware_utcmoves three deadlines at once. In a spreadsheet, anyone with edit access can change it, and the old value is gone. Protect column K once it is filled, and put every change inaware_amendments, with the old value, the new value, who changed it and why. The second example row shows one. - There is no audit trail. Version history shows that a cell changed. It does not show that a "not reportable" decision was made by a named person, on the evidence, at the time. Record every decision, including every "no", with the same care as a filing. Months later, the question is whether you had a process and whether it ran.
- The open-ended wait between 72 hours and a fix. A vulnerability case can sit after
the notification with no deadline at all, because the final-report clock has not
started. The sheet shows "waiting for a fix" for weeks. Then a release ships, nobody
fills in
fix_available_utc, and the 14 days run unseen. Tie that column to your release process, not to the person who owns the sheet.
When to move off the spreadsheet
Move when one of those failures has already happened to you, or when you can no longer name who checks the feeds on a Sunday. Other signs are a second product line, a second team, or a customer asking to see your evidence. At that point, the work is running the process, not keeping the formulas right. That is the part a tool can take over, with daily feed checks, a locked awareness time and a log of every decision. If you want to compare costs, our pricing is public. The manufacturer stays responsible for every report either way.
The documents that describe the process, such as the vulnerability handling policy, are a separate job. Our document outlines cover those.
Where to start
- Download the CSV template, open it in Excel or Google Sheets, delete the two example rows, and paste the formulas into L, O and S.
- Set the sheet to UTC and say so in every date column header. The template's headers
already end in
_utc. - Name an owner and a deputy, and set a daily feed check in someone's calendar, weekends included.
- Read Article 14 in plain language with the sheet open, and check that each column matches the stage it records. The Regulation itself is on EUR-Lex.
Frequently asked questions
Can a small company track CRA Article 14 reporting in a spreadsheet?
Yes, if you have few products, one named owner and a daily habit of checking exploitation feeds. The sheet must store awareness in UTC, keep the recorded awareness time unchanged, and hold the submission times the final-report clocks depend on.
How do I calculate the CRA 24-hour early warning deadline in Excel?
Store the awareness time as a UTC date-time and add 1, because Excel and Google Sheets count in days. The 72-hour notification is awareness plus 3. Format the result as yyyy-mm-dd hh:mm and label the column UTC.
Is the CRA incident final report due 30 days after the notification?
No. Article 14(4)(c) gives one month after submission of the incident notification. A calendar month and 30 days differ by up to two days. In a spreadsheet, use EDATE on the submission time and add the time of day back.
When is the final report due for an actively exploited vulnerability under the CRA?
Within 14 days after a corrective or mitigating measure becomes available, under Article 14(2)(c). It does not run from awareness, so until a fix exists the sheet should show that the clock has not started.
Checked against Regulation (EU) 2024/2847 as of 1 October 2026. Written by the team that builds Declara.
Not sure whether this applies to you?
This produces evidence, timelines and drafts. It is not legal advice, and you remain the party responsible for reporting.