Skip to content

Permission Inheritance with Explicit Denial

Access-control protocol — instantiates Controlled Inheritance Propagation

Lets access rights flow down a resource tree by default, while an explicit local denial overrides any inherited grant — because deny wins.

Permission Inheritance with Explicit Denial is the access-control scheme in which rights granted on a parent node — a folder, a group, an org unit — flow to every descendant by default, so administrators set access once high in the tree instead of on every leaf. Its defining move is that a locally placed explicit deny shadows any inherited allow, no matter how far up the grant originated. Reuse (broad grants that cascade) and safety (a surgical local exception) therefore ride the same channel, and the precedence rule — deny beats allow — is what stops a convenient inherited grant from silently re-opening a door someone deliberately shut. It is the one sibling whose whole personality is conflict resolution biased toward the safe answer.

Example

A company keeps all engineering docs under a top-level Engineering/ share, with the Engineering group granted Read at that level. The grant cascades to every subfolder, so a new hire added to the group can immediately read everything — no per-folder setup. Then one subfolder, Compensation-Review/, has to be walled off from most of engineering. Rather than re-architect the tree, an admin places an explicit Deny-Read for the Engineering group on that single subfolder. The inherited Allow still reaches every other descendant, but here the local deny wins and the door is shut — even though the group-wide grant three levels up still says Allow.

The surprise the mechanism is built to survive comes later: someone grants one specific person a direct Allow on Compensation-Review/ and expects it to work. Under deny-wins precedence — the same rule real systems like NTFS ACLs and AWS IAM use, where an explicit deny overrides any allow — it still does not. The fix is to remove the deny, not to stack another allow on top. That single counter-intuitive outcome is exactly the behavior the protocol exists to make predictable.

How it works

  • Attach high, inherit down. A permission set on an ancestor is the default for all descendants; broad access is expressed once, near the root.
  • Place exceptions locally. A descendant node can carry an explicit allow or, more powerfully, an explicit deny.
  • Resolve conflicts by fixed precedence. When an inherited grant collides with a local rule, deny is evaluated first and wins — the protocol's signature, and why the safe reading breaks ties.
  • Read effective access as an accumulation. A node's real access is inherited entries plus local entries, evaluated deny-first; no single line tells the whole story.

Tuning parameters

  • Inheritance blocking — whether a descendant may stop inheriting from its parent entirely (a "protected" node). Blocking isolates a sensitive subtree but also hides it from tree-wide policy changes.
  • Deny scope — whether an explicit deny applies to just this node or propagates to its own descendants. Propagating denies seal a whole subtree; node-only denies are surgical but easy to under-apply.
  • Precedence strictness — absolute deny-wins versus most-specific-wins. Deny-wins is safest and most predictable; specificity-wins is more expressive but lets a narrow allow punch through a broad deny.
  • Grant altitude — how high the broad grants sit. Higher means less admin toil but a wider blast radius; lower means tighter control but more places to maintain.

When it helps, and when it misleads

Its strength is leverage with a safety bias: set-once-high grants scale administration, a single local deny closes a gap without touching the rest of the tree, and deny-wins makes the safe outcome the default whenever rules collide.

Its failure mode follows from the same cascade. Because grants inherit invisibly, excess inherited privilege accumulates — a subtree quietly carries access nobody remembers granting, and over-broad high grants mean the true access surface is far larger than any one node suggests. The classic misuse is reaching for another explicit allow to "fix" access a deny is blocking, then piling allows on top: it never works under deny-wins and leaves a tangle of contradictory entries. The discipline that guards against this is the principle of least privilege[1] — grant the narrowest scope that works and periodically re-derive inherited access from scratch, rather than trusting that a broad cascade plus scattered denies nets out safe.

How it implements the components

  • default_propagation_rule — rights set on an ancestor become the default access for every descendant; this is the "inherit down" half of the channel.
  • precedence_and_conflict_rule — the deny-beats-allow ordering that decides an inherited grant colliding with a local exception; the mechanism's defining behavior.
  • inherited_risk_register — the cascaded, accumulated privilege a subtree carries by default is the inherited risk this scheme must keep visible and prunable.

It does not catalog what may be overridden (inheritable_property_catalog — that's Platform Variant Option Model), check whole-object substitutability (substitutability_checkObject-Oriented Class Inheritance), or expire stale exceptions (override_review_and_sunset_ruleOverride Expiry Workflow).

Notes

Effective access here is not readable off any single node — it is the deny-first accumulation of everything inherited plus everything local. That is why this protocol pairs naturally with an effective-state view (see Effective Configuration Diff) at audit time: the cascade makes access safe, but only a resolved view makes it legible.

References

[1] The principle that every subject should hold only the access its task requires and no more — Saltzer & Schroeder's least privilege. Broad inherited grants pull directly against it, which is why inherited access is the first thing a privilege audit re-derives from scratch.