Blog / Framework Critique

Why CIS Cannot Answer Your Cyber Threat Risk

CIS RAM is an excellent answer to a question it never asks. It can tell you whether a risk is reasonable. It cannot tell you whether your control set is complete — because it has no cause axis to check completeness against. This is fixable. It should be fixed.

BK
Bernhard Kreinz
• against CIS RAM v2.2 / Controls v8.1 • updated 2 Oct 2026 • ~12 min read
Updated · 2 October 2026

Checked against the TLCTC v2.6 canon, the CIS sources and the now-published per-Safeguard mapping (a rebuild against CIS Controls v8.1.2; data on GitHub). Three corrections: the fifth CDM v2.0 attack type is Targeted Intrusions; the matrix is ten clusters × six CSF functions — 60 named control objectives, each realised at local and umbrella scope — not strategies × Bow-Tie sides; and insider misuse inside a genuine grant is Abuse of Rights, not #1 (R-SCOPE). The figures in sections 03 and 05 now come from the published mapping; the June count (153 → 74) is kept as it was published. The argument stands.

Let's start where CIS is strong, because the strength is real and the critique only matters once you grant it.

CIS RAM v2.2 is, at its core, a risk-evaluation and legal-translation layer built on the Duty of Care Risk Analysis standard. Its value is genuine: Risk = Impact × Expectancy, the reasonableness and due-care balancing, the distinction between Safeguard Risk and residual risk, and the "universal translator" between security practitioners, business management, and regulators. When a regulator asks whether you acted as a reasonable person, CIS RAM gives you the machinery to answer. That is not nothing. That is the part most frameworks get wrong, and CIS gets right.

None of what follows touches that layer. The argument is narrower and structural: the layer underneath it — the threat categorization — is missing, and everything CIS RAM builds on top inherits the gap.

01 — THE GAPCIS has no cause axis. It only has consequences.

Ask CIS RAM what a threat is, and the glossary answers: "A potential or foreseeable event that could compromise the security of information assets." The modeling step then instructs you to "identify threats that may compromise the Confidentiality, Integrity, or Availability" of an asset.

Read that carefully. A threat is defined by the outcome it produces — a compromise of C, I, or A. In Bow-Tie terms, CIS RAM names threats on the consequence side of the pivot. It has no vocabulary for the cause side at all. The frequency input that drives Expectancy — the VCDB / VERIS commonality index — arrives pre-blurred, because VERIS classifies by actor, action, asset, and attribute mixed onto one axis.

The structural problem

You cannot select a Safeguard — a control that acts left of the pivot, before the compromise — coherently when your threat is named by an outcome that lives right of the pivot. The control and the threat are on opposite sides of the causal model. CIS RAM collapses the entire left side into the word "Threat" and anchors everything on the right.

The clearest symptom is the CDM v2.0 Attack Type list used in IG3: Malware, Ransomware, Web Application Hacking, Insider and Privilege Misuse, Targeted Intrusions. Five "attack types" on one list — and not one of them shares an axis with the others:

CDM "Attack Type"What it actually isTLCTC
MalwareA cause cluster#7
RansomwareAn attack path with a consequence#1 → #7 + [DRE: Ac]
Web App HackingAn asset-scoped grouping#2 #1 #3
Insider / Priv. MisuseActor label + effect#1 outside the grant · Abuse of Rights (no cluster) inside it — R-SCOPE
Targeted IntrusionsIntent metadataorthogonal

A cause, an outcome-chain, an asset class, an actor label, and an intent label — presented as peers. They are neither mutually exclusive nor collectively exhaustive. This is precisely the conflation that makes coherent risk assessment structurally impossible: when "ransomware" is a threat type sitting next to "malware," the commonality engine double-counts the same underlying #7 cause every time it appears inside a named campaign.

CIS RAM measures control effectiveness against threats it defines by their effects. The unit it counts and the unit it controls are not the same unit.

It is worse than borrowing. CIS discards the cause data it has.

The natural assumption — the one this post made in its first draft — is that CIS RAM simply inherits VERIS' actor-action-asset blurring. That is too generous. Open the Expectancy engine and look at what it actually consumes.

CIS RAM's Expectancy is the pairing of two variables: commonality × maturity. The "commonality" half is the VCDB Index — and the VCDB Index is nothing more than how often an asset class appears as a target, binned into quintiles. Six asset classes: Devices, Software, Data, Users, Network, Documentation. Users appear in ~50% of incidents → Index 3. Software in ~14% → Index 2. That is the entire threat-frequency input.

The reduction that breaks it

The VERIS Community Database is rich — by Verizon's own description it carries the causes, consequences, methods, and assets of thousands of incidents. CIS RAM throws away the cause and method dimensions and keeps only which asset class was hit. The blurring is not inherited from VERIS. It is introduced by CIS in the collapse to asset-class quintiles. The data to do better was in their hands. They discarded it.

So there is no cause variable anywhere in the calculation. Expectancy is built from an asset axis (which class got hit) and an effectiveness axis (how reliable the safeguard is). The how — the generic vulnerability, the mechanism — never enters. CIS RAM cannot express the expectancy that a server is exploited (#2) versus abused (#1) versus reached with stolen credentials (#4), because all three collapse into one row: "Software was a target, Index = N." The mechanism is invisible by construction — and they built the construction.

02 — THE MEASUREMENTWhy your Maturity Score floats.

CIS RAM's Safeguard Maturity Score ('1'–'5', "the reliability of a Safeguard's effectiveness against threats") is its own Key Control Indicator. It is trying to measure control effectiveness. The intent is right.

But effectiveness against what? The score is anchored to the outcome-blurred threat buckets above. You cannot derive a clean per-cause effectiveness from a Maturity Score when the "threat" it scores against is a mixture of causes. The number has nowhere stable to attach. It floats — per row, per assessor, per asset class — and two assessors scoring "the same" Safeguard against "the same" threat are measuring different blends.

TLCTC anchors its KCI and its DCS (detection latency at an observable edge) to mutually-exclusive clusters. Effectiveness and latency are measured per generic vulnerability. The measurement stops floating because there is finally a fixed thing to measure against. But — and this is the point — the KCI and DCS only become coherent once a categorization exists to anchor them. They are residual diagnostics. They are not the fix. The fix is the axis underneath.

03 — THE MATRIXCompleteness becomes falsifiable.

Here is the object CIS RAM cannot produce, and the reason it cannot prove its control set covers anything: the 10 × 6 × 2 matrix.

10 clusters × 6 functions × 2 scopes = 120 control areas
Ten mutually-exclusive cause clusters · the six NIST CSF functions (Govern, Identify, Protect, Detect, Respond, Recover) · two scopes (local: one asset or system; umbrella: enterprise-wide). Ten causes × six functions = 60 named control objectives — a floor, not a ceiling (application paper §8.1).

Every legitimate control objective occupies exactly one cell — one (cluster, function) objective, realised at local or umbrella scope. The matrix is the complete, deterministic control-objective space. And because it is closed, every gap is a named empty cell. Coverage becomes falsifiable: you can prove what you cover, and prove what you don't.

CIS RAM cannot do this. It maps Safeguards to threats ad hoc, row by row in the Risk Register, with the threat side anchored to C/I/A outcomes. CIS does carry the column axis — every Safeguard has a NIST CSF security function — but not the rows: the functions sit on top of outcome-blurred threats, so there is nothing to cross them with. The result is a long, flat list. A flat list cannot tell you what you are not covering, because there is no enumerated cause space to check completeness against. Your threat set is whatever the assessor happened to write down, drawn from VERIS commonality.

And once you do draw the matrix, it reveals something CIS RAM is structurally blind to. Place the Safeguards on the 60 objectives and only 31 receive a cause-specific Safeguard; the other 29 rest on umbrella controls alone — every RECOVER objective among them, and five of the six #5 Man-in-the-Middle objectives. The preventive load is lopsided too: 26 placements each on #1 Abuse of Functions and #4 Identity Theft, 18 on #2 Exploiting Server — and 3 on #6 Flooding, none of them written for flooding. This is not a risk-weighted allocation — it is where the control set historically accreted. CIS RAM's expectancy engine cannot perceive it, because its only commonality axis is asset-class frequency: it can report that devices are attacked in 74% of incidents, but it has no coordinate in which "identity theft outnumbers flooding almost nine to one" can be expressed. The skew is in plain sight, and the instrument cannot resolve it.

04 — THE FLOORAn umbrella control cannot prevent a target-zero.

This is the argument that turns everything above from a matter of elegance into a matter of correctness.

A control objective must be granular enough to map to exactly one cell. An umbrella control that spans multiple cells cannot achieve any of them to target-zero — the index compromise, the zero-patient event you are trying to prevent from occurring at all — because its effectiveness is averaged across causes that demand structurally different mechanisms.

Worked example — "Patch Management"

One Safeguard, spanning at least three cells: #2 server-side exploitation, #3 client-side exploitation, and the supply-chain re-anchoring window #10 → #1. Three different clusters. Three different velocity classes. Three different detection edges. One KCI cannot measure it, because there is no single thing being measured.

Target-zero requires the control to act on the specific generic vulnerability the cluster names — the cluster is the vulnerability. An umbrella control acts on a blend, so its effectiveness against the actual cause is necessarily sub-unity. It leaks at exactly the cell where the attacker enters. The breadth that makes a control look efficient is the same averaging that guarantees it cannot reach zero on any single path.

And CIS RAM's own engine proves it has no place to put the distinction. "Patch Management" receives one Maturity Score, paired against the Software/Devices asset-class index, yielding one Expectancy cell. But the control spans #2, #3, and #10→#1 — three causes folded into one asset-class bucket. The matrix is not merely bad at separating the three paths; it has no coordinate where the separation could be written down. The umbrella is unmeasurable because the measurement space was built without a cause axis.

An objective that cannot be measured to target-zero against a single cell is not a control objective. It is a control aspiration.

And this is where the due-care standard — CIS RAM's own crown jewel — turns against the umbrella. The moment a specific cluster-path causes harm, an umbrella control is indefensible: you cannot argue you took reasonable care against cause X when your control's effectiveness against X was never separately measurable. It was buried in an average. "We had a patch program" loses in front of a regulator. "Our KCI against cluster #2 server-side exploitation was at target-zero on the date of the incident" is the DoCRA standard actually delivered. Cell-purity is not taxonomic hygiene. It is the difference between evidence and aspiration.

05 — THE RESULTThe redesign cuts both ways at once.

If CIS were to re-anchor the Controls onto the matrix, the objective set would move toward a structural minimum from two directions simultaneously:

  1. De-aggregate the umbrellas.Safeguards that span multiple cells must split. "Patch Management" becomes distinct objectives per cluster, per side. This raises the apparent count where it was hiding coarseness. In v8.1, 43 Safeguards span more than one cluster (published mapping; the June count was 34).
  2. De-duplicate the repeats — and drop the non-controls.The same generic strategy restated across asset classes collapses to one cell. And the 46 pure enablers (inventory, process, governance, general detection rows) that act on no cluster fail the granularity floor entirely — they are not control objectives at all; 18 more act after the compromise, at the Data Risk Event, and belong in a separate DRE matrix. This lowers the count sharply.

The two forces meet at a smaller set of cell-pure objectives — each one granular enough to hit target-zero, none of them duplicated. The CIS Controls v8.1 set of 153 Safeguards is, today, simultaneously too coarse (umbrellas that can't reach zero on any cell) and too redundant (the same cell restated per asset class), while a third of it isn't cause-acting control at all. The matrix fixes all of it at once.

No longer a prediction — the mapping is done

The earlier draft of this post forecast a reduction "on the order of 60 objectives." We then performed the full cell-by-cell mapping of all 153 v8.1 Safeguards onto the matrix. The result: 153 → 74 cell-pure objectives, a net reduction of 79. The prediction held, with margin. Two drivers: 48 Safeguards fail the granularity floor (pure enablers), and de-duplication across 34 umbrellas and repeated strategies collapses the rest. In the June count every one of the ten clusters was covered on both Bow-Tie sides — so adoption is a re-anchoring, not a rebuild. (The exact 74 depends on how finely the six generic strategies are cut within a cluster; direction and magnitude are robust, the precise integer is pending ratification against the canonical strategy set.) The full mapping is in the companion evidence page: 153 Safeguards → 74 objectives.

Update, October 2026. The per-Safeguard data is now published as a rebuild (the June data file was lost). It keeps the 34 Safeguards the evidence page names and confirms the direction, with two refinements: the 18 data-layer Safeguards leave the cluster matrix, and not every cluster is covered on both sides — no cause-specific detection or response Safeguard exists for #5 or #9. On the canonical grid, 31 of the 60 objectives have a cause-specific Safeguard.

· · ·

06 — THE RELATIONSHIPNot a competitor. A foundation.

The headline is not "CIS RAM is broken." It isn't. The headline is that the two frameworks occupy different strata, and CIS RAM is missing its bottom one.

LayerCIS RAMTLCTC
Cause taxonomyabsent — borrows VERIS / CDMthe 10 clusters
Bow-Tie pivotnone — Threat → C/I/A directlySRE / DRE / BRE
Control spaceflat row list10×6×2 matrix
Effectiveness (KCI)Maturity Score — floatsper-cell, per-cause
Risk mathImpact × Expectancy (DoCRA)out of scope — sits above
Modeprobabilisticdeterministic / axiomatic

Slot TLCTC underneath CIS RAM as the cause axis. Replace the VCDB / CDM threat input with the ten clusters. Keep DoCRA's Impact × Expectancy, keep the reasonableness machinery, keep the legal translator — all untouched. The Expectancy engine even improves, because commonality measured per cluster eliminates the ransomware-as-a-threat-type double-counting it currently carries.

So: can CIS answer your cyber threat risk? It can answer whether a given risk is reasonable to accept — superbly. It cannot answer whether your control set is complete, whether any single control reaches target-zero, or whether your effectiveness measurement is anchored to anything stable. Those three questions all require a cause axis. CIS doesn't have one.

It is catalog-agnostic which controls you adopt. It is not optional whether you can name your causes.

07 — THE ASKWhat CIS should do.

This is not a request to abandon CIS RAM. It is a request to give it the foundation it is missing — and the changes are concrete:

  1. Restore the cause dimension in the VCDB ingestion.The data is already in VERIS. Stop collapsing it to asset-class quintiles. Bin commonality by cause cluster, not by which asset got hit. This alone removes the ransomware double-count and makes Expectancy mean something causal.
  2. Re-anchor the Controls onto the 10×6×2 matrix — and the data-layer Safeguards onto the DRE matrix.Assign every Safeguard to its cell. The mapping is the audit: umbrellas split, duplicates merge, gaps surface as named empty cells. Completeness becomes provable for the first time in the framework's history.
  3. Enforce the granularity floor.Retire any objective that cannot be measured to target-zero against a single cell. Those are aspirations, not controls — and under DoCRA's own due-care standard, they are indefensible the moment a specific cause-path causes harm.

Every part of CIS RAM that works — DoCRA, Impact × Expectancy, the reasonableness test, the legal translator — survives all three changes intact. Nothing of value is lost. What is gained is the one thing the framework cannot currently deliver: a defensible, falsifiable answer to the question its own title implies it can answer.

The cause axis exists. It is open, it is free, it is CC BY 4.0. There is no technical reason not to adopt it — only the inertia of a control set that grew before anyone insisted it name its causes. That inertia is now the only thing standing between CIS RAM and a risk assessment that can actually be defended.

Notes

Critique target: CIS RAM v2.2 Core (Nov 2025) / CIS Controls v8.1. Mapping result (June 2026): 153 Safeguards → 74 cell-pure objectives (−79); strategy grain pending ratification against the canonical TLCTC strategy set. Per-Safeguard data (rebuild against v8.1.2, October 2026): mappings/cis-controls-v8.1. Updated 2 October 2026: CDM attack type corrected to Targeted Intrusions, matrix axes aligned with application paper §8.1, insider misuse per R-SCOPE.

TLCTC Framework · CC BY 4.0 · github.com/Barnes70/TLCTC