DEV Community

StarkMan
StarkMan

Posted on

Range requests make cache correctness part of the security boundary

Range requests make cache correctness part of the security boundary

HTTP Range requests let a client ask for a subset of a representation. The feature supports resumed downloads and large media delivery. It also adds state to the path between an origin and a client: a response may be a 206 Partial Content, a multipart body, or an ordinary full response when the server chooses not to honor the requested range. A cache that handles those cases incorrectly can serve content that does not match the request.

RFC 9111 says a cache must not store incomplete or partial-content responses if it does not support Range and Content-Range, or if it does not understand the range units. A cache that implements partial responses must also evaluate If-Range against the response it selects. If a stored response contains only partial content, it must not include the entity tag in a union unless the request is for a range fully satisfied by that stored response. These rules exist to prevent a cache from turning parts of different representations into one response.

The security consequence depends on the asset and deployment. Public media usually tolerates a cache miss and a slow download. A signed download, a generated report, an export containing personal data, or a file whose bytes differ by tenant needs stronger validation. A shared cache must also apply the standard rule for requests with an Authorization header unless the response explicitly permits shared caching. A CDN configuration that ignores that rule can turn a user-specific response into a cross-user object.

Validators are central. A strong entity tag and an accurate Last-Modified value help distinguish representations, but they do not fix a cache that ignores Vary, the selected content encoding, or the authentication context. Compression can change the bytes that a range is supposed to address. If the cache stores one compressed variant while the client requests a range from another, the response may be structurally valid and semantically wrong.

Test the path with ordinary and adversarial cases. Request byte ranges across different representations of the same URL. Repeat with different Accept-Encoding values and an If-Range validator. Try a multi-range request, an unsatisfiable range and a range that begins near the end of a changing object. Then repeat through each cache layer, including the CDN and any application proxy. Confirm that the origin's Cache-Control, ETag, Content-Range and Vary decisions survive the path unchanged.

Do not use Range responses as a substitute for authorization. The resource server should make the access decision before slicing bytes. A range should not let a caller learn the size, checksum, file type or metadata of a resource it cannot access. Error responses should not expose an internal path or a cache key. If downloads are signed, validate the signature, the subject, the object identifier and the expiry before reading the requested bytes.

Cache operators should inventory which origins support partial responses and which content types use them. The inventory should name the owner of the cache policy and the test set for If-Range, compression and shared-cache authorization. When a new CDN rule or application framework changes the response path, rerun the test. Range handling is often implemented in libraries and infrastructure, so the application team may not see the behavior in its own code.

The control objective is not to ban Range requests. It is to make sure the object served is the object authorized, and that every cache layer either supports partial representations correctly or declines to store them. That is a routine testable property, and it belongs in the deployment checklist for any download path that crosses an authentication boundary.

References

Top comments (0)