GHSA-fwjf-m4qw-9f2x: Medium severity pip/django-cms vulnerability
Summary The CMS page cache key ignores the request headers that plugins declare via getvarycacheon(). The header is added to the response Vary header, but the CMS's own cache key does not incorporate the header values, so the first visitor's variant is served to all subsequent visitors regardless of their header values.
Details pagecachekey (in cms/cache/page.py) keys only on cache prefix, site, language, path and timezone. setpagecache collects the plugin-declared vary headers and calls patchvaryheaders(response, ...) (affecting only the emitted Vary header), but stores and retrieves the cached page under the header-agnostic key. getpagecache therefore returns whichever variant was cached first.
Impact - Information disclosure: when a plugin varies its output on a request header (e.g. Country-Code), the variant rendered for the first anonymous visitor is served to everyone until the entry expires, leaking request-specific content across users. - Cache poisoning: an unauthenticated attacker can prime the anonymous page cache with content rendered from attacker-chosen header values, which is then served to subsequent visitors.
Applies only when CMSPAGECACHE is enabled and at least one plugin implements getvarycacheon().
Patches Fixed in 5.0.8: the page cache now folds the request's values implements getvarycacheon().
Patches Fixed in 5.0.8: the page cache now folds the request's values for plugin-declared vary headers into the content key. The set of vary headers is persisted on write and looked up first on read (mirroring Django's learncachekey/getcachekey); a missing header-list entry degrades to a cache miss, never a wrong-variant hit.
Workarounds Disable CMSPAGECACHE, or avoid plugins that rely on getvarycacheon(), until upgraded.
Credits Reported by the security team at the University of Sydney ([@reporter]).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/django-cmsto a version that resolves this vulnerability.Fixed in 5.0.8 - Upgrade
Upgrade
CMS page cacheto a version that resolves this vulnerability.Fixed in 5.0.8 - Configuration
Disable CMS_PAGE_CACHE until upgraded, because the bug applies only when CMS_PAGE_CACHE is enabled and at least one plugin implements get_vary_cache_on().
CMS_PAGE_CACHE enabled = false - Compensating control
Avoid plugins that rely on get_vary_cache_on() until upgraded.
Event History
Frequently Asked Questions
Which deployments are exposed to cross-user content mixing?
Deployments are exposed when the CMS page cache is used for anonymous pages and a plugin varies its rendered output based on request headers declared through get_vary_cache_on(). The cache key does not include those header values, so one cached variant can be returned to visitors with different header values.
What does an attacker need to do to poison the cache?
An unauthenticated attacker can request a cacheable anonymous page with attacker-chosen values for a header that affects plugin output. If their request populates the cache first, that rendered variant can be served to subsequent visitors until the cache entry expires.
How can I determine whether a page is affected?
Identify plugins that implement get_vary_cache_on() and render different content according to the declared request headers, such as Country-Code. For affected pages, the response may contain the appropriate Vary header, but the CMS page cache key still uses only the cache prefix, site, language, path, and timezone rather than the header values.