# Fail-open access gates

Guards that skip checks on nil, cache miss, or non-primary fields, letting restricted data through

_Area: Web access control and IDOR. Seen in 3 disclosed reports; one confirmed bounty: $12,000; latest 2026-09-04. Updated 2026-11-02._

## How it works
An access decision is made conditional on something that is not the authorization fact itself: a feature flag, a cache entry, a non-nil field, or a group association. When that condition is absent or errors, the code takes the permissive branch instead of denying. The assumption that breaks is "the check ran and passed"; in reality the check was skipped, and downstream code still trusts that it ran. The result is a gate that fails open: missing data, a swallowed exception, or an unexpected shape all resolve to "allow".

## Where it shows up
- Early returns like `return unless project.group` that skip validation for one class of object [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- Finders/queries that return public objects regardless of feature-level access [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- Async workers (export/import jobs) that re-fetch objects without re-checking authorization [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- Filters that inspect only one field (e.g. `row.Cells[0]`) and guard the check with `if x != nil`, skipping when the field is not the expected type [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md)
- Denormalized mirror fields (relations, rollups, lookups) populated from another source and never passed through the same filter [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md)
- Guards that AND a persistent check with a volatile cache lookup, where the cache-populating code swallows exceptions [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8rh5-4mvx-xj7j.md)

## How to review
For every gate, ask: what is the deny path, and can it be reached when the condition is missing, nil, or errored? The invariant: **absence of the authorization fact must deny, never allow.** Concretely:
- Trace each early return and confirm the same params don't flow into services that assume validation ran [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- For structured-record filters, confirm every field carrying foreign content (relations, rollups) is evaluated, and that a non-matching first field denies rather than skips [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md)
- For guards combining persistent and volatile state, find the code that populates the volatile part and check whether its failure is swallowed; a silent catch turns the guard fail-open [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8rh5-4mvx-xj7j.md)
- Confirm async/background paths re-check authorization independently of the request path.

## How finders spotted it
- Read EE-prepended controllers/services; noticed `return unless project.group` skipped validation, then traced params through the service into the finder and export worker, spotting missing access-level and authz checks [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- Read the publish-access filter: saw the decision read only `row.Cells[0].Value.Block`, the `if bt != nil` guard silently skipped when column 0 wasn't a block, and relation/rollup contents came from a separate view never filtered [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md)
- Read the install guard's dual condition, then traced the constructor catch block that swallows DB exceptions and leaves the cache empty [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8rh5-4mvx-xj7j.md)

## Variants seen
- Validation bypass via early return on nil association, chained with a finder missing access-level checks and a worker missing authz [E1](https://bugbountylibrary.com/r/h1%3A689314.md)
- Filter that keys on one cell and fails open on non-block first columns, leaking mirrored relation/rollup content [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md)
- Cache-dependent guard that fails open on cache miss during DB outage [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8rh5-4mvx-xj7j.md)

## Impact and severity
E1 chained three minor flaws into full exfiltration of restricted repo, confidential issues and snippets; severity rose from chaining and from reaching private data across a tenant boundary. E2 leaked hidden-database content through an unauthenticated publish endpoint. E3 let an unauthenticated attacker overwrite `.env` with attacker DB credentials, receiving all subsequent logins and form data and controlling returned data for injection and privilege escalation — full takeover. Impact scales with what the gate protects and whether the fail-open path is reachable unauthenticated.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A689314.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-mfrj-v65r-979c.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-8rh5-4mvx-xj7j.md
