{"record":{"id":"6c300e23e9ca2891","repo":"getgrav/grav","slug":"could-not-remove-the-retired-security-xss-scan-o","errorCode":null,"errorMessage":"Could not remove the retired security.*.xss_scan_output settings","messagePattern":"Could not remove the retired security\\.\\*\\.xss_scan_output settings","errorType":"exception","errorClass":"InstallException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Installer/updates/1.8.0_2026-07-03_0.php","lineNumber":42,"sourceCode":"    'postflight' =>\n        function () {\n            /** @var VersionUpdate $this */\n            try {\n                $yaml = YamlUpdater::instance(GRAV_ROOT . '/user/config/security.yaml');\n\n                $changed = false;\n                foreach (['twig_content.xss_scan_output', 'content.xss_scan_output', 'xss_allowed_iframe_hosts'] as $key) {\n                    if ($yaml->exists($key)) {\n                        $yaml->undefine($key);\n                        $changed = true;\n                    }\n                }\n\n                if ($changed) {\n                    $yaml->save();\n                }\n            } catch (\\Exception $e) {\n                throw new InstallException('Could not remove the retired security.*.xss_scan_output settings', $e);\n            }\n        }\n];\n","sourceCodeStart":24,"sourceCodeEnd":46,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Installer/updates/1.8.0_2026-07-03_0.php#L24-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (system.yaml still has retired keys, file not writable)\ntwig_content:\n  xss_scan_output: encode\n\n# after — remove the retired block, then re-run the updater\ntwig_content: {  }","handlingStrategy":"try-catch","validationCode":"// Remove retired keys manually before upgrading to sidestep the postflight write\n$file = GRAV_ROOT . '/user/config/system.yaml';\n$yaml = \\Symfony\\Component\\Yaml\\Yaml::parseFile($file);\nforeach (['twig_content', 'content'] as $k) {\n    if (isset($yaml[$k]['xss_scan_output'])) unset($yaml[$k]['xss_scan_output']);\n}\nunset($yaml['xss_allowed_iframe_hosts']);\nfile_put_contents($file, \\Symfony\\Component\\Yaml\\Yaml::dump($yaml, 10));","typeGuard":null,"tryCatchPattern":"try {\n    Install::instance()->run();\n} catch (InstallException $e) {\n    if (str_contains($e->getMessage(), 'retired security')) {\n        // Core files are already updated; only the config cleanup failed.\n        // Inspect getPrevious() for the I/O cause, fix permissions, re-run or clean the keys by hand.\n    }\n}","preventionTips":["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"],"tags":["installer","yaml","configuration","xss","deprecated-settings"],"backgroundTag":"config-file-write-failed","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}