AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Wildcard Vary must stop shared-cache storage

Django's wildcard Vary fixes separate storage eligibility from cache-key design. The later whitespace correction shows why representation matters as well.

Citiți articolul în română

Before deciding how to distinguish cached responses, decide whether a response may enter the shared cache at all. A wildcard Vary header belongs at that earlier decision. It does not name another request header to add to a key. It refuses to define a reusable variant through the usual header comparison. Making the key more elaborate cannot supply permission that the response withheld.

Django's 5 May 2026 security announcement described CVE-2026-6907: UpdateCacheMiddleware could incorrectly cache responses whose Vary header contained an asterisk, potentially storing and serving private data. The enduring lesson is an order of decisions. Establish eligibility before constructing the identity of a stored response.

A refusal is different from another dimension

A cache key answers which reusable representation matches a request. Storage eligibility answers whether the response should participate in that reuse. These questions interact, but they are not interchangeable. Treating every variation signal as input to the key erases the possibility that the signal means reuse must stop.

The 5.2.x patch makes the distinction visible. It adds a check for the wildcard and returns the response before the later caching work. That early return is the architectural point: the response continues to its recipient without becoming a shared reusable entry through this path. It is a storage decision rather than a new key dimension.

This is also a useful way to organize code review. Reviewers can first identify the conditions that exclude a response and then inspect how eligible responses are separated. If both ideas are buried inside key construction, it becomes harder to tell whether a missing variation merely reduces specificity or violates the response's reuse policy.

The business impact comes from what sharing means. A response that reaches its intended recipient correctly can still be unsuitable for another recipient. Looking only at the first request's output misses that distinction. Shared-cache behavior therefore needs its own responsibility in maintenance work, even when ordinary page rendering appears correct.

Keep the two disclosures separate

The May announcement named Django main, 6.0 and 5.2 as affected supported branches and issued 6.0.5 and 5.2.14. Those are historical release facts. They explain which change the article discusses; they are not a statement about the versions that should be selected for a deployment at the time you read this.

There is a necessary later chapter. The 3 June 2026 announcement described CVE-2026-48587, involving leading or trailing whitespace in Vary values. Its explanation says the helper failed to strip whitespace, so a padded wildcard could escape recognition and the response could be stored. The May change must therefore not be described as exhaustive across representations.

The June announcement listed main, 6.1 at alpha status, 6.0 and 5.2 as affected supported branches and issued 6.0.6 and 5.2.15. June evidence cannot be moved into May to make the original patch seem more complete. Equally, calling the May patch useless would lose what it actually changed. The sequence shows a correct eligibility rule whose recognition still needed refinement.

That is a broader maintenance distinction worth preserving: a policy can be right while its implementation fails to recognize all the forms covered by the policy. Reviewing the policy alone will not establish that the parser handles its inputs. Reviewing one accepted spelling alone will not establish that the policy is complete either.

Representation belongs in the reasoning

The wildcard's meaning should survive the allowed representation of the header value. In this history, whitespace was enough to separate the intended policy from the behavior described by the later advisory. The important question for a maintainer is where recognition happens and what assumptions that recognition makes about input already being normalized.

It is tempting to repair such a problem by adding another exception near storage. That may be necessary in a particular patch, but the design review should still identify the shared interpretation of the header. Otherwise different callers can appear to apply the same rule while disagreeing about the values to which it applies. That disagreement is easy to miss when reading only the final storage function.

None of this establishes exposure in a particular installation. The disclosures describe a potential problem under the relevant behavior. Whether an application used the middleware, produced the affected headers, and served relevant responses requires deployment-specific evidence. The article's conclusion concerns the design boundary, without estimating incidents or presenting a reproduction.

Some routes should bypass this decision entirely

The strongest counterargument is that explicitly non-cacheable routes can avoid shared-cache middleware. That can make responsibility clearer when a route's output should never be shared. There is little value in asking a generic caching layer to rediscover a prohibition that the application's route design can state directly.

This alternative depends on the application's routing and caching arrangement. Excluding some routes does not establish that every other response is eligible. A product can legitimately contain both deliberately excluded routes and cacheable routes whose response headers carry additional restrictions. The two policies should be understandable together.

For software maintenance, the practical starting point is to map which responses can reach shared storage and where eligibility is decided. Preserve the historical distinction between the May wildcard check and June's whitespace correction when recording the reason for that review. Once the refusal is honored, key diversity can do its narrower job of distinguishing responses that are actually eligible for reuse.