# Auth fallback to weaker config

Security flag parsed but unused, or auth gate reading a mutable or defaulted value

_Area: Web authentication and account takeover. Seen in 3 disclosed reports; latest 2026-09-10. Updated 2026-10-25._

## How it works
A security decision is made against the wrong source of truth. The code parses or accepts a strong setting (a per-request auth proxy, a client API key, an auth-required flag), but the actual check reads a different value: a process-global option, a ContextVar default, or a mutable runtime field. The strong setting is silently ignored and the weaker path wins. The assumption that breaks is "the value I configured is the value the check sees." When the two diverge, the system fails open rather than closed.

## Where it shows up
- A request-scoped options object is threaded into a constructor, but the constructor branches on the corresponding global (e.g. `proxy.Opt.AuthProxy` instead of `proxyOpt.AuthProxy`) [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj.md).
- Middleware with an `if key:` branch that only sets context when a key exists, then falls through to `call_next` with no rejection [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md).
- A ContextVar or config default that resolves to a server-side secret when the client supplies nothing [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md).
- An unauthenticated endpoint that mutates the same runtime flag the auth middleware reads (`rc.NoAuth`) [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md).
- Auth checks that dereference mutable state rather than an immutable startup value [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md).

## How to review
For every security flag, trace it from where it is set to where it is read. The invariant: the value the authorization check reads must be the same value the caller configured, and it must not be writable by an unauthenticated request. Concretely: grep for branches on global options when a local option object exists [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj.md); inspect the negative branch of optional-auth middleware and confirm it rejects rather than passes through [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md); confirm no unauthenticated endpoint can write a field the auth gate reads [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md). A parsed-but-unused security flag is a fail-open.

## Variants seen
- Per-server auth proxy parsed but never activated; falls back to anonymous FTP or fixed-backend S3 [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj.md).
- Optional client key absent; request authenticated upstream with the operator's own key [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md).
- Unauthenticated config mutation flips the auth gate off at runtime [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md).

## Impact and severity
Anonymous access to protected resources [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj.md), full impersonation of the operator's upstream account [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md), and auth bypass enabling config disclosure and command execution [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md). Severity is high because the bypass needs no credential and the weak path is the default when config is missing or unset. It worsens when the fallback credential is a server-side secret or when the flag is mutable at runtime.

## Why fixes fail
Fixes that only set the strong option without changing the read site leave the global/default path intact; the flag stays parsed-but-unused. Fixes must move the check to the request-local value and make the gate field immutable to unauthenticated callers.

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-x9vc-9ffq-p3gj.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx.md
