Skip to content
Stribog

Compliance

All writing

ISO 27002 vs 27001: One Is Guidance, One Is Certifiable

ISO 27001 is certifiable; ISO 27002 is the implementation guidance behind its Annex A. What the split changes when you run the infrastructure yourself.

Stribog13 min read

Search the comparison and the first page is GRC-vendor explainers. Most land on the right answer — you certify to 27001, not 27002 — and almost none work from either document's own words. The question was never which is certifiable, but what each contains, which sentences are normative, and what an accredited body is audited against.

Two documents, one control numbering, one of them normative

ISO/IEC 27002:2022 describes itself. Its Scope says the document "provides a reference set of generic information security controls including implementation guidance", then names three users: organisations working "within the context of an information security management system (ISMS) based on ISO/IEC 27001", organisations "implementing information security controls based on internationally recognized best practices", and organisations "developing organization-specific information security management guidelines". Introduction 0.1 repeats the framing: a reference "for determining and implementing controls for information security risk treatment" in such an ISMS, and "a guidance document for organizations determining and implementing commonly accepted information security controls".

Its controls sit in four clauses: 5 Organizational, 5.1 to 5.37; 6 People, 6.1 to 6.8; 7 Physical, 7.1 to 7.14; 8 Technological, 8.1 to 8.34. The familiar 37/8/14/34 split is not a figure any of these documents states — it follows from those ranges, and sums to the 93 controls the accreditation record gives. Both annexes are informative: Annex A on using attributes, Annex B on correspondence with 2013.

ISO/IEC 27001:2022 is different. Its Annex A appears in that standard's table of contents as "Annex A (normative) Information security controls reference", and IAF MD 26:2023, the International Accreditation Forum's mandatory document, says what it holds: "Annex A references the information security controls in ISO/IEC 27002:2022, which includes the information of control title and control." A title and a control statement — not the purpose, the implementation guidance or the attributes, which live in 27002 under identical numbering.

The direction of dependency is the part vendor comparisons invert. 27001:2022's foreword records it as a third edition whose main change is that "the text has been aligned with the harmonized structure for management system standards and ISO/IEC 27002:2022". 27001 was aligned to 27002's revision, not the other way round — so the assumed hierarchy, normative standard on top and optional guidance below, is not the relationship.

Dashed edges are inputs nobody certifies you against. Solid edges are the only path a certificate traverses.

What a certification body is actually accredited to audit

"Is ISO 27002 certifiable?" is usually answered by assertion; it is answerable from text. The Scope already quoted gives three named uses, none of them conformity assessment. The other end supplies the rest: ISO/IEC 27006-1:2024, which specifies requirements for bodies auditing and certifying an ISMS, states in its Introduction: "ISO/IEC 17021-1 sets out requirements and guidance for bodies providing audit and certification of management systems. If such bodies intend to be compliant with ISO/IEC 17021-1 with the objective of auditing and certifying information security management systems (ISMS) in accordance with ISO/IEC 27001, some additional requirements and guidance to ISO/IEC 17021-1 are critical. These are provided by this document." The certificate exists inside that structure, which names 27001.

Clause 2 of 27006-1:2024 is short: its complete set of normative references is ISO/IEC 17021-1:2015 and ISO/IEC 27001:2022. ISO/IEC 27002 is not among them. Clause 7.1.3.1.3, on audit-team competence, reads the same way: "Each auditor in an ISMS audit team shall have knowledge of all requirements contained in ISO/IEC 27001. The audit team members shall, collectively, have knowledge of all controls contained in ISO/IEC 27001:2022, Annex A and their implementation."

The distinction is commercial as much as technical. A questionnaire asking for "ISO 27002 certification" asks for something the accreditation route does not produce, and the answer is a 27001 certificate with a scope statement, not an apology. Sector extensions behave the same way: holding both cloud roles at once, as in ISO 27017 when you are your own provider, changes the control set you work through, not the standard the certificate names.

The Statement of Applicability is the artefact, and 6.1.3 says what is in it

Clause 6.1.3 is where the two documents meet an auditor, and IAF MD 26:2023 bounds that meeting: "The requirements in ISO/IEC 27001 that use the reference control set in Annex A are the comparison process between the information security controls determined by the organization and those in Annex A (6.1.3 c)) and the production of a Statement of Applicability (6.1.3 d))." Two requirements; everything else in 27001 is the management system.

The sequence inside the clause is what explainers skip. First, 6.1.3 b): "determine all controls that are necessary to implement the information security risk treatment option(s) chosen". Then the note nobody quotes, because it undercuts the implement-Annex-A framing: "NOTE 1 Organizations can design controls as required, or identify them from any source." Only then does 6.1.3 c) ask you to "compare the controls determined in 6.1.3 b) above with those in Annex A and verify that no necessary controls have been omitted", with NOTE 2 calling Annex A "a list of possible information security controls" that users are "directed to" so "that no necessary information security controls are overlooked". NOTE 3 closes it: the list "is not exhaustive".

Read in order, the standard asks you to design your control set and check it against a reference list — not to start from the list. And 6.1.3 d) is exact about the output: a Statement of Applicability contains four things and only four — "the necessary controls", "justification for their inclusion", "whether the necessary controls are implemented or not", and "the justification for excluding any of the Annex A controls". That is a data schema. The file itself is built in ISO 27001 without inherited controls; the layout is what matters here.

yaml
# soa.yaml — two records, shown to make one point about field boundaries.
# Not a Statement of Applicability: a real one decides every Annex A id.
# The four contents clause 6.1.3 d) asks for are `control`, `justification`,
# `implemented` and `exclusion_justification`. Every other key is ours.
---
- control: "8.22"
  justification: >-
    Multi-tenant workloads share cluster network fabric. Risk register R-021.
  implemented: true
  exclusion_justification: null

  # --- CONVENIENCE FIELD, not one of the four. The reconciler ignores it and
  # --- requires exactly one of the two justifications above, so a record with
  # --- both, or with neither, fails whatever this says.
  decision: included

  # --- NON-NORMATIVE. Never sampled as the control. Kept in its own block so
  # --- nothing mistakes guidance for a requirement.
  guidance_consulted:
    - document: "ISO/IEC 27002:2022"
      clause: "8.22"
      note: Implementation substance only. Not a conformity claim.
  evidence_prefix: evidence/8.22/

- control: "7.4"
  justification: null
  implemented: false
  exclusion_justification: >-
    The organisation operates no premises hosting in-scope systems. The
    colocation operator is assessed as a supplier and its certificate held.
  decision: excluded
  guidance_consulted: []
  # Nothing is implemented under this id, so there is no evidence prefix.
  evidence_prefix: null
Field layout only — two records, not a Statement of Applicability. This is the reconciler's input file; the point is the boundary between the four contents clause 6.1.3 d) requires and everything kept below them, which is ours.

Reading 27002 when nobody else operates the control

A tenant on managed infrastructure answers a network control partly by reference to somebody else's control catalogue. Operate the substrate yourself and that reference disappears — which is when a team stops skimming Annex A's one-line control statements and starts reading 27002's clause of the same number.

Take the network pair. The titles set the boundary: Annex A 8.20 is networks security, 8.22 is segregation of networks. What follows is an engineering reading of those titles, not a quotation of either control's implementation guidance. 8.20 is the broader, reaching into CNI selection, node-level firewalling, control-plane exposure and the enforcement path itself; no single manifest discharges it. 8.22 is narrower, and is what a namespace default-deny plus explicit allow rules can point at. Labelling one NetworkPolicy "8.20: done" is the mistake.

yaml
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: payments
  labels:
    compliance.stribog/control: "8.22"
  annotations:
    compliance.stribog/evidence-prefix: evidence/8.22/
spec:
  podSelector: {}
  policyTypes:
    - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ledger-ingress-from-api
  namespace: payments
  labels:
    compliance.stribog/control: "8.22"
  annotations:
    compliance.stribog/evidence-prefix: evidence/8.22/
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: ledger
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: payments-api
      ports:
        - protocol: TCP
          port: 8443
The default-deny object, labelled with the control it evidences; the paired allow rules carry the same label and a podSelector. The Kubernetes documentation is explicit that this is a request to a plugin: "Creating a NetworkPolicy resource without a controller that implements it will have no effect."

Two sentences from the Kubernetes documentation are load-bearing. "Network policies are implemented by the network plugin", and a resource without a controller implementing it "will have no effect" — so the manifest is intent, not a control. And "by default, a pod is non-isolated for ingress; all inbound connections are allowed", which is why the default-deny object exists. Behaviour past those sentences varies by plugin, and the evidence closing the gap is traffic, not YAML — see default deny, actually.

Reaching for 27002's prose here is not a workaround. ENISA's Technical Implementation Guidance on cybersecurity risk-management measures, version 1.0 of June 2025, maps each NIS2 implementing-regulation requirement to ISO/IEC 27001:2022, ISO/IEC 27002:2022, NIST Cybersecurity Framework 2.0, ETSI EN 319 401 and CEN/TS 18026:2024. When it needs a control's substance rather than its title it quotes 27002 directly, defining privileged access rights in a footnote as "access rights provided to an identity, a role or a process that allows the performance of activities that typical users or processes cannot perform", cited to "ISO/IEC 27002, 8.2". An EU agency reaches for the guidance document when it needs a control in prose. That is the job.

Failure modes: guidance promoted to requirement, and evidence with no control

Three failures follow from misreading the split, each settled by a specific sentence rather than by argument.

  • Guidance promoted to requirement. A team copies 27002's implementation sub-points into the SoA as separate rows. The file now holds entries corresponding to no reference control, so the 6.1.3 c) comparison cannot be verified against it. Settled by 6.1.3 d), whose four contents key on the necessary controls and the Annex A exclusions.
  • "We follow 27002" offered as a conformity claim. It appears in questionnaires, trust pages and contracts. 27002's Scope names no conformity assessment; 27006-1:2024's clause 2 names only 17021-1 and 27001. No accredited body issues the thing being claimed.
  • Evidence collected against no control id. The one that survives longest, because nothing about it looks wrong. Scan output, policy reports and access reviews accumulate in directories named after the tool. Every artefact is real; none is addressed to a control, so at audit the mapping is rebuilt by hand — the work the SoA was meant to have done.

Reconciling the Statement of Applicability against what is actually running

That third failure is the one good automation walks into: evidence accrues continuously, and if the naming convention is the tool's rather than the control's, the pile needs translating. The fix is a control id on the object producing the evidence — which is why the manifests above carry a label, and why SOC 2 on self-hosted Kubernetes needs the criterion on the artefact. An SoA held as data can then be tested against three sets: the controls it decided, the objects carrying a control id, and the dated evidence on disk.

python
#!/usr/bin/env python3
"""Reconcile an ISO/IEC 27001 Statement of Applicability against the objects
and evidence actually present. Non-zero exit on any finding. Needs PyYAML.
Usage: reconcile_soa.py <inventory.json> <report.json> <commit>
"""

from __future__ import annotations

import json
import sys
from datetime import datetime, timezone
from pathlib import Path

import yaml

LABEL = "compliance.stribog/control"
SOA = Path("compliance/soa.yaml")
EVIDENCE = Path("evidence")
# Annex A ids are data, never hard-coded: the set moved once and will again.
REFERENCE = Path("compliance/annex-a-2022.ids")


def evidenced(control: str) -> bool:
    d = EVIDENCE / control
    return d.is_dir() and any(c.is_file() for c in d.rglob("*"))


def reconcile(soa: dict, reference: set, objects: set) -> list[dict]:
    out: list[dict] = []

    def flag(condition: str, control: str) -> None:
        out.append({"condition": condition, "control": control})

    # 1. Declared implemented, but no labelled object or no dated evidence.
    for control, record in sorted(soa.items()):
        if record.get("implemented") and not (
            control in objects and evidenced(control)
        ):
            flag("implemented-without-evidence", control)

    # 2. An object claims a control the SoA never decided.
    for control in sorted(objects - set(soa)):
        flag("evidence-without-a-decision", control)

    # 3. Exactly one justification per reference control. Neither leaves
    #    6.1.3 d) unmet for that id; both is a contradiction. Both fail.
    for control in sorted(reference):
        record = soa.get(control)
        if record is None or bool(record.get("justification")) == bool(
            record.get("exclusion_justification")
        ):
            flag("control-without-a-decision", control)

    return out


def main(inventory: str, report: str, commit: str) -> int:
    records = yaml.safe_load(SOA.read_text()) or []
    soa = {str(r["control"]): r for r in records}
    if len(soa) != len(records):
        raise SystemExit(f"{SOA}: duplicate control id")

    reference = {
        s
        for line in REFERENCE.read_text().splitlines()
        if (s := line.split("#", 1)[0].strip())
    }
    objects = {
        str(label)
        for obj in json.loads(Path(inventory).read_text())
        if (label := ((obj.get("metadata") or {}).get("labels") or {}).get(LABEL))
    }
    findings = reconcile(soa, reference, objects)

    # Written on every run: a clean reconciliation is evidence in its own
    # right, and a report that appears only on failure proves nothing ran.
    out = Path(report)
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(json.dumps({
        "generated_at": datetime.now(timezone.utc).isoformat(timespec="seconds"),
        "commit": commit,
        "controls_declared": len(soa),
        "findings": findings,
        "result": "fail" if findings else "pass",
    }, indent=2) + "\n")

    print(f"{len(findings)} finding(s) -> {out}", file=sys.stderr)
    return 1 if findings else 0


if __name__ == "__main__":
    raise SystemExit(main(*sys.argv[1:4]))
reconcile_soa.py — fails closed on all three disagreements. Standard library plus PyYAML, which is a third-party dependency and must be installed; everything else is stdlib.
bash
#!/usr/bin/env bash
set -euo pipefail

OUT="evidence/_reconciliation/$(date -u +%Y-%m-%d)"
mkdir -p "${OUT}"

# Core API types only: every cluster serves these, so this get cannot abort
# the run under set -e.
kubectl get networkpolicies,roles,rolebindings --all-namespaces \
  -l 'compliance.stribog/control' -o json | jq '[.items[]]' > "${OUT}/core.json"

# CRD-served kinds only where the CRD is installed: clusterpolicies.kyverno.io
# is Kyverno's, not a stock API, and a cluster without it must still report.
echo '[]' > "${OUT}/crd.json"
if kubectl get crd clusterpolicies.kyverno.io >/dev/null 2>&1; then
  kubectl get clusterpolicies.kyverno.io -l 'compliance.stribog/control' -o json \
    | jq '[.items[]]' > "${OUT}/crd.json"
fi

# labelled-artefacts.json is the non-cluster limb and is not optional: 5.x, 6.x
# and 7.x controls have no Kubernetes object, so their labelled repository
# artefacts are rendered there. Without it, condition 1 fails every one.
jq -s 'add' "${OUT}/core.json" "${OUT}/crd.json" \
  policies/_generated/labelled-artefacts.json > "${OUT}/inventory.json"

# Snapshot the SoA before reconciling: the reconciler exits non-zero on any
# finding, and under set -e that is the path where the snapshot matters most.
cp compliance/soa.yaml "${OUT}/soa.yaml"

python3 tools/reconcile_soa.py \
  "${OUT}/inventory.json" "${OUT}/reconciliation.json" "$(git rev-parse HEAD)"
The CI gate. SoA, inventory and report are produced by one pipeline run against one commit, so the reconciliation is dated and attributable rather than reassembled before a Stage 2 audit.
The negative result is also evidence: the report is written on every run, clean or not.

Exit ramps: controls from any source, and what survives the certificate

NOTE 1 under 6.1.3 b) is the most useful sentence in 27001 for a team with no appetite for lock-in: "Organizations can design controls as required, or identify them from any source." NOTE 3 backs it — the list "is not exhaustive". Together they authorise what a platform team wants anyway: build the control from mechanisms your stack already has, and treat Annex A as the checklist you compare against at the end.

So the primary record is the mechanism; the framework identifier is an attribute of it. An admission policy exists; "8.22" is one label it wears. Add a second and the same object answers a second regime — NIST SP 800-53 on Kubernetes you own is that object seen through a different catalogue, and the overlapping obligations in EU AI Act, NIS2 and DORA are more of them.

One caution, stated by ENISA about its own mapping: it "should not be interpreted as a measure of equivalency among different standards or frameworks", and it "simply refers to relevant requirements" without assessing whether they "fully cover the requirements of the regulation". A label is a pointer, not proof of coverage. Keep labels cheap and the mechanism authoritative, and dropping a framework costs a column, not a rebuild.

The long game: one edition in force, and a control set that will move again

Control sets move, and the last move is precedent, not forecast. 27002's foreword describes the 2022 edition as a technical revision of the 2013 one, with a modified title, a changed structure "presenting the controls using a simple taxonomy and associated attributes", and controls "merged", "deleted" and "newly introduced". IAF MD 26:2023 puts numbers on it: 114 controls in 14 clauses became 93 in 4, with 11 new, 24 merged and 58 updated, and certification bodies had to transition certified clients by 31 October 2025.

The precision required is finer than renumbering. 27002:2022 was reissued as a corrected version, and one correction moves an attribute value between named columns: "#information_security_assurance" was moved for control 5.22 "from the column headed 'Security domains' to the column headed 'Operational capabilities'". A pipeline keyed on that string in that column needed re-checking over a corrigendum. Anything assuming control metadata is stable gets rebuilt by hand eventually.

Which is why the SoA belongs in data rather than prose: structured, a remapping is a transformation over records; unstructured, it is a retyping exercise. 27002 says as much of its own contents — it "can be regarded as a starting point for developing organization-specific guidelines", and "not all of the controls and guidance in this document can be applicable to all organizations". One document supplies the substance, the other the requirements and the reference list. A certificate is a third party's statement about a moment in time; the inventory, the labelled objects and the dated reports are yours, readable without a portal login, and they answer the question that survives a change of auditor, framework or certification body: what was enforced, on which date, against which commit.

§FAQ/Common questions

Frequently asked

Is ISO 27002 certifiable?

Not through the accredited ISMS certification route. The document's own Scope names three uses — working within an ISMS based on ISO/IEC 27001, implementing controls based on internationally recognised best practices, and developing organisation-specific guidelines — and conformity assessment is not among them. ISO/IEC 27006-1:2024, which specifies requirements for bodies auditing and certifying an ISMS, lists exactly two normative references in its clause 2: ISO/IEC 17021-1:2015 and ISO/IEC 27001:2022.

What is the difference between ISO 27001 Annex A and ISO 27002?

They share the same control numbering and differ in what they carry. IAF MD 26:2023 describes 27001's normative Annex A as referencing the controls in ISO/IEC 27002:2022 and including "the information of control title and control" — a title and a control statement. ISO/IEC 27002:2022 carries the purpose, implementation guidance and attributes for each of those same numbered controls across its clauses 5 to 8.

Does ISO 27001 require you to implement the Annex A controls?

It requires you to determine the controls necessary for your chosen risk treatment, then compare that set against Annex A and verify nothing necessary was omitted. Clause 6.1.3 NOTE 1 states that organisations "can design controls as required, or identify them from any source", and NOTE 3 states the Annex A list "is not exhaustive". Annex A is the comparison reference, not a mandatory implementation list.

What exactly must a Statement of Applicability contain?

Clause 6.1.3 d) names four contents: the necessary controls, justification for their inclusion, whether the necessary controls are implemented or not, and the justification for excluding any of the Annex A controls. Anything else you keep alongside it — a mechanism list, an evidence path, a pointer to the ISO/IEC 27002 clause you consulted — is yours, and is best held in a visibly separate field so guidance is never sampled as though it were the control.

If you run your own infrastructure, which document do you actually work from?

Both, for different things. You read ISO/IEC 27002 for the substance of a control when there is no provider catalogue to inherit from — the same way ENISA's June 2025 technical implementation guidance quotes ISO/IEC 27002 clause 8.2 when it needs privileged access rights defined in prose. You build and maintain the Statement of Applicability against ISO/IEC 27001 Annex A, because that is what an accredited certification body audits.

iso 27002 vs 27001iso 27001 vs iso 27002is iso 27002 certifiableiso 27002 implementation guidancestatement of applicability iso 27001 6.1.3iso 27002 2022 four themes

Executive Briefing

Thirty minutes to clarify your infrastructure risk

Walk us through your vendor footprint and regulatory constraints. We will tell you honestly where sovereignty creates leverage — and where it does not. No pitch deck. No obligation.