Pakkit.net
← Back to blog

Security

The Change That Locks You Out Flips a Default From Allow to Deny

The scariest config changes aren't the ones that obviously break something — they're the ones that silently convert an implicit allow-all into an explicit allow-list, so the thing you added quietly excludes everything you didn't.

  • Security
  • Linux
  • Operations
  • SSH

The change that locks you out of a box is rarely the one that looks dangerous. It’s usually a small, well-intentioned addition that flips an implicit allow-all into an explicit allow-list without announcing it did so. You add one entry to permit one thing, and as a side effect you’ve just denied everything you didn’t name — including, often, yourself. The canonical example lives in SSH, but the shape shows up everywhere, and learning to recognize it has saved me more than one “why can’t I log in anymore” moment.

The classic: adding AllowUsers to sshd

Picture a host whose sshd has no AllowUsers directive. That’s an implicit allow-all: any account that can otherwise authenticate is permitted. Now some automation, hardening a box, adds AllowUsers serviceaccount so the service can log in. Reasonable, right? Except the presence of AllowUsers changes the rule from “everyone allowed” to “only the listed users allowed.” You didn’t just permit the service account — you implicitly denied every other user on the system, including your own login and anyone else who relied on getting in.

Adding the first entry to an allow-list doesn’t add a permission. It removes everyone you forgot to add.

On a remote host, that’s how a “harden SSH” task turns into “I can no longer reach this machine.” The directive did exactly what it says; the trap is that going from absent to present-with-one-entry is a polarity flip, not an addition.

The pattern: implicit-allow to explicit-deny

SSH is just the example everyone eventually meets. The general failure mode is any mechanism where defining a rule at all changes the default for everything the rule doesn’t mention:

  • A firewall that allowed all egress until you add your first explicit allow rule — and now everything unlisted is dropped.
  • An access-control list that was permissive until the first entry made it a strict membership test.
  • A login PAM or policy change that introduces an allow-list where there was none.

In every case the dangerous moment is the transition from no policy to a one-entry policy, because that’s when the implicit “everything” becomes an explicit “only these.” Adding the second and third entries is safe and obvious. It’s the first one that silently redefines the universe.

Why it’s so easy to miss

Two things make this bite. First, it reads as additive — you’re adding a line, and adding usually means granting, so your guard is down. Second, it often works for you in the moment: the entry you added is the path you’re testing, so your test passes while everyone and everything else is now excluded. The damage is in the set you didn’t enumerate, which is precisely the set you’re not looking at. By the time the exclusion surfaces, you’ve moved on, and the symptom (“nobody else can get in”) looks unrelated to the “harmless” line you added.

How to defuse it

The habits that keep this from ruining a day are cheap:

  • Know the default you’re leaving. Before adding the first entry to any rule, ask: “what’s the behavior with no rule, and does adding one flip it?” If absent means allow-all, your first entry is a deny-everyone-else in disguise.
  • Enumerate yourself into the list. If you must introduce an allow-list, make sure your own access and any other essential accounts are in it in the same change, not in a follow-up you’ll forget.
  • Validate config before you cut over. For SSH specifically, test the config syntax and, better, keep a second session open so a bad change can’t fully lock you out. Many tools have a “check, don’t apply” mode — use it on the change that could strand you.
  • Have an out-of-band way back. A console, a second access path, a snapshot to revert to. The whole risk of this class of change is losing your way in; keep a door that the allow-list doesn’t control.

Respect the polarity flip

The takeaway is small and worth internalizing: some changes don’t add or remove a permission, they change the default stance for everything unmentioned. Those are the ones to slow down on, because their blast radius is the entire set you didn’t think to name. I treat any “add the first entry to a list that gates access” change as a potential lockout until I’ve proven otherwise — same caution I bring to anything with a wide blast radius, like giving automation a panic button or treating security as architecture, not decoration. If you’ve locked yourself out of a box with a one-line “improvement,” you’re among friends — tell me.