Grav before 2.0.4 ships a default .htaccess (and reference webserver-configs/htaccess.txt) whose rules blocking access to sensitive file…
[email protected]·CWE-178·Published 2026-07-17
Grav before 2.0.4 ships a default .htaccess (and reference webserver-configs/htaccess.txt) whose rules blocking access to sensitive file types (.yaml, .php, .json, etc.) lack the [NC] flag, making extension matching case-sensitive. On case-insensitive filesystems (Windows/NTFS, macOS/HFS+, or Docker volume mounts), an unauthenticated attacker can request these files with uppercase or mixed-case extensions (e.g., .YAML, .PHP) to bypass the restrictions and read sensitive configuration files that may contain API keys and credentials.
Grav before 2.0.4 ships a default .htaccess (and reference webserver-configs/htaccess.txt) whose rules blocking access to sensitive file types (.yaml, .php, .json, etc.) lack the [NC] flag, making extension matching case-sensitive. On case-insensitive filesystems (Windows/NTFS, macOS/HFS+, or Docker volume mounts), an unauthenticated attacker can request these files with uppercase or mixed-case extensions (e.g., .YAML, .PHP) to bypass the restrictions and read sensitive configuration files that may contain API keys and credentials.
## Summary The default `.htaccess` shipped with Grav (and the reference `webserver-configs/htaccess.txt`) contains security rules that block direct HTTP access to sensitive file types (`.yaml`, `.yml`, `.php`, `.json`, `.twig`, etc.) under `user/` and `system/vendor/` directories. However, these rules lack the `[NC]` (No Case) flag, making them case-sensitive. On case-insensitive filesystems (Windows/NTFS, macOS/HFS+, or Linux with Docker volumes mounted from Windows/macOS), an attacker can bypass these rules by requesting files with uppercase extensions (e.g., `.YAML`, `.PHP`, `.JSON`). ## Affected Versions - Grav 2.0.1 (latest stable as of June 2026) — confirmed - Grav 1.7.x — likely affected (same `.htaccess` rules) - All versions shipping the current `webserver-configs/htaccess.txt` ## Affected Component File: `.htaccess` (root of Grav installation) Reference: `webserver-configs/htaccess.txt` ## Affected Rules (lines 68, 70, 72) ```apache # Line 68 — system/vendor file types RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$ error [F] # Line 70 — user file types RewriteRule ^(user)/(.*)\.(txt|md|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$ error [F] # Line 72 — .md files globally RewriteRule \.md$ error [F] ``` All three rules use `[F]` without `[NC]`, making the extension match case-sensitive. ## Steps to Reproduce 1. Install Grav on a system with a case-insensitive filesystem: - Windows (native WAMP/XAMPP) - macOS (default HFS+) - Docker on Windows/macOS with volume mounts (e.g., `./data:/var/www/html`) 2. Create or use any plugin that stores sensitive data in its YAML config (e.g., API keys): ``` user/plugins/my-plugin/my-plugin.yaml ``` 3. Request the file with a case-varied extension: ``` GET /user/plugins/my-plugin/my-plugin.YAML HTTP/1.1 ``` 4. **Expected**: HTTP 403 Forbidden 5. **Actual**: HTTP 200 OK — full file contents returned, including any API keys or sensitive configuration ## Impact - **Information disclosure**: Plugin configuration files (`.yaml`) containing API keys, credentials, or sensitive settings can be read by unauthenticated users - **Source code exposure**: PHP source files can be downloaded (instead of executed) when requested with `.PHP` extension on some configurations - **Configuration exposure**: `user/config/system.yaml`, `user/config/site.yaml`, and other system configuration files are accessible ## Fix Add the `[NC]` flag to the three affected rules: ```apache RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$ error [F,NC] RewriteRule ^(user)/(.*)\.(txt|md|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$ error [F,NC] RewriteRule \.md$ error [F,NC] ``` The `[NC]` flag makes the extension matching case-insensitive, covering `.YAML`, `.Yaml`, `.PHP`, `.Json`, etc. ## Mitigating Factors - On native Linux with ext4 filesystem (case-sensitive), the attack does not work because Apache cannot resolve the uppercase filename to the actual file - Grav 2.0's Twig sandbox blocks access to `plugins` config subtree from page content, preventing SSTI-based config exfiltration - The `user/accounts/`, `user/config/`, and `user/data/` folders have separate rules (line 62, 66) that block ALL file types regardless of extension — these are not affected ## Environment - Grav: 2.0.1 - PHP: 8.3 - Apache: 2.4 with mod_rewrite - OS: Docker (php:8.3-apache) with volume mounted from Windows 10 (NTFS) - Tested: June 2026 ## Reporter Sisnetic
| Version | Type | Source | Base | Exp | Impact | Vector |
|---|---|---|---|---|---|---|
| 3.1 | Primary | cve.org | 7.5 | — | — | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Primary | NVD | 7.5 | 3.9 | 3.6 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Secondary | NVD | 7.5 | 3.9 | 3.6 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 4.0 | Primary | cve.org | 8.7 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | ENISA EUVD | 8.7 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | NVD | 8.7 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X |