Research Published · 4 min read

CIS and Docker contradict each other, so decide in writing

CIS says disable IP forwarding. Docker depends on it. Applying the control breaks the platform; skipping it quietly makes the compliance report lie.

Our platform applies the CIS hardening benchmark across every server. It also runs all of its services in containers. Those two sentences conflict more often than is usually admitted, and the conflict has only three possible outcomes.

Either you apply the control and break the platform. Or you skip it quietly, and the compliance report states something untrue. Or you decide explicitly, in writing, with the reason.

The third is the only defensible one, and it is the least practised.

The clearest case: IP forwarding

The benchmark says to disable IP packet forwarding on a host that is not a router. The control is entirely sound: a machine that routes when routing is not its job offers an attacker a lateral path.

Docker, however, depends on it structurally. The bridge networking that containers rely on assumes the host forwards packets between its physical interface and the virtual ones. Without forwarding, containers lose network egress.

Applying the control on a Docker host therefore does not harden the machine, it switches off the service the machine provides. And the effect is particularly unpleasant because it is deferred: the value can be written into persistent configuration, the platform keeps running on the kernel’s current state, and the outage only appears at the next reboot, weeks after the change that caused it.

The exception, written down and reasoned

Our decision sits in the inventory variables, with its reason on the same line:

linux_kernel_disable_ip_forward: false   # all nodes run Docker — Docker manages ip_forward
linux_ip_forwarding_ubuntu_disabled: true  # skip ip_forwarding role — Docker manages this

This is not a discreet exception buried inside a role, it is a decision legible at the place where the estate is configured. Anyone inheriting the infrastructure sees both what was waived and why, without having to reconstruct the intent.

That is the entire difference between an exception and an oversight. Technically the machine is in the same state. In governance terms they are opposites: one is an accepted, documented risk, the other is an undetected deviation.

The other trade-offs, and their nature

Forwarding is not an isolated case. The same estate carries several exceptions, and they do not all follow the same logic. The distinction is worth making, because it changes what you owe an auditor.

Control not applicable. The benchmark asks for a bootloader password. On a cloud provider’s virtual machine you have no console access at boot, and the corresponding threat model does not apply. The control is waived because it has no object.

Control in functional conflict. The system’s application confinement has to be adjusted where containers need their own profiles. The control is not removed, it is moved to the mechanism that does understand containers.

Control covered by other means. The benchmark mandates a file integrity tool. Ours is disabled, because integrity monitoring is handled by the SOC agent, which additionally feeds those events into the detection chain. The control’s objective is met by a different, better integrated route.

That third case is the interesting one, and compliance vocabulary has a name for it: a compensating control. It is not a waiver, it is a commitment, and it is worth exactly what the replacing measure is worth.

Control contrary to context. The benchmark suggests disabling IPv6. Our provider uses it. Disabling it would degrade connectivity with no identifiable security benefit.

The real indicator is not the score

Hardening is often measured as a percentage of controls satisfied. It is a convenient and weak indicator, because it does not distinguish an applied control from an inapplicable one, nor a reasoned exception from an oversight.

Two estates showing the same score can be in very different states. The useful question is not “how many controls pass”, but “are the controls that do not pass all known, reasoned and dated?”. An estate at 78% whose remaining 22% are documented line by line is in a far better position than one at 92% whose 8% are unexplained.

It is also the only form in which hardening survives the departure of whoever set it up.

What we take from it

  1. A general-purpose benchmark does not know your platform. CIS describes a Linux host, not a Linux host running containers. Conflicts are expected, not exceptional.
  2. Silence is the worst of the three choices. Applying and breaking is visible; deciding and writing it down is defensible; skipping without saying so produces a false report, which is precisely what a report must not be.
  3. An exception is judged on its reason, and that reason must live where you configure, not in a parallel document that will drift.
  4. Distinguish inapplicable, conflicting, and compensated. The three do not commit you to the same thing, and only the third creates a lasting obligation.
  5. Deferred hardening is a trap. A written value that only takes effect at reboot separates cause from effect by weeks. Check what survives a restart, not what is written in the file.

Point 2 is what separates a team doing security from a team producing security reports.

ciscompliancedockerhardeninggrc