Skip to content

data-quality: ISO 27001 and ISO 27002 mappings are identical for all 1020 M365 checks (should diverge) #360

Description

@Daren9m

Summary

data/registry.json currently maps every M365 check identically to BOTH iso-27001 and iso-27002 — 1020/1020 mappings are identical, 0 divergent. This is silently wrong: ISO 27001 (the ISMS standard) and ISO 27002 (the implementation guidance for Annex A controls) are different frameworks with overlapping but not identical control sets.

Surfaced by Galvnyz/M365-Assess#871 — M365-Assess has a Pester regression test (tests/Behavior/Iso-27001-27002-Mapping-Audit.Tests.ps1) currently -Skip:$true waiting for this upstream fix. Once corrected here, that test un-skips automatically on their weekly registry sync.

Why the two are different

  • ISO/IEC 27001:2022 — the ISMS standard. Contains clauses 4–10 (process: risk assessment, internal audit, statement of applicability, management review) plus a normative reference to Annex A's 93 controls.
  • ISO/IEC 27002:2022 — the implementation guidance for those Annex A controls. 93 controls, structured the same way as 27001 Annex A, but the document is the "how to implement" guide, not the certification standard.

A check verifying e.g. "MFA on admin accounts":

  • Should map to ISO 27001 Annex A 8.5 (the control reference)
  • Should map to ISO 27002 8.5 (the implementation guidance for that control)
  • Should NOT map both to identical strings — the framework purposes are different even when the control numbers match.

For a check verifying e.g. "documented information security policy" (an ISMS-process control):

  • Should map to ISO 27001 §5.2 (clause 5.2 — Policy)
  • Should NOT map to ISO 27002 at all (27002 doesn't cover ISMS process clauses; only Annex A controls)

So the mappings should diverge in two ways:

  1. Identical-numbered Annex A mappings still need different controlId semantics (A.X.Y vs X.Y — 27001 prefixes with A. because it's referencing Annex A explicitly)
  2. ISMS-process controls have ISO 27001 mappings without ISO 27002 mappings

Reproducer

python -c "
import json
reg = json.load(open('data/registry.json', encoding='utf-8'))
identical = different = absent_27002 = absent_27001 = 0
for c in reg['checks']:
    fw = c.get('frameworks', {})
    has_27001 = 'iso-27001' in fw
    has_27002 = 'iso-27002' in fw
    if not has_27001 and not has_27002: continue
    if has_27001 and not has_27002: absent_27002 += 1
    elif has_27002 and not has_27001: absent_27001 += 1
    elif fw['iso-27001'].get('controlId') == fw['iso-27002'].get('controlId'):
        identical += 1
    else:
        different += 1
print(f'Identical: {identical}, Different: {different}, 27001-only: {absent_27002}, 27002-only: {absent_27001}')
"
# Currently: Identical: 1020, Different: 0, 27001-only: 0, 27002-only: 0
# Target: Different > 0 (Annex A mappings should use A.X.Y vs X.Y form);
#         27001-only > 0 (ISMS-process clause checks);
#         Identical: 0

Likely root cause

Probably one of:

  1. data/scf-framework-map.json maps both iso-27001 and iso-27002 to the same SCF framework ID. The build then derives identical mappings.
  2. SCF database controls_mappings table has identical entries for both framework IDs (upstream SCF data issue rather than CheckID).
  3. Manual override path copies the 27001 mapping into 27002 (or vice versa) somewhere in Build-Registry.py.

Investigation: trace the build for one M365 check (e.g., ENTRA-ADMIN-001) and see where the iso-27001 + iso-27002 entries get populated.

Suggested fix scope

Path A — Different controlId formats (Annex A reference vs implementation guidance)

If ISO 27001 should always be A.X.Y and ISO 27002 should always be X.Y, the fix is mechanical: build-time format the SCF-derived ID with the appropriate prefix per framework. Verify that 27001's intent is "this check satisfies Annex A control X.Y" and 27002's intent is "this check implements 27002 guidance X.Y."

Path B — ISMS-process checks should have ISO 27001 only

Identify which CheckIDs map to ISO 27001 clauses 4–10 (ISMS process). Today these likely don't exist as ISO 27001 mappings at all (only Annex A). May want to file a separate issue if introducing ISMS-process coverage is in scope.

Path C — Both A and B

Most thorough. May warrant breaking into separate PRs.

Acceptance criteria

  • Reproducer exit shows Different > 0 and Identical: 0 after fix
  • Existing M365-Assess regression tests/Behavior/Iso-27001-27002-Mapping-Audit.Tests.ps1 un-skips and passes (their CI catches the change automatically on next registry sync)
  • CHANGELOG documents the divergence model
  • No regression in mapping count for either framework (additive or differentiation, not loss)

Cross-impact

  • M365-Assess#871 — un-skip and tick the boxes in their audit doc
  • The community example from M365-Assess#618 — a tenant with admin-MFA gap should NOT mark ISO 27001 as failing if MFA isn't an ISO 27001 §5.x ISMS-process clause. Verify this scenario after fix.

Out of scope

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcontentAuthoring rationale, impact, references for checksupstreamIntegration with upstream data sources (SecFrame)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions