GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-GWFR-JFJF-92VV

Vulnerability from github – Published: 2026-05-05 21:29 – Updated: 2026-05-08 15:36
VLAI
Summary
Grav has Insecure Deserialization in File Cache
Details

Insecure Deserialization in File Cache

  • Severity: High
  • CWE: CWE-502
  • Location: system/src/Grav/Framework/Cache/Adapter/FileCache.php
  • Sink: unserialize($value, ['allowed_classes' => true])

Affected version(s)

  • Affected: >= 1.7.44 and <= 1.7.49.5 (verified in current codebase and changelog-covered releases).
  • Fixed: No upstream fix identified in the reviewed branch at the time of analysis.
  • Notes: Earlier 1.7.x releases may also be affected, but were not fully back-traced in this review.

Notes

allowed_classes => true allows object instantiation and does not constrain classes.

PoC (Primitive Demonstration)

Preconditions

  • Local PHP runtime.
  • Goal is to validate the deserialization primitive used in cache retrieval.

Steps

php -r '
class CacheWakeup { public function __wakeup(){ file_put_contents("/tmp/grav_filecache_poc.txt", "wakeup"); } }

$payload = serialize(new CacheWakeup());
unserialize($payload, ["allowed_classes" => true]);

echo file_exists("/tmp/grav_filecache_poc.txt") ? "FILECACHE_UNSERIALIZE_TRIGGERED\n" : "FILECACHE_UNSERIALIZE_NOT_TRIGGERED\n";
'

Expected Result

  • Output contains: FILECACHE_UNSERIALIZE_TRIGGERED.

Interpretation

This reproduces the same unsafe primitive used by FileCache::doGet(): unserialize($value, ['allowed_classes' => true]). If cache files are attacker-tampered, object magic methods may execute.

Exploit Preconditions

  • Cache file poisoning/tampering capability.

Recommendation

  • Avoid object deserialization in cache payloads.
  • Use non-object formats and integrity protection for cache files.

Maintainer note — fix applied (2026-04-24)

Fixed in Grav core on the 2.0 branch: commit c66dfeb5f — will ship in 2.0.0-beta.2.

What changed: Framework\Cache\Adapter\FileCache now HMAC-signs every cache payload with Security::getNonceKey() on write, and verifies the HMAC on read. Tampered, forged, or pre-upgrade files are treated as cache misses and unlinked instead of being unserialized. The on-disk format is now versioned:

v2
<expires>
<key>
<hmac-hex>
<serialized>

Existing caches rebuild transparently on first read. Note that Framework\Cache\Adapter\FileCache isn't wired into Grav's main cache path — Symfony's FilesystemAdapter is — but the class is reachable by plugin and downstream consumers, so the hardening applies defensively.

Files: - system/src/Grav/Framework/Cache/Adapter/FileCache.php. - tests/unit/Grav/Common/Security/FileCacheSecurityTest.php — round-trip, tampered-payload rejection, wrong-key forgery rejection, pre-v2 file rebuild, key-field mismatch.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "getgrav/grav"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.0.0-beta.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-7317"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-502"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T21:29:29Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "# Insecure Deserialization in File Cache\n\n- **Severity:** High \n- **CWE:** CWE-502\n- **Location:** `system/src/Grav/Framework/Cache/Adapter/FileCache.php`\n- **Sink:** `unserialize($value, [\u0027allowed_classes\u0027 =\u003e true])`\n\n## Affected version(s)\n\n- **Affected:** `\u003e= 1.7.44` and `\u003c= 1.7.49.5` (verified in current codebase and changelog-covered releases).\n- **Fixed:** No upstream fix identified in the reviewed branch at the time of analysis.\n- **Notes:** Earlier `1.7.x` releases may also be affected, but were not fully back-traced in this review.\n\n## Notes\n`allowed_classes =\u003e true` allows object instantiation and does not constrain classes.\n\n## PoC (Primitive Demonstration)\n\n### Preconditions\n- Local PHP runtime.\n- Goal is to validate the deserialization primitive used in cache retrieval.\n\n### Steps\n```bash\nphp -r \u0027\nclass CacheWakeup { public function __wakeup(){ file_put_contents(\"/tmp/grav_filecache_poc.txt\", \"wakeup\"); } }\n\n$payload = serialize(new CacheWakeup());\nunserialize($payload, [\"allowed_classes\" =\u003e true]);\n\necho file_exists(\"/tmp/grav_filecache_poc.txt\") ? \"FILECACHE_UNSERIALIZE_TRIGGERED\\n\" : \"FILECACHE_UNSERIALIZE_NOT_TRIGGERED\\n\";\n\u0027\n```\n\n### Expected Result\n- Output contains: `FILECACHE_UNSERIALIZE_TRIGGERED`.\n\n### Interpretation\nThis reproduces the same unsafe primitive used by `FileCache::doGet()`:\n`unserialize($value, [\u0027allowed_classes\u0027 =\u003e true])`.\nIf cache files are attacker-tampered, object magic methods may execute.\n\n## Exploit Preconditions\n- Cache file poisoning/tampering capability.\n\n## Recommendation\n- Avoid object deserialization in cache payloads.\n- Use non-object formats and integrity protection for cache files.\n\n\n\n---\n\n## Maintainer note \u2014 fix applied (2026-04-24)\n\nFixed in Grav core on the `2.0` branch: commit [`c66dfeb5f`](https://github.com/getgrav/grav/commit/c66dfeb5f) \u2014 will ship in **2.0.0-beta.2**.\n\n**What changed:** `Framework\\Cache\\Adapter\\FileCache` now HMAC-signs every cache payload with `Security::getNonceKey()` on write, and verifies the HMAC on read. Tampered, forged, or pre-upgrade files are treated as cache misses and unlinked instead of being unserialized. The on-disk format is now versioned:\n\n```\nv2\n\u003cexpires\u003e\n\u003ckey\u003e\n\u003chmac-hex\u003e\n\u003cserialized\u003e\n```\n\nExisting caches rebuild transparently on first read. Note that `Framework\\Cache\\Adapter\\FileCache` isn\u0027t wired into Grav\u0027s main cache path \u2014 Symfony\u0027s `FilesystemAdapter` is \u2014 but the class is reachable by plugin and downstream consumers, so the hardening applies defensively.\n\n**Files:**\n- [`system/src/Grav/Framework/Cache/Adapter/FileCache.php`](https://github.com/getgrav/grav/blob/2.0/system/src/Grav/Framework/Cache/Adapter/FileCache.php).\n- [`tests/unit/Grav/Common/Security/FileCacheSecurityTest.php`](https://github.com/getgrav/grav/blob/2.0/tests/unit/Grav/Common/Security/FileCacheSecurityTest.php) \u2014 round-trip, tampered-payload rejection, wrong-key forgery rejection, pre-v2 file rebuild, key-field mismatch.",
  "id": "GHSA-gwfr-jfjf-92vv",
  "modified": "2026-05-08T15:36:36Z",
  "published": "2026-05-05T21:29:29Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/getgrav/grav/security/advisories/GHSA-gwfr-jfjf-92vv"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-7317"
    },
    {
      "type": "WEB",
      "url": "https://github.com/getgrav/grav/commit/5a12f9be8314682c8713e569e330f11805d0a663"
    },
    {
      "type": "WEB",
      "url": "https://github.com/getgrav/grav/commit/c66dfeb5f"
    },
    {
      "type": "WEB",
      "url": "https://github.com/devsamuelsantiago/grav-cms-filecache-object-injection"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/getgrav/grav"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/submit/798732"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/vuln/359965"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/vuln/359965/cti"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Grav has Insecure Deserialization in File Cache"
}



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…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…