GHSA-FWJF-M4QW-9F2X

Vulnerability from github – Published: 2026-08-24 20:09 – Updated: 2026-08-24 20:09
VLAI
Summary
django CMS: Page cache ignores plugin-declared Vary headers (disclosure & poisoning)
Details

Summary

The CMS page cache key ignores the request headers that plugins declare via get_vary_cache_on(). 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

_page_cache_key (in cms/cache/page.py) keys only on cache prefix, site, language, path and timezone. set_page_cache collects the plugin-declared vary headers and calls patch_vary_headers(response, ...) (affecting only the emitted Vary header), but stores and retrieves the cached page under the header-agnostic key. get_page_cache 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 CMS_PAGE_CACHE is enabled and at least one plugin implements get_vary_cache_on().

Patches

Fixed in 5.0.8: the page cache now folds the request's values implements get_vary_cache_on().

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 learn_cache_key/get_cache_key); a missing header-list entry degrades to a cache miss, never a wrong-variant hit.

Workarounds

Disable CMS_PAGE_CACHE, or avoid plugins that rely on get_vary_cache_on(), until upgraded.

Credits

Reported by the security team at the University of Sydney ([@reporter]).

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "django-cms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.0.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54625"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-349",
      "CWE-524"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-24T20:09:51Z",
    "nvd_published_at": "2026-08-20T18:16:28Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nThe CMS page cache key ignores the request headers that plugins declare via `get_vary_cache_on()`. The header is added to the response `Vary` header, but the CMS\u0027s own cache key does not incorporate the header values, so the first visitor\u0027s variant is served to all subsequent visitors regardless of their header values.\n\n### Details\n`_page_cache_key` (in `cms/cache/page.py`) keys only on cache prefix, site, language, path and timezone. `set_page_cache` collects the plugin-declared vary headers and calls `patch_vary_headers(response, ...)` (affecting only the emitted `Vary` header), but stores and retrieves the cached page under the header-agnostic key. `get_page_cache` therefore returns whichever variant was cached first.\n\n### Impact\n- **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.\n- **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.\n\nApplies only when `CMS_PAGE_CACHE` is enabled and at least one plugin implements `get_vary_cache_on()`.\n\n### Patches\nFixed in 5.0.8: the page cache now folds the request\u0027s values implements `get_vary_cache_on()`.\n\n### Patches\nFixed in 5.0.8: the page cache now folds the request\u0027s 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\u0027s  `learn_cache_key`/`get_cache_key`); a missing header-list entry degrades to a cache miss, never a wrong-variant hit.\n\n### Workarounds\nDisable `CMS_PAGE_CACHE`, or avoid plugins that rely on `get_vary_cache_on()`, until upgraded.\n\n### Credits\nReported by the security team at the University of Sydney ([@reporter]).",
  "id": "GHSA-fwjf-m4qw-9f2x",
  "modified": "2026-08-24T20:09:52Z",
  "published": "2026-08-24T20:09:51Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/security/advisories/GHSA-fwjf-m4qw-9f2x"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54625"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/pull/8646"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/pull/8647"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/commit/8758714b865ffa79c6bcd0e5c503958ea48885aa"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/commit/d5dc1efa18d157445491c4b12c2dd1efd56f439f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/django-cms/django-cms"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/releases/tag/5.0.8"
    },
    {
      "type": "WEB",
      "url": "https://github.com/django-cms/django-cms/releases/tag/5.1.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "django CMS: Page cache ignores plugin-declared Vary headers (disclosure \u0026 poisoning)"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…