GHSA-gwfr-jfjf-92vv
Grav has Insecure Deserialization in File Cache
Quick fix
GHSA-gwfr-jfjf-92vv — getgrav/grav: upgrade to the fixed version with the command below.
composer require getgrav/grav:^2.0.0-beta.2Details
# 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 ```bash 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`](https://github.com/getgrav/grav/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`](https://github.com/getgrav/grav/blob/2.0/system/src/Grav/Framework/Cache/Adapter/FileCache.php). - [`tests/unit/Grav/Common/Security/FileCacheSecurityTest.php`](https://github.com/getgrav/grav/blob/2.0/tests/unit/Grav/Common/Security/FileCacheSecurityTest.php) — round-trip, tampered-payload rejection, wrong-key forgery rejection, pre-v2 file rebuild, key-field mismatch.
Are you affected?
Enter the version of the package you're using.
Affected packages
0Fixed in: 2.0.0-beta.2composer require getgrav/grav:^2.0.0-beta.2References
- https://github.com/getgrav/grav/security/advisories/GHSA-gwfr-jfjf-92vv[WEB]
- https://nvd.nist.gov/vuln/detail/CVE-2026-7317[ADVISORY]
- https://github.com/getgrav/grav/commit/5a12f9be8314682c8713e569e330f11805d0a663[WEB]
- https://github.com/getgrav/grav/commit/c66dfeb5f[WEB]
- https://github.com/devsamuelsantiago/grav-cms-filecache-object-injection[WEB]
- https://github.com/getgrav/grav[PACKAGE]
- https://vuldb.com/submit/798732[WEB]
- https://vuldb.com/vuln/359965[WEB]
- https://vuldb.com/vuln/359965/cti[WEB]