Downloads
Everything Grav
Download Grav
Grav Core is the base package with core functionality and a few essential starting pages. Grav Core + Admin also includes the Administration Panel plugin. Both are easy to get started with — check out our Basic Tutorial and Guide to the Administration Panel.
Latest stable release
Production-ready. The version we recommend for every new site and every upgrade of an existing one.
Get Started
1
Quick installation
- Download either the Grav Core or Grav Core + Admin2 plugin installation package.
- Extract the zip file into your webroot.
- Point your browser at your local webserver:
http://yoursite.com
2
How to install the Admin2 plugin
If you have not already installed the admin plugin, you can do so easily with GPM:
$
This will install the admin plugin plus its dependencies (api & login). After this is complete, point your browser to your Grav installation and you will be prompted to create a new admin user.
Changelog
v2.0.19
Latest
10 hours ago
-
- You can now tighten the Twig content sandbox below its built-in defaults with new
denied_*settings insecurity.yaml. - The "Twig in Content" report can show the effective sandbox policy, so you can see exactly what page content is allowed to do.
- You can now tighten the Twig content sandbox below its built-in defaults with new
-
- A theme or plugin that ships its own
.htaccesscan no longer switch off the protection on its own folder, which used to leave its configuration and template files downloadable #4236 - Twig in page content now renders on new installs by default, instead of appearing as raw text until the setting was turned on.
- The long Twig sandbox allowlists now ship built into Grav, so
security.yamlonly records your own additions and future security updates to the defaults reach every site. - Existing sites that had trimmed those allowlists to tighten them keep exactly that policy after upgrading, now recorded as explicit
denied_*entries. - Removed two rarely-used Twig sandbox switches (
loggingandadmin_hint); both behaviours are now always on.
- A theme or plugin that ships its own
-
- The content cross-site scripting check no longer objects to harmless
<option>and<select>markup, whose original issue is fixed in the form field that actually rendered it. - Sites running with the Twig 2 compatibility setting no longer crash with a server error on every page once an update clears the template cache #4235
- The content cross-site scripting check no longer objects to harmless
v2.0.18 4 days ago
-
- [security] Updated the bundled DOM sanitizer to 1.0.14, which closes two further ways a crafted stylesheet could hide an external image reference from the checks added in the previous release (GHSA-ww22-4mqv-x5w3).
- [security] Modular pages are now checked for cross-site scripting when they are saved, closing a way for a page editor to store a script that ran for every visitor (GHSA-fg8g-663r-f366).
- [security] The Twig
sortandfindfilters no longer run a plain function name as a callable inside the content sandbox, closing a way for a page editor to execute arbitrary PHP (GHSA-p6qj-p5m7-f62h). - A blueprint that builds on another one can again fill dropdowns from its own PHP, which mostly affected themes because their page blueprints nearly always extend the default one (getgrav/grav-plugin-email#193).
- The Scheduler no longer fails outright on hosts that disable PHP's
proc_open, so scheduled jobs can still be viewed and edited there getgrav/grav-admin-next#16 - A scheduled job that cannot be started on such a host is now reported as failed with an explanation, instead of stopping the whole scheduler run
- Grav now works out who the site runs as without starting a shell, so that detail still appears when external commands are unavailable
- The record of when the scheduler last ran is now written to a fixed location rather than one relative to wherever the trigger happened to run from
-
- Grav now decides whether the scheduler is being triggered by checking that each job has run when its own schedule says it should have, instead of requiring a run in the last two minutes, so a sparse crontab, a webhook or a scheduled task on Windows all count
v2.0.17 1 week ago
-
- [security] Updated the bundled DOM sanitizer to 1.0.13, which stops CSS comments from hiding dangerous values and covers image loading through
image-set(), so untrusted SVG or HTML can no longer reference external resources those ways (GHSA-ww22-4mqv-x5w3).
- [security] Updated the bundled DOM sanitizer to 1.0.13, which stops CSS comments from hiding dangerous values and covers image loading through
v2.0.16 1 week ago
-
- Updated vendor libs to latest versions
- The list of groups on the account form is now read through the current user groups system, retiring a routine deprecated since Grav 1.7.
-
- [security] The site, system and theme settings offered to Twig written inside page content are now filtered by the same denied-paths list that already covered
config, so a page editor can no longer read secrets such as a Redis password straight out of them (GHSA-p597-crqc-m349). - [security] Twig written into a form's email settings now runs under the same restrictions as Twig written into page content, closing a route that let someone with only page-editing rights run commands on the server (GHSA-gh8j-q67c-j53f).
- [security] Form security tokens are now compared with a routine that takes the same amount of time whichever characters differ, so the check can no longer hint at how much of a guess was right (GHSA-38p6-h87p-r4cg).
- [security] The check for whether a visitor arrived from your own site now requires a full address match, so another site whose domain merely begins with yours no longer counts as your own (GHSA-9ccq-2jfg-qw33).
- [security] Scheduler job locks are now kept inside your site rather than in the shared system temp folder, so another account on the same server can no longer redirect a lock write to a file of its choosing (GHSA-q8w8-6cq5-j4h2).
- A scheduled job set to run only one at a time now refuses to start when its lock cannot be written, instead of running unprotected. Note that
bin/grav clearremoves these locks along with the rest of the temporary folder. - [security] Deleting, renaming and copying a media file now check the whole path rather than just the file's own name, so a plugin calling those routines directly cannot reach a file outside the media folder (GHSA-jq29-c7v8-rg55).
- [security] The
media_directory()Twig function now only accepts folders inside your site, so Twig written into page content can no longer list files or republish images from elsewhere on the server (GHSA-47ch-6w46-6xm7). - Deleting a media file no longer also removes the retina copies and metadata belonging to a different file whose name merely ends with the same text, so deleting
banner.jpgleaves[email protected]alone. - A fallback page handed to
Uri::referrer()is now returned as given, instead of being trimmed away to nothing whenever the visitor did not arrive from your site. Pages::referrerRoute()was comparing a full web address against a site path, so it never recognised a match and always reported that the visitor came from somewhere else.
- [security] The site, system and theme settings offered to Twig written inside page content are now filtered by the same denied-paths list that already covered
v2.0.15 2 weeks ago
-
- A plugin's blueprints can use the data providers that plugin ships again, instead of having every one of them refused by a check that only recognised the providers core itself registers (getgrav/grav-plugin-email#193). Fields defined in page frontmatter are held to the stricter rule instead, which is where the risk actually was.
- [security] A configuration admin can no longer reach an unvetted built-in routine by writing a blueprint field's data provider as a plain function name, a spelling that was still being checked against a list of known-bad names rather than the list of approved ones (GHSA-f8wv-xp27-6gq7).
- [security] The content security scan now reads an unpaired quote inside an unquoted attribute value the way a browser does, closing another way a page editor could hide a script from it (GHSA-vfmf-q6x9-cw96).
- [security] The media URL in an audio or video tag is now escaped, so a filename carrying markup can no longer add its own attributes to the player (GHSA-6qw9-4vv5-jr97).
- JSON responses no longer fail outright when the data contains invalid UTF-8.
json_encode()returnsfalseon malformed bytes, and the PSR-7 response body is type-hintedstring|resource|StreamInterface, so thatfalsecame back out as an unhandledTypeErrorfrom inside the vendor stream rather than as a response. AffectedcreateJsonResponse()and both JSON error responses inControllerResponseTrait, where an exception message carrying a bad byte would take out the error handler itself, plus the Clockwork data endpoint inDebugger. Bad bytes are now substituted, and the remaining structural failures (recursion depth,INF/NAN) raise a catchableJsonExceptioninstead of a silentfalse. Output for valid data is unchanged. - [security] The fast static asset server now keeps a request inside the directory the site published, instead of also allowing any neighbouring directory whose name starts with the same letters (GHSA-4v9q-p283-qc2m).
- [security] File uploads now reject a few more extensions that browsers run script from, or that a server may hand to PHP:
xhtml,xht,svgz,php7,php8,pht,phtmandphps(GHSA-66xf-ggf4-6hmc). - [security] The bundled
Caddyfileprotections did nothing. They were written as nginx-style regexes, which Caddy reads as literal paths that never match, and therespondthey redirected to ran after the catch-all rewrite had already claimed the request. A site served with this config handed outuser/accounts/,user/config/,logs/,composer.lock, page files, and thesystem/andvendor/folders to anyone who asked. The rules are now namedpath_regexpmatchers answering403directly, inside arouteblock so they run before the rewrite, and they were checked request by request against the.htaccessbehaviour.
v2.0.14 2 weeks ago
-
- Removed old JQuery
2.1.4. However2.2.4and3.7.1remain for legacy support
- Removed old JQuery
-
- [security] An administrator with account-management rights can no longer grant themselves super-admin access by saving it into a user group's permissions, a protection the account form already had (GHSA-xhfv-7758-r9hx).
- [security] The content security scan no longer reports a page as clean when it was unable to examine it, closing two ways a page editor could hide a script from it: a single invalid character anywhere in the content, and padding a tag out to several thousand characters (GHSA-q2j8-x8hf-63ch).
v2.0.19
Latest
10 hours ago
-
- You can now tighten the Twig content sandbox below its built-in defaults with new
denied_*settings insecurity.yaml. - The "Twig in Content" report can show the effective sandbox policy, so you can see exactly what page content is allowed to do.
- You can now tighten the Twig content sandbox below its built-in defaults with new
-
- A theme or plugin that ships its own
.htaccesscan no longer switch off the protection on its own folder, which used to leave its configuration and template files downloadable #4236 - Twig in page content now renders on new installs by default, instead of appearing as raw text until the setting was turned on.
- The long Twig sandbox allowlists now ship built into Grav, so
security.yamlonly records your own additions and future security updates to the defaults reach every site. - Existing sites that had trimmed those allowlists to tighten them keep exactly that policy after upgrading, now recorded as explicit
denied_*entries. - Removed two rarely-used Twig sandbox switches (
loggingandadmin_hint); both behaviours are now always on.
- A theme or plugin that ships its own
-
- The content cross-site scripting check no longer objects to harmless
<option>and<select>markup, whose original issue is fixed in the form field that actually rendered it. - Sites running with the Twig 2 compatibility setting no longer crash with a server error on every page once an update clears the template cache #4235
- The content cross-site scripting check no longer objects to harmless
v2.0.18 4 days ago
-
- [security] Updated the bundled DOM sanitizer to 1.0.14, which closes two further ways a crafted stylesheet could hide an external image reference from the checks added in the previous release (GHSA-ww22-4mqv-x5w3).
- [security] Modular pages are now checked for cross-site scripting when they are saved, closing a way for a page editor to store a script that ran for every visitor (GHSA-fg8g-663r-f366).
- [security] The Twig
sortandfindfilters no longer run a plain function name as a callable inside the content sandbox, closing a way for a page editor to execute arbitrary PHP (GHSA-p6qj-p5m7-f62h). - A blueprint that builds on another one can again fill dropdowns from its own PHP, which mostly affected themes because their page blueprints nearly always extend the default one (getgrav/grav-plugin-email#193).
- The Scheduler no longer fails outright on hosts that disable PHP's
proc_open, so scheduled jobs can still be viewed and edited there getgrav/grav-admin-next#16 - A scheduled job that cannot be started on such a host is now reported as failed with an explanation, instead of stopping the whole scheduler run
- Grav now works out who the site runs as without starting a shell, so that detail still appears when external commands are unavailable
- The record of when the scheduler last ran is now written to a fixed location rather than one relative to wherever the trigger happened to run from
-
- Grav now decides whether the scheduler is being triggered by checking that each job has run when its own schedule says it should have, instead of requiring a run in the last two minutes, so a sparse crontab, a webhook or a scheduled task on Windows all count
v2.0.17 1 week ago
-
- [security] Updated the bundled DOM sanitizer to 1.0.13, which stops CSS comments from hiding dangerous values and covers image loading through
image-set(), so untrusted SVG or HTML can no longer reference external resources those ways (GHSA-ww22-4mqv-x5w3).
- [security] Updated the bundled DOM sanitizer to 1.0.13, which stops CSS comments from hiding dangerous values and covers image loading through
v2.0.16 1 week ago
-
- Updated vendor libs to latest versions
- The list of groups on the account form is now read through the current user groups system, retiring a routine deprecated since Grav 1.7.
-
- [security] The site, system and theme settings offered to Twig written inside page content are now filtered by the same denied-paths list that already covered
config, so a page editor can no longer read secrets such as a Redis password straight out of them (GHSA-p597-crqc-m349). - [security] Twig written into a form's email settings now runs under the same restrictions as Twig written into page content, closing a route that let someone with only page-editing rights run commands on the server (GHSA-gh8j-q67c-j53f).
- [security] Form security tokens are now compared with a routine that takes the same amount of time whichever characters differ, so the check can no longer hint at how much of a guess was right (GHSA-38p6-h87p-r4cg).
- [security] The check for whether a visitor arrived from your own site now requires a full address match, so another site whose domain merely begins with yours no longer counts as your own (GHSA-9ccq-2jfg-qw33).
- [security] Scheduler job locks are now kept inside your site rather than in the shared system temp folder, so another account on the same server can no longer redirect a lock write to a file of its choosing (GHSA-q8w8-6cq5-j4h2).
- A scheduled job set to run only one at a time now refuses to start when its lock cannot be written, instead of running unprotected. Note that
bin/grav clearremoves these locks along with the rest of the temporary folder. - [security] Deleting, renaming and copying a media file now check the whole path rather than just the file's own name, so a plugin calling those routines directly cannot reach a file outside the media folder (GHSA-jq29-c7v8-rg55).
- [security] The
media_directory()Twig function now only accepts folders inside your site, so Twig written into page content can no longer list files or republish images from elsewhere on the server (GHSA-47ch-6w46-6xm7). - Deleting a media file no longer also removes the retina copies and metadata belonging to a different file whose name merely ends with the same text, so deleting
banner.jpgleaves[email protected]alone. - A fallback page handed to
Uri::referrer()is now returned as given, instead of being trimmed away to nothing whenever the visitor did not arrive from your site. Pages::referrerRoute()was comparing a full web address against a site path, so it never recognised a match and always reported that the visitor came from somewhere else.
- [security] The site, system and theme settings offered to Twig written inside page content are now filtered by the same denied-paths list that already covered
v2.0.15 2 weeks ago
-
- A plugin's blueprints can use the data providers that plugin ships again, instead of having every one of them refused by a check that only recognised the providers core itself registers (getgrav/grav-plugin-email#193). Fields defined in page frontmatter are held to the stricter rule instead, which is where the risk actually was.
- [security] A configuration admin can no longer reach an unvetted built-in routine by writing a blueprint field's data provider as a plain function name, a spelling that was still being checked against a list of known-bad names rather than the list of approved ones (GHSA-f8wv-xp27-6gq7).
- [security] The content security scan now reads an unpaired quote inside an unquoted attribute value the way a browser does, closing another way a page editor could hide a script from it (GHSA-vfmf-q6x9-cw96).
- [security] The media URL in an audio or video tag is now escaped, so a filename carrying markup can no longer add its own attributes to the player (GHSA-6qw9-4vv5-jr97).
- JSON responses no longer fail outright when the data contains invalid UTF-8.
json_encode()returnsfalseon malformed bytes, and the PSR-7 response body is type-hintedstring|resource|StreamInterface, so thatfalsecame back out as an unhandledTypeErrorfrom inside the vendor stream rather than as a response. AffectedcreateJsonResponse()and both JSON error responses inControllerResponseTrait, where an exception message carrying a bad byte would take out the error handler itself, plus the Clockwork data endpoint inDebugger. Bad bytes are now substituted, and the remaining structural failures (recursion depth,INF/NAN) raise a catchableJsonExceptioninstead of a silentfalse. Output for valid data is unchanged. - [security] The fast static asset server now keeps a request inside the directory the site published, instead of also allowing any neighbouring directory whose name starts with the same letters (GHSA-4v9q-p283-qc2m).
- [security] File uploads now reject a few more extensions that browsers run script from, or that a server may hand to PHP:
xhtml,xht,svgz,php7,php8,pht,phtmandphps(GHSA-66xf-ggf4-6hmc). - [security] The bundled
Caddyfileprotections did nothing. They were written as nginx-style regexes, which Caddy reads as literal paths that never match, and therespondthey redirected to ran after the catch-all rewrite had already claimed the request. A site served with this config handed outuser/accounts/,user/config/,logs/,composer.lock, page files, and thesystem/andvendor/folders to anyone who asked. The rules are now namedpath_regexpmatchers answering403directly, inside arouteblock so they run before the rewrite, and they were checked request by request against the.htaccessbehaviour.
v2.0.14 2 weeks ago
-
- Removed old JQuery
2.1.4. However2.2.4and3.7.1remain for legacy support
- Removed old JQuery
-
- [security] An administrator with account-management rights can no longer grant themselves super-admin access by saving it into a user group's permissions, a protection the account form already had (GHSA-xhfv-7758-r9hx).
- [security] The content security scan no longer reports a page as clean when it was unable to examine it, closing two ways a page editor could hide a script from it: a single invalid character anywhere in the content, and padding a tag out to several thousand characters (GHSA-q2j8-x8hf-63ch).