DEV Community

Arif Kurnaz
Arif Kurnaz

Posted on

SOC 2, CRA, NIS2: they all ask your cluster the same five questions

In eleven days, on 11 September 2026, the reporting obligations of the EU Cyber Resilience Act start applying to anyone who puts a product with digital elements on the European market. Not the full regulation. Just the part where, if you find out an actively exploited vulnerability is in your product, you have 24 hours to tell ENISA about it.

I have watched a lot of engineering teams meet this class of deadline for the first time. It usually goes the same way. Somebody in sales gets a security questionnaire. Somebody in engineering gets forwarded the questionnaire. Three weeks later there is a shared folder called evidence-final-v3 with 200 screenshots in it, and nobody can tell you which screenshot answers which question.

I have spent the last several months building a tool whose entire job is that folder, so I read the instruments properly. This is what I found out. It is written for engineers, not for a compliance team, and I try to be specific about what the text says rather than what a vendor blog says it says.

Where SOC 2 came from, and why that still shapes it

SOC 2 exists because of a misuse.

In 1992 the AICPA published SAS 70, an auditing standard for service organisations. Its purpose was narrow: if you outsourced your payroll, your auditor needed some assurance that your payroll provider's internal controls did not corrupt your financial statements. It was an accounting instrument, for accountants, about financial reporting.

Then the industry outsourced everything else. By the mid-2000s companies were sending their customer data to service providers, and they wanted assurance about that, not about financial reporting. There was nothing designed for it, so they asked for the thing that existed. Vendors started waving SAS 70 reports around as proof they were secure. They were not proof of that. SAS 70 had no defined control set at all: the service organisation wrote its own control objectives, and the auditor tested against whatever had been written. Two SAS 70 reports could have nothing in common.

In 2010 the AICPA split the thing in half. Financial reporting controls stayed, renamed SOC 1 under SSAE 16 (SSAE 18 since 2017). The security question got its own report: SOC 2, with an actual defined set of criteria behind it.

That history is worth carrying, because SOC 2 still has SAS 70's shape in one important respect. It defines criteria, not controls. It tells you what has to be true. It does not tell you how. More on that in a moment, because it is the single most common misunderstanding.

Type I and Type II

Two report types, and the difference is most of the value.

Type I is a point in time. An auditor looks at your controls on one date and gives an opinion on whether they are suitably designed. It answers: do you have the right things in place?

Type II covers a period, typically 3 to 12 months, with 6 being the usual choice for a first report. The auditor gives an opinion on whether the controls were suitably designed and operated effectively throughout that period.

A Type I says you built the fence. A Type II says the fence was standing every day for six months.

Almost every buyer who asks for SOC 2 means Type II, or will mean it at renewal. And it matters enormously to how you should think about evidence, because "operated effectively throughout the period" is not a thing you can produce at the end. The auditor samples across the whole window. If your quarterly access review was supposed to run four times and it ran once, in the week before fieldwork, that is an exception in your report and everybody reading it can see it.

That property, that the evidence must have existed continuously rather than being assembled afterwards, is the one I would burn into a wall. It is what makes screenshot folders a bad answer.

The five criteria, and the four you probably do not need

SOC 2 is built on the Trust Services Criteria (AICPA TSP section 100, 2017, revised 2022). Five categories:

  • Security — the Common Criteria, CC1 to CC9. Mandatory. Every SOC 2 includes it.
  • Availability — is the system up when you said it would be
  • Confidentiality — is information designated confidential protected
  • Processing Integrity — is processing complete, valid, accurate, timely, authorised
  • Privacy — personal information handled per your notice

Only Security is required. You choose the rest, and you should choose as few as you can defend, because each one is more scope, more testing, more cost. Most infrastructure and SaaS companies do Security, or Security plus Availability. Add Confidentiality if your contracts talk about it. Processing Integrity is genuinely rare and mostly belongs to payments and payroll.

Inside the Common Criteria, the ones an engineer actually touches:

Criterion Roughly
CC1–CC3 Governance, communication, risk assessment. Mostly organisational.
CC4 Monitoring: do you check your own controls are present and functioning?
CC5 Control activities.
CC6 Logical and physical access. Who can reach what, and how you keep the outside out.
CC7 System operations. Detecting vulnerabilities and configuration drift, spotting anomalies, handling incidents.
CC8 Change management. Nothing untested or unauthorised reaches production.
CC9 Risk mitigation, including vendor and third-party risk.

If you run containers on Kubernetes, most of your technical evidence lands in CC6, CC7 and CC8. CC6.8 is the one people miss: "the entity implements controls to prevent or detect and act upon the introduction of unauthorized or malicious software." That is your image supply chain, stated in 2017 language.

SOC 2 does not tell you what to do

This is the part that catches teams out.

There is no SOC 2 control list. There is no "you must scan images" clause. The criteria are outcome statements, and you define the controls that meet them, and then the auditor tests the controls you defined. You write a control saying "all container images are scanned before deployment and images with critical vulnerabilities are blocked", and now you are on the hook to prove that happened every day of the period.

This cuts both ways. The freedom is real: you are not forced into somebody else's architecture. The trap is also real, and it is that a weak control, written vaguely, passes the audit while protecting nothing. "We use industry standard scanning tools" is a sentence that can be true while your cluster runs whatever anybody pushes.

The auditor is not there to tell you the control is weak. They are there to test whether it operated as described.

The other instruments, and their clocks

SOC 2 is voluntary and market-driven; you do it because a customer asked. Most of what arrived after it is not voluntary. Here is the landscape as it stands at the end of August 2026.

EU Cyber Resilience Act — Regulation (EU) 2024/2847. Applies to products with digital elements sold in the EU, which for most of us means the software itself. Three dates: conformity assessment bodies from 11 June 2026 (passed), vulnerability and incident reporting from 11 September 2026 (eleven days away), and the substantive obligations, including technical documentation and the SBOM requirement, from 11 December 2027. Annex I Part II point 1 is the SBOM clause: components documented in a commonly used machine-readable format, covering at least the top-level dependencies. You do not have to publish it. You do have to have it and hand it over when a market surveillance authority asks.

NIS2 — Directive (EU) 2022/2555. Applies to entities in essential and important sectors, and reaches software vendors indirectly, forcefully, through Article 21(2), which names supply chain security and requires covered entities to consider the security practices of their direct suppliers. That is why NIS2-derived questionnaires arrive at companies that are not themselves in scope. Being a supplier to somebody in scope is enough.

DORA — Regulation (EU) 2022/2554, in force since 17 January 2025 for EU financial entities and the ICT providers serving them. Chapter V Article 28 is the third-party risk chapter, and it has teeth in a way NIS2 does not, including audit rights written into contracts.

ISO/IEC 27001:2022 — certification rather than a report. Buyers outside the US often prefer it. Annex A control 8.8 (technical vulnerabilities), 8.25 through 8.31 (secure development, separation of environments) are the ones your pipeline touches.

NIST — SP 800-190 for container security specifically, SP 800-218 (SSDF) for secure development, SP 800-53 Rev. 5 for the full federal control catalogue. Not law unless you sell to the US government, but the language is precise and much of the rest of the world quotes it.

GDPR Article 32 — security of processing. Short, general, and still the clause that turns a container escape into a regulatory event if personal data was on the other side of it.

They are all asking the same five questions

Here is the thing I did not expect when I started reading these side by side. The instruments are written by different bodies, in different decades, for different legal systems, and underneath they converge hard.

CRA Annex I Part I (3)(g), on availability and resilience of essential functions, and SOC 2 A1.2 both turn on outages and what the system does when a component fails. CRA (3)(c) on access control and CC6.1 both turn on hardening and federated access. CRA (3)(k) on recording and monitoring activity and CC7.2 both turn on the audit trail. DORA Article 9's protection and prevention requirements land in the same place as CC6.8.

For a workload running in a cluster, strip away the citations and every one of them is asking:

  1. What is running? An inventory. Not "what did we deploy", what is actually admitted right now.
  2. Where did it come from? Provenance. A signature, an identifiable registry, a build you can point at.
  3. What is wrong with it? Known vulnerabilities, against a database that was current at the time of the check.
  4. Who allowed the exceptions? Because there are always exceptions. An unrecorded exception is indistinguishable from a control failure.
  5. Can you prove all of the above for a period you did not choose in advance?

Question 5 is the one tools get wrong.

What good evidence looks like

Most compliance tooling is built to produce a dashboard. A dashboard tells you the state now. An auditor is not asking about now, they are asking about February.

Working backwards from what a Type II sampling exercise actually needs, evidence has to carry five properties:

A period, stated on the document. Not "generated today", but "covers 1 February to 31 July, and here is what happened in that window."

Provenance of the evidence itself. Who generated it, from which system, at what version. A compliance mapping is an interpretation, and interpretations change as you read a framework more carefully. Evidence that does not record which reading it used cannot be re-examined later.

Integrity. A PDF is a suggestion. Anybody can edit a PDF. If the document that goes to the auditor is not cryptographically bound to the bytes that were generated, then the strongest statement you can make about it is "someone in our company typed this."

Citation, not paraphrase. Every claim should name the clause it answers, quoted close to the instrument's own words. Auditors read the criterion, not your marketing vocabulary. If your report says "we are compliant with CC7.1" without restating what CC7.1 asks, you have made the reader do a lookup, and made yourself impossible to check.

Honest gaps. This is the one I care most about. A container security tool can evidence maybe a third of NIS2 Article 21. The rest is staff training, disclosure policies, reporting to a national CSIRT, business continuity. A report that quietly maps a feature list onto the other two thirds is worse than no report at all, because it tells an organisation a duty is discharged when nobody has done it. Anything that comes back all green is lying to you, and the lie is expensive precisely when it matters.

Why the admission controller is the right place to stand

For the Kubernetes-specific part of this: scanning in CI is necessary and insufficient.

CI scanning proves you scanned an image. It does not prove that only scanned images ran. Those are different claims and the second is the one CC6.8 asks for. Between the pipeline and the cluster there is a gap wide enough to drive a kubectl apply through: a manually applied manifest, a Helm chart from a vendor, a sidecar injected by a mesh, a latest tag that resolved to something different this morning than it did last week.

The admission webhook is the last point where the answer to "may this run" is still no. It is also the only point where a record of the decision is a record of what actually entered the cluster, rather than a record of intent. Every admission review is a dated, attributable event: this digest, this policy, admitted or refused, at this moment. That is the raw material a Type II sample is made of, and it accumulates whether or not anybody remembers to collect it.

That property, evidence that exists because the control ran and not because somebody prepared for an audit, is the whole point.

How we built this into Attestkeep

Attestkeep is a Kubernetes admission controller that scans images, verifies signatures and attestations, and enforces policy at admission. That part is not novel and I would not write a post about it. The part I want to describe is what happens after six months of it running.

You pick a period and a framework. It generates a report against eight of them: SOC 2, EU CRA + NIS2, DORA, NIST SP 800-190, SSDF, SP 800-53 Rev. 5, ISO 27001, and GDPR Article 32. Every requirement in the report carries its citation, the obligation restated close to the instrument's own words, a status, and a note written in the period's own numbers.

There are four statuses, and the fourth is the reason I am writing this section:

  • met — the control operates and the records show it operating
  • partial — it operates but something narrows what it proves: a permissive failure policy, audit-only mode, an exemption
  • gap — squarely within what this thing can enforce, and the records say it is not being enforced
  • outside_scope — a duty of the organisation, not a property of a cluster. Named rather than omitted, so the reader can see where the document's coverage ends.

Here is an unedited fragment from a real 30-day report generated against a demo cluster:

{
  "id": "CC4.1",
  "citation": "CC4.1",
  "title": "Evaluations to ascertain that controls are present and functioning",
  "asks": "The entity selects, develops, and performs ongoing and/or separate evaluations to ascertain whether the components of internal control are present and functioning.",
  "status": "met",
  "note": "the control's operation is measured continuously rather than sampled: 293 reviews, 31 admitted, 262 refused, and 3 windows in which it was not operating",
  "evidence": ["admission", "availability"]
}
Enter fullscreen mode Exit fullscreen mode

and, from the same report, one that did not pass:

{
  "id": "CC6.6",
  "citation": "CC6.6",
  "status": "gap",
  "note": "no registry allow-list is in force, so an image may be pulled from any registry the node can reach",
  "evidence": ["control_statement.allowed_registries"]
}
Enter fullscreen mode Exit fullscreen mode

The summary for that period was 3 met, 6 partial, 2 gap, 2 outside scope. That is a demo cluster with a loose policy, and the report says so. I would rather ship a tool that tells you that in August than one that tells you everything is fine and lets an auditor find it in February.

The evidence field is a pointer into the sections of the same document that carry the underlying numbers, so a reader can check the claim rather than accept the note.

Integrity. The report is signed with Ed25519 into a DSSE envelope carrying an in-toto Statement v1. The signature covers report.json and nothing else. The subject is the report's SHA-256, so the signature binds to the exact bytes, and any copy of those bytes can be checked against it.

What the auditor receives is a zip:

README.txt          what is signed, and three ways to check it
report.json         the evidence. these exact bytes are what is signed
attestation.json    DSSE envelope, in-toto Statement v1
certificate.jwt     the public half of the signing key, signed by us
<id>.pdf            a readable rendering. convenience only, carries no signature
<id>.attestkeep.json  all of the above in one file, for single-file verifiers
Enter fullscreen mode Exit fullscreen mode

The README is always in English, whatever language the console is set to, because an auditor's file gets read in places you cannot predict. It states plainly that if the PDF and report.json ever disagree, report.json is the record and the PDF is wrong. Verification works three ways: a browser page that runs entirely client-side and uploads nothing, a Python script with no dependencies, or cosign if you already have it. The archive is byte-for-byte reproducible: the zip entry timestamps come from the report's own generation time rather than the clock, so two people downloading the same package get the same file.

And the scope statement, which is printed at the top of every SOC 2 report we produce:

It is evidence for an audit, not an audit: only a service auditor issues an opinion, and only the entity defines its own system boundary.

I put that there because I have seen what the alternative does to people. A tool cannot make you compliant. It can make the day the auditor asks a boring one.

What this does not do

Being straight about the limits, since I just spent 400 words demanding honest gaps from everybody else.

The compliance mappings have not been through legal or audit review. They are my careful reading of published texts, with citations included specifically so a professional can check my work rather than trust it. The NIST SP 800-190 citations were corrected once already, when I went back and compared them against the published guidance instead of my notes.

Nothing here binds a report to a trusted clock. generated_at is an assertion by the signer, not proof. If you need trusted timestamping, you need it from somewhere else, and the predicate says so in a comment rather than hiding it.

And the honest scope line applies to me too: one cluster's admission control answers part of SOC 2 and a smaller part of NIS2. It does not answer your access reviews, your onboarding, your incident response drills, or your vendor register.

If you take one thing

Whatever you use, and it does not have to be mine, make the evidence a byproduct of the control operating rather than a project you run before an audit. The frameworks converge on this even where their words differ. SOC 2 Type II wants the whole period. CRA wants technical documentation that was maintained, not assembled. DORA wants an audit right that is meaningful when exercised without notice.

Evidence you can only produce by preparing for the question is not evidence that the control was working. It is evidence that you can prepare.


I build Attestkeep, a Kubernetes admission controller with compliance evidence built in. It is early. If you have been through a Type II with containers in scope and something above is wrong, I would genuinely like to hear it.

Top comments (3)

Collapse
 
crdtcto profile image
Kane Lim

Hello Glad to see you, I am Kane Lim from Hong Kong. I have over 10 years of development experience. I am writing this because your post was interesting.

The strongest architectural point here is treating compliance evidence as an immutable telemetry stream rather than an audit artifact. For Kubernetes, I would push this further with a policy decision log backed by admission events, image digests, SBOM references, signature verification, workload identity, and policy versions.

A particularly useful model is evidence as a verifiable event graph. Every admission decision references the exact OCI digest, attestation, registry, identity, policy revision, timestamp, and enforcement result. You can then reconstruct the cluster's security state for any historical interval without relying on screenshots or manually generated reports.

I would also correlate admission events with runtime signals from eBPF, Kubernetes audit logs, and vulnerability intelligence. That lets you distinguish “image was compliant when admitted” from “workload remained compliant during execution.”

The scope boundaries you describe are equally important. Compliance automation should explicitly represent unknown and outside scope states rather than manufacture green dashboards.

Excellent engineering direction. I would be glad to exchange ideas around verifiable evidence pipelines and policy enforcement.

Collapse
 
arifkurnaz profile image
Arif Kurnaz

Thanks Kane. The admission-versus-execution point is the one I would have
raised against myself, so let me answer it properly, and be specific about
what is recorded today versus what you are describing.

Recorded per decision right now: OCI digest, registry, timestamp,
enforcement result and reason, actor, signature verification including the
signer identity, and attestation presence. A denial carries the pods it
applied to. What is not recorded is policy revision, only policy name, and
workload identity. Both are fair hits. The policy revision one bothers me
more than it should, because a control statement without a revision lets a
report say "the policy required X" over a period in which the policy
changed.

On evidence as a verifiable event graph: I agree with the model, with one
constraint I would add. The stream is the right internal representation,
but no auditor reads a stream. Whatever you build, the thing that leaves
the building has to be a bounded, signed document with a period stated on
it, or you have only moved the assembly problem from your team to theirs.
We sign per report rather than per event for that reason, and it is a real
trade-off: the period document is verifiable, the underlying rows are not
individually attested.

Admission-time versus execution-time is the honest gap. We close half of
it with periodic rescans, so a CVE published after admission surfaces
against images already running and the next admission decides on it. We do
not close the behavioural half at all and do not claim to. eBPF correlation
is the right answer there, and it is not a small feature.

Collapse
 
crdtcto profile image
Kane Lim

I would like to get to know you better and discuss about your post. Would you please contact me? t_g_@kanelim1997