pattern

Fail-Closed Classification Default

also called Untagged-Is-Restricted, Deny-On-Missing-Label

Resolving an absent sensitivity label to the most restrictive class, so that forgetting to classify data produces a denied query rather than a silent exposure.

data-classificationpolicy-engineschema-changedefault-denygovernance

A platform binds access policy to sensitivity labels: restricted columns go to a small group, internal columns to everyone with warehouse access. The labels are curated and the policy engine works.

Then a migration adds eleven columns to the orders table, one of them a date of birth, and nobody labels them. The policy engine evaluates the rules, finds no label, and resolves "no label" to "no restriction". Four hundred dashboard users can read a date of birth, every query succeeds, and nothing reports it, because no control alerts on an absent label.

The pattern is the one-line correction: an absent label resolves to the most restrictive class, and the missing classification becomes a denial somebody notices within an hour.

Why it matters

Label-bound policy is only as good as its default, and the default is usually chosen implicitly by whoever wrote the rule-evaluation code. The untagged set is not a backlog that shrinks; it regenerates continuously, because schema change is continuous. An estate of 40,000 columns taking on the order of 300 new columns a month has a permanent queue whose length is the exposure window.

The detection asymmetry is what makes fail-open dangerous. A missing label produces a working dashboard; a fail-closed default produces a broken one, reported in minutes by the person who needs it.

Implementation patterns

  • Deny on missing label in the policy engine, as the evaluation default rather than a rule somebody adds.
  • Require a label in the schema-change path. A migration without labels on new columns fails in continuous integration, where the fix takes 30 seconds. The policy engine is the backstop.
  • Inheritance from the table or domain as the default label, so only exceptions are typed.
  • A grace list with expiry. Switching the default on breaks live dashboards, so ship it with an exemption list where every entry carries an owner and a 30-day expiry.
  • Automated discovery as a detector rather than a gate, with untagged column count reported as a trend. A scanner runs after the exposure exists, so it measures the window rather than closing it.

Industry example

The pattern is the one firewalls settled on decades ago: a rule set whose default is permit accumulates exposure nobody chose, and the fix is deny with an explicit allow list. Data platforms arrived later because labels began as documentation and became enforcement afterwards. Catalogues and warehouses now support tag-based access policy with a configurable default, and that configuration is the whole decision: the same tooling with the default inverted produces either a control or a comment. Data protection by design and by default has been an EU legal requirement since 2018, and a permissive label default fails the second half of that phrase.

Failure scenarios

  • A new data source onboarded whose tables arrive entirely unlabelled, so the whole dataset is readable.
  • Derived tables and exports losing the label in transformation, which fail-closed catches.
  • A policy engine that fails open on its own errors, so a timeout against the label store grants access. The default must hold when the mechanism breaks, not only when the label is missing.

Trade-offs

What you buy is that forgetting produces a denial. What you pay is friction on the day you switch it on: broken dashboards, broken pipelines and a queue of exemption requests. That cost is front-loaded and finite, which is the argument for paying it and why the grace list matters more than the default itself. The ongoing cost is a label decision per migration, roughly 30 seconds, against a governance queue measured in weeks.

The second-order cost is over-classification: if labelling is annoying, people label everything restricted, the class becomes unworkable, and access is granted broadly to compensate. Inheritance from the table or domain prevents that by making the common case automatic.

When not to use it

An internal analytics estate with no external sharing and nothing a regulator would ask about does not need this, and flipping the default costs more in broken work than the exposure is worth. Prefer detect-and-alert with a hard remediation deadline when the blast radius of an unlabelled column is a dozen trusted colleagues, and switch to fail-closed when the readership leaves that group. The threshold is not the estate's size but who can read an unlabelled column by default.

Interview question

Q: "You own a warehouse with tag-based access policy and 40,000 columns. An auditor finds a sensitive unlabelled column readable by 400 people. The team proposes a nightly scanner and steward approval on schema changes. What would you do instead, and what breaks on the day you do it?"

What a strong answer covers: the default being the actual defect; deny-on-missing plus a label requirement in the migration path so the failure lands in continuous integration; why steward approval is a throughput ceiling against roughly 300 schema changes a month; the grace list with owners and expiry; over-classification as the predictable side effect and inheritance as the defence; and when detect-and-alert is proportionate.

Quick check

Quiz: A policy engine finds no sensitivity label on a column. What should it do and why? Answer: deny, because a missing label is a missing decision, and a denial is reported in minutes while a silent permit is found by an auditor.

Flashcard: Why is a nightly scanner not a substitute for a restrictive default? It runs after the exposure exists, so it measures the window rather than closing it.