# Auth checked once, not per request

Policy or ACL evaluated at session or handle creation, then reused for later packets or requests

_Area: Web infrastructure and server-side requests. Seen in 2 disclosed reports; latest 2026-07-17. Updated 2026-11-02._

## How it works
Authorization is decided at one moment — session creation, connection setup, or first use of a handle — and the result is cached. But the thing being authorized is not fixed: later packets carry their own destination, later requests carry their own body, later calls reuse the same handle with a different method. The assumption that breaks is "the thing I authorized at creation is the thing I will act on later." When the per-request attribute (destination address, body size, method) can change after the check, the cached decision no longer describes what is actually being done, and the action proceeds unchecked.

## Where it shows up
- A protocol message that carries its own destination or target per packet, while the server stores policy at session scope [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md)
- Session-creation hooks that run ACL/outbound checks once, then later code paths calling write/send directly [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md)
- Filters that compute a size or parse result conditionally, returning empty/nil on some branches that policy then reads as "absent" [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md)
- Client libraries storing HTTP method and behavior in separate fields, reused across calls [E3](https://bugbountylibrary.com/r/h1%3A1991428.md)
- Any "authorize once, act many times" structure: connection pools, keep-alive, cached handles, long-lived sessions

## How to review
Find the authorization decision and list every attribute it depends on. Then find every later action taken under that decision and check whether any of those attributes can differ from what was checked. The invariant: **every action must be authorized against the attributes of that specific action, not a prior one.** For per-packet destinations, confirm policy runs per packet [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md). For body-based policy, confirm every branch of the size comparison (negative, equal, oversized) yields a parsed body or an explicit deny — never a silent empty that deny-on-presence reads as allow [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md). For reused handles, confirm method and option state reset together [E3](https://bugbountylibrary.com/r/h1%3A1991428.md).

## How finders spotted it
- Read the fix commit for a prior CVE, noticed the comment only reasoned about `ContentLength == -1` and the added test only covered small bodies, then hypothesized the oversized branch was unhandled and confirmed with the project's own unit test [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md)
- Noticed the protocol defines a per-packet address and the client exposes send-to-arbitrary-destination, then traced server code: session creation runs the ACL hook once, later packets call write without re-checking [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md)
- Code review of handle-reuse logic where method and behavior lived in separate fields, spotting the inconsistent state on a PUT-to-POST transition [E3](https://bugbountylibrary.com/r/h1%3A1991428.md)

## Variants seen
- Oversized declared body skips extraction, policy sees empty body and fails open while payload reaches upstream [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md)
- Per-packet UDP destination reuses a session authorized for a different address, reaching localhost/RFC1918 [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md)
- Reused HTTP handle transitions PUT to POST, stale read callback still fires [E3](https://bugbountylibrary.com/r/h1%3A1991428.md)

## Impact and severity
Bypasses authorization to reach blocked destinations (localhost, private networks) via SSRF [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md); silently defeats deny policies while delivering the payload upstream [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md); can send wrong data or trigger use-after-free in a widely used client library [E3](https://bugbountylibrary.com/r/h1%3A1991428.md). Severity rises when the cached decision guards a network boundary or when the unchecked action reaches internal services.

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **github.com/zalando/skipper (go)** < 0.27.26, fixed in 0.27.26: Skipper: Incomplete fix for CVE-2026-50197: an oversized body can bypass OPA deny-on-presence Rego policies (CVE-2026-65838). Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md. Fix: https://github.com/zalando/skipper/commit/2cfceabaa6ff0af65b312dcb9bcbe84691b9d507
- **github.com/apernet/hysteria/core/v2 (go)** >= 2.0.0, <= 2.9.1, fixed in 2.9.2: Hysteria has an authenticated UDP ACL bypass that enables localhost and private-network UDP SSRF. Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-8qqm-fp2q-v734.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-vgrc-hq28-p3xp.md
- E3: https://bugbountylibrary.com/r/h1%3A1991428.md
