The real fix isn't always available today. The dependency with the known CVE can't be upgraded without a migration nobody has time for this quarter. The vendor integration handling the actual flaw is out of your hands until their next release. The architecture change that would close the gap properly needs a redesign, not a patch. A compensating control is what you put in place instead — not a replacement for the fix, but something specific enough to actually reduce the risk while the real fix is still pending.
Quick definition: A compensating control is a mitigation applied in place of the actual fix for a risk, when that fix isn't available right now. It has to measurably reduce exposure to a specific threat, not just exist nearby — and it comes with an expiry, not a permanent home in the design.
When it's legitimate
A compensating control earns its name when the root cause genuinely can't be fixed on a reasonable timeline, and the control in its place actually closes the specific path an attacker would use. The classic case: a legacy dependency with a known vulnerability that can't be upgraded without breaking something else first, mitigated with a WAF rule or input filter that blocks the exact exploit pattern for that CVE. The vulnerability is still there. The path to reach it isn't, for as long as the rule holds.
Other reasonable cases follow the same shape: an internal service that should require mutual TLS but can't yet, temporarily restricted to a network segment nothing external can reach; a third-party integration with an overly broad OAuth scope, wrapped in a proxy that strips the calls you don't actually need. In each case, something about the system's real exposure changed. That's the test a compensating control has to pass.
When it's a rationalization wearing a control's name
The failure mode is common and easy to miss in the moment: a team identifies a real risk, can't fix it now, and reaches for something that feels like mitigation without actually interrupting the attack path. Adding a log line, a dashboard alert, or general monitoring "in case something happens" is the most frequent version of this — it improves your chances of noticing after the fact, but it does nothing to the likelihood or impact of the thing you were trying to reduce. That's a detective measure, not a compensating control, and confusing the two is how a real gap ends up marked as handled.
The tell is almost always the same: can you name the exact attack path the "control" interrupts? "We have a WAF" is not an answer to that question. "This WAF rule blocks the specific parameter injection this CVE relies on" is. If the honest answer is "it makes us feel better about this area," it isn't a compensating control yet, whatever it's labeled as in the register.
Where compliance frameworks already formalized this
PCI DSS is the clearest existing spec for what separates a real compensating control from a stand-in: it requires that a compensating control meet the intent and rigor of the original requirement, not just gesture at the same general area, and that it address the specific risk the unmet requirement was meant to cover. A compliance auditor asking "what does this actually stop, and how do you know" is asking exactly the question a threat model should already be asking before the auditor shows up. If you can't answer it in a design review, you won't be able to answer it in an audit either.
It belongs in the risk register with the same discipline as an acceptance
A compensating control isn't a one-time fix-and-forget action — it's a live mitigation standing in for one that hasn't shipped, and it needs the same bookkeeping an accepted risk gets: a named owner, a written statement of what it actually blocks, and a review date tied to when the real fix is expected. Without that date, a compensating control quietly becomes the permanent architecture by default — nobody decided that on purpose, it just never came back up. Record it in the risk register linked to the specific threat it covers, not as a general note that "this area has some mitigation," so the next person to look at that entry can tell at a glance whether the control still matches the risk it was built for.
The review date matters even when the timeline looks stable. A compensating control's justification rests on facts that can shift quietly — the vendor's release schedule slips, the dependency picks up a second, unrelated vulnerability the original control never accounted for, or the network segment it relied on gets opened up for an unrelated reason six months later. A control with no expiry doesn't get re-examined when any of that happens. One with a date does.
Where this goes wrong
- Monitoring standing in for mitigation. Visibility after the fact is valuable, but it isn't the same claim as "this reduces the risk," and treating it as equivalent is how a real gap gets marked closed.
- No expiry. A compensating control with no review date becomes the permanent design, invisibly, the moment everyone stops thinking about it.
- Vague scope. "We have some mitigations around this" isn't a control anyone can verify. Name the exact path it interrupts, or it isn't one yet.
- Stacking without re-testing. Layering a second compensating control on top of a first, without checking whether the combination still addresses the original threat or has just added complexity around it.
None of this makes compensating controls a lesser option — sequencing real work is a normal part of running a system, and pretending every risk gets fixed the moment it's found is its own kind of dishonesty. The distinction that matters is between a control that actually does something to the attack path and a placeholder that only looks like one. The first is a legitimate, time-bound decision. The second is an accepted risk that never admitted it was one.
PCI DSS's own Compensating Controls Worksheet is the most formalized version of this test in any widely-used framework — see threat modeling for fintech for how that scope boundary interacts with the rest of a cardholder data environment.