Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐘 Packagist

GHSA-gwfr-jfjf-92vv

MEDIUMFix: getgrav/grav@5a12f9b

GHSA-gwfr-jfjf-92vv is a medium-severity (CVSS 5) Improper Input Validation vulnerability in getgrav/grav. O3 Security confirms whether GHSA-gwfr-jfjf-92vv is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

Grav has Insecure Deserialization in File Cache

Also known asCVE-2026-7317
Published
May 5, 2026
Updated
May 8, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed

Real-World Exposure

1 pkg affected
🐘getgrav/grav

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.

Description

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:

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐘Packagistgetgrav/gravall versions2.0.0-beta.2

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for getgrav/grav. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update getgrav/grav to 2.0.0-beta.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-gwfr-jfjf-92vv is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-gwfr-jfjf-92vv is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-gwfr-jfjf-92vv. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

# 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 ins
O3 Security · Impact-Aware SCA

Is GHSA-gwfr-jfjf-92vv in your dependencies?

O3 detects GHSA-gwfr-jfjf-92vv across Packagist dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.