CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-74907

CVE-2026-74907: Directory Traversal in Grav CMS Pre-Boot Static Asset Server

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 18, 2026·7 min read·25 visits

Executive Summary (TL;DR)

An insecure string containment check in Grav's pre-boot asset server allows unauthenticated remote attackers to read files in sibling directories via path traversal.

An unauthenticated directory traversal vulnerability exists in Grav CMS prior to version 2.0.15. Due to an insecure string-based containment check (str_starts_with) in the pre-boot static asset server, attackers can read files in sibling directories sharing a prefix with the configured asset path when plugin-asset-map.php is enabled.

Vulnerability Overview

CVE-2026-74907 is a directory traversal vulnerability discovered in Grav, an open-source flat-file Content Management System (CMS). The vulnerability is situated within the pre-boot static asset serving routine implemented in the primary index.php routing file. This component bypasses the core application initialization cycle to quickly deliver static files registered in an optional configuration.

Because this pre-boot server operates before the core access control libraries of the CMS are fully instantiated, any routing flaw within it exposed a wide attack surface. The root cause is identified as an insecure string containment check (CWE-22) that fails to validate directory-level boundaries when resolving client paths. Unauthenticated attackers can leverage this defect to read arbitrary files from sibling folders that share a base prefix with the configured asset directory.

To be reachable, the vulnerable code path requires a specific, non-default configuration: the presence of an active asset map profile. If this asset map is present, any remote user can target the pre-boot route without prior authentication. The security impact is confined to unauthorized information exposure on the hosting file system.

Root Cause Analysis

The vulnerability stems from a logical design flaw where string-based prefix matching is substituted for filesystem boundary verification. When serving static assets, the pre-boot server resolves the absolute file path using the absolute base path on disk. To verify that the requested file resides inside the allowed directory, the code performs a verification using the PHP built-in str_starts_with function.

The string check was written as str_starts_with($realFile, $realBase). Because this check operates strictly on arbitrary characters and is not directory-aware, it treats folder delimiters as normal characters. Consequently, any directory that begins with the exact characters of the base path will satisfy the condition and bypass the containment boundary.

Consider a configuration where the legitimate base path resolves to /var/www/html/grav/assets and an attacker requests a resource residing in /var/www/html/grav/assets-secret/credentials.txt. The string comparison will evaluate /var/www/html/grav/assets-secret/credentials.txt against /var/www/html/grav/assets. Because the characters align sequentially, the check returns true, incorrectly treating a distinct sibling directory as a subdirectory of the allowed asset directory.

Code Analysis

The pre-boot asset verification logic in Grav versions prior to 2.0.15 was structured to evaluate input paths as follows:

// Vulnerable routing block in index.php
$filePath = __DIR__ . '/' . ltrim($diskPath, '/') . $relPath;
$realFile = realpath($filePath);
$realBase = realpath(__DIR__ . '/' . ltrim($diskPath, '/'));
 
if ($realFile && $realBase && str_starts_with($realFile, $realBase) && is_file($realFile)) {
    // Serve the file directly
}

In this logic, the code retrieves the relative request path and appends it to the base directory path before passing it to realpath(). The function realpath() resolves all symbolic links, relative references, and directory traversal sequences (..). However, if the canonicalized path of a sibling directory starts with the same string prefix as $realBase, the execution bypasses the boundary constraint.

The official fix in version 2.0.15 resolves this issue by ensuring that the base comparison string terminates on a system-defined directory boundary. This is achieved by stripping any existing trailing slashes and appending a single DIRECTORY_SEPARATOR to the base path comparison string:

// Patched logic in index.php (Grav >= 2.0.15)
$filePath = __DIR__ . '/' . ltrim($diskPath, '/') . $relPath;
$realFile = realpath($filePath);
$realBase = realpath(__DIR__ . '/' . ltrim($diskPath, '/'));
 
// Containment has to end on a directory boundary. A bare
// prefix test also accepts any sibling whose name merely
// extends the base one.
$inBase = $realFile && $realBase
    && str_starts_with($realFile, rtrim($realBase, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR);
if ($inBase && is_file($realFile)) {
    $ext = strtolower(pathinfo($realFile, PATHINFO_EXTENSION));
    // Serve file safely
}

By converting the base path to /var/www/html/grav/assets/ on Unix-like environments, a request traversing into /var/www/html/grav/assets-secret/credentials.txt will fail the validation because the character at the index of the trailing slash is - instead of /. This patch provides robust and complete mitigation against sibling-prefix directory traversal attacks.

Exploitation Methodology

To successfully exploit CVE-2026-74907, an attacker must identify a Grav target where the optional static asset-mapping configuration file user/config/plugin-asset-map.php is active. When this file exists, the static asset handler in index.php is executed for matching request prefixes, allowing path validation checks to run.

An attacker begins by scanning for common sibling directories that share a suffix or prefix string on the server's filesystem, such as assets-secure, assets-secret, or assets-backup. Once a potential target directory is identified, the attacker crafts a raw HTTP GET request to the index route containing traversal sequences within the query string mapping parameters.

GET /index.php?_url=../assets-secret/keys.json HTTP/1.1
Host: target-grav-instance.local
Accept: */*
Connection: close

During execution, the server combines the relative path input with the default directory path. When realpath() normalizes the path, the traversal sequence resolves to the sibling folder assets-secret. The comparison check evaluates the path and returns true because the absolute target path starts with the literal characters of the base directory. The web application then processes the file and sends its contents back to the requester in the HTTP response body.

Impact Assessment

The severity of CVE-2026-74907 is limited to the disclosure of sensitive files (Confidentiality). Because the affected asset-serving logic only reads files from the disk and lacks write or delete routines, an attacker cannot modify files (Integrity) or execute code directly on the target machine (Availability).

The CVSS v3.1 base score is 5.9 (Medium), indicating a conditional exploit path. The Attack Complexity is rated as High because the attack requires a specific prerequisite configuration file to be populated and the target files must reside in a sibling directory with a name extending the base path prefix. If these environments exist, the exploitation does not require authentication or user interaction.

If sensitive data such as system configuration backups, credential store files, or development environments are maintained within the targeted prefix-sharing folders, the impact can escalate. Attackers can leverage leaked API keys or database credentials to conduct lateral movement. Current threat intelligence (EPSS score 0.00333) suggests low active utilization in automated exploitation campaigns.

Remediation and Mitigation

The definitive remediation is to upgrade Grav to version 2.0.15 or later. The security update patches the routing check in index.php to guarantee directory boundary checks. Administrators must ensure that the core file index.php is replaced during the update and that local modifications do not override the patch.

If an immediate upgrade is not feasible, administrators can apply a manual hotfix. Locate the vulnerability block in the root index.php file and modify the validation logic to enforce directory-level checks using the DIRECTORY_SEPARATOR constant as shown in the patch code analysis. Clear the server's cache after applying the patch to enforce the new validation logic.

If the asset mapping feature is not required for production services, the vulnerability can be mitigated by disabling the configuration. Delete or rename the configuration file located at user/config/plugin-asset-map.php. Removing this file prevents the application from entering the vulnerable pre-boot asset handler, bypassing the vulnerable code path entirely.

Official Patches

getgravOfficial Git Patch file fixing path traversal boundary verification

Fix Analysis (1)

Technical Appendix

CVSS Score
5.9/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
EPSS Probability
0.33%
Top 73% most exploited

Affected Systems

Grav CMS

Affected Versions Detail

Product
Affected Versions
Fixed Version
Grav
getgrav
< 2.0.152.0.15
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork (AV:N)
CVSS v3.1 Score5.9 (Medium)
EPSS Score0.00333 (Percentile: 26.56%)
ImpactConfidentiality (High)
Exploit StatusProof of Concept / Conceptual
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1083File and Directory Discovery
Discovery
T1005Data from Local System
Collection
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The application uses path components without properly validating that they resolve to directories within the intended base path, allowing string containment bypasses.

Vulnerability Timeline

Vendor release 2.0.15 and patch details published
2026-08-03
GitHub Security Advisory GHSA-4v9q-p283-qc2m disclosed
2026-08-03

References & Sources

  • [1]GitHub Security Advisory GHSA-4v9q-p283-qc2m
  • [2]NVD Vulnerability Details for CVE-2026-74907
  • [3]VulnCheck Security Advisory
  • [4]Official Commit Patch

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-118777
4.8

CVE-2026-118777: Prototype Pollution in Forge HTTP Client Cookie Management

CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.

Amit Schendel
Amit Schendel
7 views•10 min read
•1 day ago•CVE-2026-118775
3.7

CVE-2026-118775: ASN.1 OID First Arc Truncation and Ambiguity in node-forge

CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.

Amit Schendel
Amit Schendel
8 views•10 min read
•1 day ago•CVE-2026-119194
7.5

CVE-2026-119194: Algorithmic Complexity Denial of Service in pyasn1 Schemaless ASN.1 Decoder

CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).

Alon Barad
Alon Barad
7 views•9 min read
•1 day ago•CVE-2026-119195
7.5

CVE-2026-119195: Quadratic-Time Denial of Service in pyasn1 BER/CER/DER Decoders

CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.

Amit Schendel
Amit Schendel
8 views•10 min read
•1 day ago•CVE-2026-119197
7.5

CVE-2026-119197: Quadratic Algorithmic Complexity Denial of Service in pyasn1 REAL Mantissa Decoder

An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.

Amit Schendel
Amit Schendel
7 views•10 min read
•1 day ago•CVE-2026-119196
7.5

CVE-2026-119196: Quadratic CPU Consumption in pyasn1 Constructed BIT STRING Decoding

A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.

Alon Barad
Alon Barad
8 views•10 min read