Remove X-Frame-Options header in favor of CSP frame-ancestors

Signed-off-by: Maximilian Krög <maxi_kroeg@web.de>
This commit is contained in:
Maximilian Krög 2026-03-07 23:48:13 +01:00
parent 8f15b3f4a4
commit e781d75a1e
No known key found for this signature in database
GPG Key ID: 3C00897BB53AAB9C
2 changed files with 10 additions and 16 deletions

View File

@ -376,13 +376,6 @@ class Header
'Permissions-Policy' => 'fullscreen=(self), interest-cohort=()',
];
/* Prevent against ClickJacking by disabling framing */
if ($this->config->config->AllowThirdPartyFraming === 'sameorigin') {
$headers['X-Frame-Options'] = 'SAMEORIGIN';
} elseif ($this->config->config->AllowThirdPartyFraming !== true) {
$headers['X-Frame-Options'] = 'DENY';
}
$headers = array_merge($headers, Core::getNoCacheHeaders($clock ?? new Clock()));
/**
@ -445,6 +438,13 @@ class Header
"style-src 'self' 'unsafe-inline'" . $captchaUrl . $cspAllow,
];
// Prevent click-jacking by disabling inline-framing
if ($this->config->config->AllowThirdPartyFraming === 'sameorigin') {
$csp[] = "frame-ancestors 'self'";
} elseif ($this->config->config->AllowThirdPartyFraming !== true) {
$csp[] = "frame-ancestors 'none'";
}
return implode('; ', $csp) . ';';
}

View File

@ -186,7 +186,6 @@ class HeaderTest extends AbstractTestCase
string $privateKey,
string $publicKey,
string $captchaCsp,
string|null $expectedFrameOptions,
string $expectedCsp,
): void {
$header = $this->getNewHeaderInstance();
@ -206,21 +205,17 @@ class HeaderTest extends AbstractTestCase
'X-Permitted-Cross-Domain-Policies' => 'none',
'X-Robots-Tag' => 'noindex, nofollow',
'Permissions-Policy' => 'fullscreen=(self), interest-cohort=()',
'X-Frame-Options' => $expectedFrameOptions ?? '',
'Expires' => 'Wed, 21 Oct 2015 07:28:00 GMT',
'Cache-Control' => 'no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0',
'Pragma' => 'no-cache',
'Last-Modified' => 'Wed, 21 Oct 2015 07:28:00 GMT',
'Content-Type' => 'text/html; charset=utf-8',
];
if ($expectedFrameOptions === null) {
unset($expected['X-Frame-Options']);
}
self::assertSame($expected, $header->getHttpHeaders(MockClock::from('2015-10-21T05:28:00-02:00')));
}
/** @psalm-return list<array{string|bool, string, string, string, string, string|null, string}> */
/** @psalm-return list<array{string|bool, string, string, string, string, string}> */
public static function providerForTestGetHttpHeaders(): array
{
return [
@ -230,12 +225,12 @@ class HeaderTest extends AbstractTestCase
'',
'',
'',
'DENY',
"default-src 'self';"
. " img-src 'self' data: tile.openstreetmap.org;"
. " object-src 'none';"
. " script-src 'self' 'unsafe-inline' 'unsafe-eval';"
. " style-src 'self' 'unsafe-inline';"
. " frame-ancestors 'none';",
],
[
'sameorigin',
@ -243,12 +238,12 @@ class HeaderTest extends AbstractTestCase
'PrivateKey',
'PublicKey',
'captcha.tld csp.tld',
'SAMEORIGIN',
"default-src 'self' captcha.tld csp.tld example.com example.net;"
. " img-src 'self' data: captcha.tld csp.tld example.com example.net tile.openstreetmap.org;"
. " object-src 'none';"
. " script-src 'self' 'unsafe-inline' 'unsafe-eval' captcha.tld csp.tld example.com example.net;"
. " style-src 'self' 'unsafe-inline' captcha.tld csp.tld example.com example.net;"
. " frame-ancestors 'self';",
],
[
true,
@ -256,7 +251,6 @@ class HeaderTest extends AbstractTestCase
'PrivateKey',
'PublicKey',
'captcha.tld csp.tld',
null,
"default-src 'self' captcha.tld csp.tld;"
. " img-src 'self' data: captcha.tld csp.tld tile.openstreetmap.org;"
. " object-src 'none';"