In an ordered firewall policy, a broad permit sits above a deny naming the same traffic — what reaches the server, and what does the deny still claim?
answer
- Order decides, not intent
- Unreachable code, but in a policy
- A rule that never matches never logs
- The deny on the page is not evidence
basics
~20 sThe traffic arrives. The earlier permit decides and the deny below it is never evaluated. The deny still sits in the policy, still reads as an enforced control in review and audit, and never logs anything.
solid answer
~50 sThe packet is permitted. In an ordered policy the earlier rule decides, so the deny is unreachable text — the policy's author, a reviewer and an auditor all read a control that is not in effect. That asymmetry is the whole danger: a shadowed *permit* is found in hours because the requester's flow breaks and someone raises a ticket, while a shadowed *deny* produces no symptom at all. It never matches, so it never increments a counter and never writes a log line, and the permitted traffic looks like ordinary allowed business traffic in whatever logging exists. An intruder with a foothold does not need to defeat the control; they ride a path the policy claims is closed. Nothing in day-to-day operations will surface it — you only see it by reading the whole ordered policy at once and asking which rule wins each region of the match space.
go deeper
Be ready to say plainly that the earlier rule decides and the later deny never runs, and that such a rule produces no log and no counter. Do not reach for a specificity or precedence rule that does not exist here.
Explain why the failure is silent: an unreachable permit breaks somebody's flow and gets reported, an unreachable deny fails open with no symptom. Be able to say what evidence a zero counter does and does not carry.
Show that you would find these by reading the exported policy as a whole rather than waiting for an operational signal, and that you treat a deny rule in an export as a claim to be verified, not as evidence of a control.
Own the consequence for assurance: if a deny that was presented as a control turns out to be unreachable, the control was not in effect for that period, and your evidence process has to produce analysis output rather than rule text.
## The shape of the problem A classical firewall policy is an ordered list of rules, and the first rule whose match criteria cover a packet decides its fate. That much is mechanics. What matters here is the consequence at the scale of a real rulebase: a rule's effect is not a property of the rule, it is a property of the rule *plus everything above it*. When an earlier rule's match set completely covers a later rule's match set and the two carry different actions, the later rule can never fire. It is unreachable — dead text in a live document. The security-relevant case is a broad **permit above a specific deny**: ``` 20 permit 10.0.0.0/8 -> 10.5.0.0/16 tcp/3389 (added during migration) ... 90 deny any -> 10.5.0.0/16 tcp/3389 (written years earlier) ``` Rule 90 will never match a packet as long as rule 20 stands above it. The remote-desktop path into 10.5.0.0/16 that rule 90 exists to close is open to everything in 10.0.0.0/8. ## Why it is a security artefact and not just untidiness Three separate people are misled by the same page. - **The author.** Somebody wrote rule 90 deliberately, for a reason they could defend. They believe that path is closed. Their threat model, their segmentation diagram and their design document all assume it. - **The reviewer.** The permit that shadowed it arrived on its own ticket, correct in isolation and approved on its merits. - **The auditor.** A deny rule in an exported policy is routinely accepted as evidence of a control. Here it is evidence of nothing. And the fourth party is the one that turns this from a documentation defect into an incident: an intruder who already has a foothold somewhere inside 10.0.0.0/8 does not have to defeat the boundary. They enumerate what actually answers, find the path, and use it. The control was never in their way. Post-incident, the defender's own policy export argues that the traffic could not have happened. ## Why nothing raises it The usual operational signals are all silent by construction: | Signal | What it shows for a shadowed deny | |---|---| | The rule's own hit counter | Zero — it never matched | | Deny logging | Nothing — a rule that never matches never logs | | The permitted traffic's logs | Ordinary allowed traffic, indistinguishable from business flows | | The change ticket that caused it | One new permit, correct on its face | There is no alarm to miss. Note the direction of the claim carefully: a zero hit count on a deny is **not** evidence that the traffic is being blocked. Traffic that is blocked *matches* the deny and increments it. Zero means either nobody tried, or the rule is unreachable — and from the counter alone you cannot tell which. ## The asymmetry that matters Order faults come in two flavours and they behave completely differently in production: - A **permit** that is shadowed (by an earlier deny, or by an earlier permit with different treatment) has a loud failure mode. The person who requested the flow finds it broken and complains the same day. - A **deny** that is shadowed has no failure mode. It fails open, silently, forever, and the only party who benefits is someone you do not want. This is why interviewers ask about this and not about first-match evaluation in the abstract: the mechanics are simple, the consequence is not intuitive, and the failure is invisible to everything except a deliberate reading of the whole policy. ## What actually finds it Not a person reading a diff, and not the appliance — accepting a rule that some earlier rule makes unreachable is not an error condition, and the box will take it. It is found by whole-ruleset analysis: export the ordered policy, decompose the multi-dimensional match space (source, destination, port, protocol, zone) into disjoint regions, and for each region ask which rule wins. Any rule that wins no region at all is unreachable. That computation is offline and static — it needs the policy, not the traffic — which is exactly why it is available to you and also why it is easy to never run. ## The price Running that analysis on a rulebase of several thousand rules does not return one finding. It returns thousands, spread across several anomaly classes, most of which are not security defects. Detection is cheap here; deciding what to do with the output, and finding an owner for rules whose authors left the company years ago, is where the cost lands. That is the trade this leaf turns on: the control is easy to prove broken and expensive to prove safe to fix.
- Does it matter whether the permit was added before or after the deny was written?No — the fault is positional, not chronological. A permit added last week near the top of the policy can silently kill a deny written five years earlier and never touched since. That is what makes it hard to attribute: the change that created the exposure looks nothing like the rule it disabled.
- Why does nobody notice from logs?Because there is nothing to notice. The shadowed deny never matches, so it produces no log line and no counter movement. The traffic it should have stopped is handled by the permit above and appears, wherever it is logged at all, as ordinary allowed traffic. Silence here is indistinguishable from success.
- Is a deny sitting below a broader permit always a defect?It is always dead — the deny cannot act. Whether that matters depends on what it names. Some were copied in as documentation, or as defence in depth against a rule that has since moved. The real problem is that nothing on the box tells you which kind you are looking at, so every one has to be read by a person.
It is unreachable code with a security label on it: the compiler is happy, the line reads correctly in review, and it never runs.
saying these in an interview costs you the question
- Says the deny wins because deny is stronger than permit
- Thinks the more specific rule wins regardless of position
- Assumes the appliance warns when a rule becomes unreachable
- Reads a zero hit count on a deny as proof traffic is being blocked
- Believes the later rule refines or narrows the earlier one