Bugfix
- 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. Bad bytes are now substituted, and the remaining structural failures 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. The rules are now namedpath_regexpmatchers answering403directly, inside arouteblock so they run before the rewrite.