heygrc
Guide

NIS 2 software requirements: what lands in a pull request

NIS 2 sets cybersecurity risk-management duties for EU essential and important entities, and most coverage treats it as policy and process. One measure, secure development and vulnerability handling under Art. 21(2)(e), is decided by what actually ships. Which changes trip it, a worked example distinct from the framework hub, and what a review can and cannot catch.

the heygrc team

NIS 2 (Directive (EU) 2022/2555) names ten cybersecurity risk-management measures at Art. 21(2), and most compliance write-ups cover them as policy and process: an information security policy, an incident-handling procedure, a business continuity plan. That is accurate for most of the list. It is incomplete for the one measure decided by what a team actually ships: Art. 21(2)(e), security in the acquisition, development and maintenance of network and information systems, including vulnerability handling and disclosure.

This guide is for developers whose organisation is in scope for NIS 2, an essential or important entity under the directive, or a supplier feeding one, and who want to know which part of that measure a pull request review can actually catch, distinct from the supply-chain and cyber-hygiene measures the framework hub already covers.

Who this is for, and the size-cap rule

NIS 2 applies to medium and large entities under the size-cap rule (broadly, 50 or more staff, or annual turnover and annual balance-sheet total both above EUR 10 million) operating in the sectors Annex I and Annex II of the directive list: energy, transport, banking, health, and digital infrastructure among others in Annex I; postal services, chemicals, food, and manufacturing among others in Annex II. Sector alone does not decide essential versus important: within Annex I, a large entity meeting the size-cap is generally classified 'essential' and a medium entity generally 'important'; an Annex II entity meeting the size-cap is generally classified 'important' whether medium or large, size does not split it further the way it does in Annex I; and a smaller set of entities (certain digital-infrastructure providers, public administration, and a few other special categories) are brought into scope, and sometimes classified essential, regardless of size, by name rather than by the size-cap rule. Whether your organisation, or the customer you build software for, is essential, important, or out of scope is a legal classification question for your compliance or legal team, not something a code review decides. If that conversation has not happened, have it before treating this guide as a compliance programme.

This guide assumes the classification question is already answered and the organisation is in scope. It is not a substitute for the risk-management framework the directive requires, the incident handling Art. 21(2)(b) and the incident reporting Art. 23 require, or the management-body accountability Art. 20 assigns. It is about the one Art. 21(2) measure that erodes in a diff.

The measure that actually shows up in a diff: Art. 21(2)(e)

Two of the ten Art. 21(2) measures already have their own control-in-code pages on this site: supply chain security (Art. 21(2)(d), an unpinned or unverified dependency) and basic cyber hygiene (Art. 21(2)(g), a known vulnerability left unpatched). Point (e), security in the acquisition, development and maintenance of network and information systems, is a different slice: it covers how software gets built and how vulnerabilities in it get found and disclosed, not which dependencies you pull in or which patches you apply afterward.

In practice that maps to two engineering habits. First, the security testing a development process runs before a change ships: a static-analysis gate, a required security review step, a dependency or fuzz check that has to pass. Second, a working vulnerability-disclosure path for the software once it is running: a security contact, a published intake for an external report, a route for someone who finds a hole to tell you about it. Either can erode in a single pull request: a gate gets disabled to unblock a release, or a new externally reachable surface ships with no disclosure route attached.

Worked example: the gate disabled to hit a deadline

A team is under deadline pressure to ship a new public-facing API endpoint, the company's first customer-facing surface reachable from the open internet. The pull request that adds the endpoint also includes an unrelated one-line change: the repository's required static-analysis security gate, which normally has to pass before merge, gets marked non-blocking with a comment referencing a follow-up ticket. The endpoint itself is well-built, with input validation and auth checks that pass a human read. The follow-up ticket referenced in the comment does not exist, and nothing in the PR restores the gate to blocking once the release ships. Separately, the company has no security contact, `security.txt`, or published vulnerability-reporting intake anywhere: internal tools were the only things ever exposed before, so nobody has needed one.

Reviewed only as a feature, this PR is fine: the endpoint works, the tests pass, the deadline is met. Reviewed against Art. 21(2)(e), it is two things at once. It weakens the security testing the development process is supposed to run before code ships, with no scoped exception or restore path, which is exactly the acquisition-and-development half of the measure. And it is the moment the company's missing vulnerability-disclosure path stops being a paper gap and starts being a real one: there is now a live, externally reachable surface and no route for someone who finds a hole in it to tell the company, which is the disclosure half. Neither problem is about whether the endpoint's code is correct. Both are about whether the process and the organisation still meet the measure that assumed the gate stayed on and a disclosure route existed somewhere.

A finding that cites Art. 21(2)(e) does not decide whether the gate should have been disabled for a real reason, draft the disclosure policy, or run the security test itself. It makes the change visible while the PR is still open, so the author or a reviewer can either restore the gate with a real tracked exception, and flag that the organisation needs a disclosure channel before this endpoint is the front door for a report with nowhere to land. If a disclosure path already existed elsewhere at the organisation level, this second half would not apply: the gap is real only because none does.

What to look for in review without becoming an NIS 2 lawyer

When a pull request touches CI configuration, ask whether it disables, weakens, or bypasses a required security-testing step, and if so, whether the same PR (or a linked one) documents why and when it comes back. A gate turned off with no restore path is the Art. 21(2)(e) tell. When a pull request adds a new externally reachable endpoint, service, or integration, ask whether a vulnerability-disclosure path for it already exists at the organisation level; if it does, the new surface inherits it and nothing further is needed, if it does not, that is a gap worth raising even though it is a one-time organisational fix rather than a per-PR one.

This is a narrower ask than the full measure. It does not cover whether your development lifecycle documentation is complete or whether your vulnerability-handling process meets every element the directive describes; those are process questions for whoever owns your NIS 2 programme. It covers the two places a pull request can quietly undo work that programme already did.

Where heygrc fits, and the honesty boundary

heygrc is built to read each pull request against the frameworks you selected, including NIS 2 when enabled, and to name the point a change appears to touch, for example Art. 21(2)(e) on a disabled security gate or a new endpoint with no visible disclosure path, Art. 21(2)(d) on an unpinned dependency, Art. 21(2)(g) on a held-back patch. The finding is a review comment with the clause attached, so the author and reviewer decide with full information. It does not certify NIS 2 compliance, write your vulnerability-disclosure policy, run your security testing, classify your entity, or file the incident reports Art. 23 requires. Those stay human and organisational duties.

If your team already runs a SAST or code-quality tool on the same pull request, keep it. That tool asks whether the code itself is correct and safe. Art. 21(2)(e) asks whether the process around the code, the gate that was supposed to run and the path someone uses to report a hole, still holds. The endpoint above can pass every quality check and still leave the measure thinner than it was. Run both layers; neither replaces the other.