Articles

NIS2 belongs in the code

NIS2 has been Danish law since 2025. Controls in a spreadsheet go stale the moment someone changes a system. Controls in the code keep up.

Who is covered, and who supervises

Denmark has implemented NIS2 in three laws. The energy sector got its own, Act no. 258 on strengthened preparedness in the energy sector, in force from 7 March 2025. Telecoms got Act no. 435 and most other sectors Act no. 434, both in force from 1 July 2025. Banks and financial market infrastructure are covered by the EU’s DORA regulation, which takes precedence over NIS2.

The energy act is broad. It covers electricity, gas, oil, district heating, district cooling and hydrogen, and charging points and filling stations above a certain size. As a rule it applies to companies with at least 50 employees or more than €10 million in turnover and balance sheet. Every grid company is covered regardless of size. Supervision sits with the Ministry of Climate, Energy and Utilities, in practice the Danish Energy Agency.

Under the general NIS2 act no authority designates you. You must assess for yourselves whether you are covered and register on virk.dk; the deadline was 1 October 2025. Energy companies report to the Danish Energy Agency instead, which places them in levels. The first deadline was 1 April 2025.

Management is in the front line. The energy act empowers the minister to require that management approves the risk assessment, the preparedness plans and the supplier contracts, and acquires knowledge of risk management itself. If an essential entity does not comply with an order within the deadline set, the minister can temporarily bar the CEO from exercising management functions in the company. And the directive gives you 24 hours for an early warning after you become aware of a significant incident, 72 hours for a notification and one month after the notification for the final report.

Sixteen days in May 2023

On 25 April 2023 Zyxel announced a critical hole in a range of its firewalls, and the update was ready. Many Danish energy companies run them in front of their control systems. SektorCERT, the shared cybersecurity centre of Denmark’s critical sectors, warned its members again on 1 May.

On 11 May, 16 days later, a group attacked 16 selected energy companies with a single network packet each. 11 were compromised. Over May, 22 companies were hit, and several had to run in island mode.

According to SektorCERT, most of the attacks succeeded because the update had not been installed. The reasons were ordinary. Some believed a new firewall had the latest software. Some believed the vendor took care of it. Some had opted out of the update because the vendor charged to install it. Some did not know they had the device, because a vendor had set it up. And some believed it was updated when it was not.

This is not particular to Denmark. In 2025 ENISA asked 1,080 organisations in the EU’s NIS sectors how long it takes to apply a critical patch to a critical system. 8 % do it within a week. 28 % take more than three months. One in two names patching as one of the hardest NIS2 requirements.

Only 8 % close a critical hole within a week

How long it takes to apply a critical patch to a critical system, IT or OT. The attack in May 2023 came 16 days after the patch.

Within a week
8 %
Within a month
31 %
Within three months
32 %
More than three months
28 %
Varies or not tracked
1 %
Source: ENISA, NIS Investments 2025, fig. 14. 1,080 organisations in the EU’s NIS sectors in all 27 member states, May–August 2025, 83 % large enterprises.

Why the spreadsheet does not hold

Several of the companies that were hit believed their firewall was updated. It probably said so in a document somewhere, too.

The typical NIS2 effort is a spreadsheet. Each row is a requirement, each column a control, an owner and a status. It is filled in once a year by someone who does not change the systems.

The systems change every day. A new user, an opened port, a new supplier with access to operations. The spreadsheet describes the landscape as it looked when it was filled in.

When the supervisor comes, it will want evidence. Who had access to the control system on 3 March? What changed in the firewall that week? Does the log from the night to the 4th exist? The spreadsheet cannot answer. The systems can, if they are built for it.

Three controls that belong in the code

The energy act lists the cybersecurity measures the minister can require. Three of them are easier to prove in code than in a document.

Access. Who has access to what, and in which role, is written in the code and changed through a pull request that someone else approves. Multi-factor authentication is switched on in the configuration, not in a guideline. The list of access rights is the repository, and its history is the repository’s log.

Logging. Every system that is deployed gets its logging from the start: what is logged, where it is sent and how long it is kept. The alerts are code too. A new system cannot go into operation without being visible.

Change. Nobody changes operations by hand. Every change goes through a pipeline that shows what will happen before it happens, and records who approved it. What runs, and in which version, is written in the code, so no device is unknown. If operations drift from the code, a daily check finds it, including the firewall everyone believed was updated.

The evidence for the supervisor becomes a by-product. The question about 3 March is answered with a query, not a meeting.

Two examples from operations

For Sinal and Norlys we built an observability platform on open source that traces a fibre order across the systems. It went into production in an OT environment under NIS2 requirements in six months.

For the grid company N1 we built, through VaaS.Digital, a platform that moves millions of meter readings a day between the company’s systems, under NIS2 and OT requirements and with Terraform as the release environment. It took about a year from the first stakeholder meeting to a platform in operation.

In both cases security was part of what was deployed. It was not added afterwards.

Where to start

Pick one system that supports your most important service.

Describe access to it as code, and let changes go through an approval.

Set up logging as part of the deployment, with alerts.

Close off changes by hand, and set up a daily check that finds drift.

Put the spreadsheet next to it, and see which rows the code now answers.