getgrav/grav · error · InstallException
Could not remove the retired security.*.xss_scan_output sett
Error message
Could not remove the retired security.*.xss_scan_output settings
What it means
Postflight hook of the Grav 1.8.0 (2026-07-03) update that retires the XSS scan output settings: it removes twig_content.xss_scan_output, content.xss_scan_output and xss_allowed_iframe_hosts from user/config/system.yaml if present, saving only when something actually changed. Any Exception in that undefine/save sequence becomes InstallException 'Could not remove the retired security.*.xss_scan_output settings'. The message slightly over-names the keys — it covers all three retired settings.
Source
Thrown at system/src/Grav/Installer/updates/1.8.0_2026-07-03_0.php:42
'postflight' =>
function () {
/** @var VersionUpdate $this */
try {
$yaml = YamlUpdater::instance(GRAV_ROOT . '/user/config/security.yaml');
$changed = false;
foreach (['twig_content.xss_scan_output', 'content.xss_scan_output', 'xss_allowed_iframe_hosts'] as $key) {
if ($yaml->exists($key)) {
$yaml->undefine($key);
$changed = true;
}
}
if ($changed) {
$yaml->save();
}
} catch (\Exception $e) {
throw new InstallException('Could not remove the retired security.*.xss_scan_output settings', $e);
}
}
];
View on GitHub (pinned to 6040efed04)
Solutions
- Fix write permissions/ownership on user/config/system.yaml and re-run direct-install — removal re-executes cleanly
- Alternatively pre-clean the keys manually: delete twig_content.xss_scan_output, content.xss_scan_output and xss_allowed_iframe_hosts from system.yaml before upgrading
- Inspect the chained previous exception for the exact write/parse failure
Example fix
# before (system.yaml still has retired keys, file not writable)
twig_content:
xss_scan_output: encode
# after — remove the retired block, then re-run the updater
twig_content: { } Defensive patterns
Strategy: try-catch
Validate before calling
// Remove retired keys manually before upgrading to sidestep the postflight write
$file = GRAV_ROOT . '/user/config/system.yaml';
$yaml = \Symfony\Component\Yaml\Yaml::parseFile($file);
foreach (['twig_content', 'content'] as $k) {
if (isset($yaml[$k]['xss_scan_output'])) unset($yaml[$k]['xss_scan_output']);
}
unset($yaml['xss_allowed_iframe_hosts']);
file_put_contents($file, \Symfony\Component\Yaml\Yaml::dump($yaml, 10)); Try / catch
try {
Install::instance()->run();
} catch (InstallException $e) {
if (str_contains($e->getMessage(), 'retired security')) {
// Core files are already updated; only the config cleanup failed.
// Inspect getPrevious() for the I/O cause, fix permissions, re-run or clean the keys by hand.
}
} Prevention
- Pre-clean retired settings (xss_scan_output, xss_allowed_iframe_hosts) from system.yaml before the 1.8 upgrade
- Confirm the upgrading user can write user/config/system.yaml
- Re-run direct-install after fixing the write failure — the removal only fires when the keys still exist
When it happens
Trigger: user/config/system.yaml containing one of the retired keys AND being unwritable/locked/corrupt at update time; permission mismatch when direct-install runs as a different user than the file owner; invalid YAML blocking the updater's rewrite.
Common situations: Sites hardened with custom xss_scan_output / iframe-host allowlists being upgraded; config files owned by the web server while gpm runs as root or a deploy user.
Related errors
- Could not update system configuration to maintain backwards
- Could not update system configuration for Twig compatibility
- Failed to update {file}: {message}
- Could not migrate the Twig-sandbox allowlists to the additiv
- Versions file cannot be read
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/6c300e23e9ca2891.
Report an issue: GitHub.