/

CVE-2026-69089

Severity:

HIGH RISK

(7.5)

Path Traversal (CWE-22) in Grav CMS Image Watermarking

CVE-2026-69089

Deferred

Vulnerability type

Category:

Path Traversal

CWE:

CWE-22

Impact:

Unauthorized File Disclosure

Severity:

HIGH RISK

(7.5)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

A path traversal flaw in Grav CMS's image watermarking logic allows crafted image paths to reach a resource locator without adequate containment checks.

When an editor embeds Markdown image tags containing traversal sequences, arbitrary image files outside the media sandbox can be composited and then exposed via public, unauthenticated URLs.

Affected context

This vulnerability appears in Grav CMS deployments where user-supplied image paths in Markdown content are processed by the ImageMedium::watermark() functionality.

The issue primarily affects environments that allow editors or content authors to control image URLs and where the resource locator's file:// handling only collapses .. segments lexically, without realpath-based containment checks against the intended media directory.

Under these conditions, traversal sequences in image paths can escape the media sandbox and reach arbitrary files readable by the Grav process.

Exploit preconditions

  • Attack surface: Web-facing content authoring interfaces that accept Markdown with image syntax.
  • Required access: Ability to create or modify content containing image references (e.g., editor-level access to Grav pages or posts).
  • Trigger point: Rendering of a page where the vulnerable watermarking routine processes the attacker-controlled image path through findResource() using the file:// scheme.
  • Why exploitation is possible: The resource locator collapses .. segments lexically but does not perform a realpath or directory containment check, allowing paths that escape the intended media directory to be treated as valid resources and subsequently cached and served publicly.

Why this happens

The underlying flaw is improper validation of path-like input before resource resolution, mapping directly to CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

The image watermarking routine forwards an unsanitized $image argument to a resource locator that, for file:// URLs, only performs lexical cleanup of .. segments instead of computing the canonical filesystem path and enforcing that it remains inside the configured media sandbox.

Because the code trusts this normalized path and does not perform containment checks or enforce an allowlist of permitted directories, attacker-controlled traversal sequences can escape the sandbox and cause arbitrary readable files to be loaded into image operations.

Potential impact

  • Disclosure of arbitrary image files readable by the Grav CMS process.
  • Exposure of internal assets such as design comps, internal diagrams, or non-public marketing materials.
  • Potential leakage of screenshots or image exports containing sensitive information.
  • Increased reconnaissance capability for attackers by revealing directory layout and file names through exposed images.

General mitigation guidance

Effective mitigation focuses on enforcing strict directory containment for any path used in media or resource loading.

Typical defensive patterns include:

  • Performing canonicalization (e.g., via realpath) on incoming filesystem paths and verifying they remain within a configured media root or sandbox directory.
  • Rejecting or stripping traversal sequences and disallowing arbitrary file:// references when processing user-controlled image paths.
  • Implementing an explicit allowlist of media directories and refusing resources that resolve outside these boundaries.
  • Ensuring that any caching or public serving layer only exposes files from vetted, controlled media locations and never from the broader filesystem.

How teams detect issues like this

Teams can detect similar path traversal risks through:

  • Static analysis rules that flag use of user-controlled path parameters passed into resource locators, file I/O functions, or URL schemes without containment checks.
  • Code review practices that look for normalization-only handling of .. segments instead of canonical path validation and directory boundary enforcement.
  • Security policies requiring that all media and resource resolution routines apply sandboxing logic and do not accept raw filesystem paths from content.
  • Automated scanning tools configured to attempt traversal sequences in image and media URLs and verify whether unexpected files become accessible via public endpoints.

Sources

SourceLink
github.comgithub.com/getgrav/grav/commit/b282200a65ce979377963180629babd2335212ba
github.comgithub.com/getgrav/grav/commit/c569a53304cd7d95ff21bffa6fc590adcf0be83d
github.comgithub.com/getgrav/grav/commit/db8c1fcd63aaaf6d6b244bc6b4cfa5f7b96bbc7f
github.comgithub.com/getgrav/grav/security/advisories/GHSA-w3f4-8pj2-599w
vulncheck.comvulncheck.com/advisories/grav-cms-before-path-traversal-via-watermark

Frequently asked

questions

Exploitation is limited to contexts where an attacker has the ability to author or edit content containing image references, such as an editor account in Grav. Anonymous visitors cannot directly inject the malicious paths but can later access the exposed images once they are generated.

The attacker typically needs content authoring capabilities—being able to create or modify Markdown that includes image syntax. System-level or shell access is not required; exploitation happens entirely through the CMS's content features.

The safest approach is to canonicalize all file-based image paths and enforce that they stay within a dedicated media root, rejecting any path that resolves outside the sandbox. Combined with strict handling of file:// schemes and traversal sequences, this removes the ability to escape the intended directory.

Future implementations should treat all user-controllable paths as untrusted, apply realpath-based containment checks, and restrict resource loading to explicit, well-defined directories. Incorporating these checks into shared utilities and enforcing them via code review and static analysis policies helps avoid repeating the pattern.

Find out what's already
exploitable in your codebase.