concept

Policy Bypass Surface

also called Enforcement Gap, Derived-Object Leak

The set of objects and paths through which data protected by a row or column policy can be read without that policy being evaluated - typically derived objects refreshed under a privileged identity.

rlsmaterialised-viewsextractsenforcement-pointcontrols

A row-level policy restricts each regional analyst to their own region. It is correct, it is tested, and a Berlin analyst's dashboard returns French rows.

The dashboard does not read the protected table. It reads a materialised view that was refreshed under its owner's identity, and the policy was evaluated once, for someone who sees everything. The rows were filtered before they were written down, which in this case means not filtered at all.

Every estate has a set of such paths. Enumerating it is the difference between a policy that protects data and a policy that protects one object.

Why it matters

The control tests pass throughout. Query the base table as a restricted user and the right rows come back, every time, which is exactly what a control test does. The incident is invisible to the test and to the auditor relying on it.

The exposure is also durable: a materialised view or an extract is a stored copy, so the leak persists until someone notices, and access logs on the protected table show nothing unusual because the protected table was never queried by the wrong person.

Implementation patterns

  • Enumerate the surface from lineage: every view, materialised view, extract, scheduled export, reverse-ETL push and feature table derived from a policy-bearing object.
  • Prefer invoker's-rights evaluation where the engine supports it, so the policy is applied for the reader rather than the creator.
  • Carry the policy column into derived objects and attach an equivalent policy, rather than relying on the derivation being safe.
  • Move enforcement to the layer consumers actually query — often the semantic layer or the serving store — when derived objects are the normal consumption path.
  • Test every published object, not just base tables, as a restricted test user on a schedule. This single change is what converts the control from theatre into evidence.

Industry example

Definer's-rights views have behaved this way in relational databases for decades: the SQL standard has carried explicit definer and invoker security semantics since SQL:1999, so this is documented, intentional behaviour, and it is why mature engines added invoker's-rights variants and why cloud warehouses now publish explicit guidance about policies and materialised views. The governance failure is not the engine's. It is that the control was designed around an object and the organisation consumes derivatives, which is a mismatch that no product setting fixes.

Failure scenarios

  • A materialised view refreshed by a service account with full access.
  • A BI tool extract holding an unfiltered copy of all 27 regions in its own storage, often on a laptop.
  • Reverse ETL pushing a filtered-once dataset into a CRM where different people read it.
  • A feature store built from protected tables months earlier by a team that has moved on.
  • A support tool with a service account, which is the version that shows up in a breach report rather than an audit finding.

Trade-offs

Enforcing at the base table costs a policy evaluation on every read and makes derived objects awkward; enforcing at the semantic layer is convenient for consumers and fails completely for anyone who connects to the warehouse directly. Most estates end up with both, which costs two policy definitions that must agree, and the reconciliation between them is itself a control worth testing.

When not to use it

The concept always applies, but the effort is not always justified: where the protected attribute is not sensitive — a convenience filter, a tidy default — chasing every derived object is disproportionate. Reserve the enumeration and the scheduled tests for policies that exist because of a legal or contractual obligation, and say plainly which policies those are, so the effort goes where a breach would actually matter.

Interview question

Q: An auditor asks you to demonstrate that your row-level security is effective. Your control test queries the protected table as a restricted user and passes. Why is that insufficient, and what test would you offer instead?

What a strong answer covers: the base table is one of many read paths; derived objects evaluated under a privileged identity break the guarantee while the test stays green; deriving the object list from lineage rather than from memory; a scheduled test that reads every published object as a restricted user; the copies outside the warehouse — extracts, reverse ETL, feature stores — that lineage will not show; and proposing enforcement at the consumption layer if that is where people actually read, rather than defending the current design.

Quick check

Quiz: Why do access logs on a protected table show nothing during a bypass incident? — The unauthorised reader never queried it; they queried a derived object that had already been materialised by a privileged identity.

Flashcard: Which control test distinguishes a real row-level policy from a partial one? — Reading every published object as a restricted test user, not just the base table.