Deny protected operations. A timeout or error from the policy engine is not a permit. You may keep serving from a previously verified policy only while its policy, data and any decision cache stay inside an agreed freshness limit. Past that limit, the safe answer is a denial.
Two different outages
The OWASP Authorization Policy and Data Distribution Cheat Sheet separates loss of the policy distribution service from loss of a usable decision. They need different responses.
| What failed | What it means | Safe behaviour |
|---|---|---|
| Distribution service (bundle server) | New policy cannot arrive | Keep the last verified policy, within freshness bounds |
| Decision service (remote engine) | No answer for this request | Deny the protected operation |
| An attribute lookup | A required input is missing | Deny the affected operation |
| Startup with no policy loaded | Nothing to evaluate | Do not serve protected operations yet |
OPA, per the cheat sheet, retains its existing bundle when a new bundle fails verification. That preserves availability, but it does not prove the old bundle is still fresh enough.
Make the failure mode explicit
The Authorization Patterns Cheat Sheet points at Envoy's failure-mode setting as an example. The setting makes the choice visible, and allowing requests when authorization fails bypasses the control. Many teams leave this at a default they never read.
Write the choice down per route class. An admin write route and a public status page do not need the same behaviour.
Add a freshness budget
Every security-relevant input should carry a maximum age. Ask three questions.
- How quickly must a revocation or new restriction take effect?
- How long can a PDP run on its last data before it must stop granting access?
- What happens to cached decisions after a revocation?
The cheat sheet notes that an emergency restriction needs dynamic updates or an authoritative lookup, and that you should measure the propagation bound and deny affected operations when it cannot be met. Publication is not proof that every PDP activated the update, since bundle distribution is eventually consistent.
Do not turn undefined into allow
A common bug sits in the error path: a catch block that returns true, or a rule that yields undefined and gets coerced to permit. Test it deliberately.
- Kill the PDP and send a protected request. Expect a denial.
- Return malformed output from a stub PDP. Expect a denial.
- Delay the response past the timeout. Expect a denial, not a retry that eventually allows.
- Start the service with no policy available. Expect protected routes to refuse traffic.
Plan for availability without weakening it
A denial during an outage hurts. Reduce that pain without opening the door.
- Run an embedded or local PDP, so the network is not in the path.
- Distribute policy independently of releases so fixes land fast.
- Alert on policy age and on rising deny counts caused by errors.
- Keep a reviewed break-glass process for the few operations that truly cannot wait, with logging.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how ongoing checks surface drift, the same idea as alerting on policy age.
Safeguard supports policies, gates and guardrails, and dependency scanning that tracks advisories in the policy engine libraries you ship. Try the free scan at gold.safeguard.sh/scan.
Quick check
Should read-only routes fail open?
Decide per route and record why. Reading sensitive data is still protected, so most read routes deny too. Truly public content needs no policy call at all.
Is a cached permit acceptable during an outage?
Only for the same subject, action, scope and tenant, inside the approved freshness limit. It must not outlive a required revocation deadline.
Sources
- OWASP Authorization Policy and Data Distribution Cheat Sheet
- OWASP Authorization Patterns Cheat Sheet
Last reviewed: 19 October 2026.