diff --git a/app/Util/CspService.php b/app/Util/CspService.php index 227ec8e0b..4262b5c98 100644 --- a/app/Util/CspService.php +++ b/app/Util/CspService.php @@ -133,18 +133,30 @@ class CspService protected function getAllowedIframeSources(): array { - $sources = config('app.iframe_sources', ''); - $hosts = array_filter(explode(' ', $sources)); + $sources = explode(' ', config('app.iframe_sources', '')); + $sources[] = $this->getDrawioHost(); - // Extract drawing service url to allow embedding if active + return array_filter($sources); + } + + /** + * Extract the host name of the configured drawio URL for use in CSP. + * Returns empty string if not in use. + */ + protected function getDrawioHost(): string + { $drawioConfigValue = config('services.drawio'); - if ($drawioConfigValue) { - $drawioSource = is_string($drawioConfigValue) ? $drawioConfigValue : 'https://embed.diagrams.net/'; - $drawioSourceParsed = parse_url($drawioSource); - $drawioHost = $drawioSourceParsed['scheme'] . '://' . $drawioSourceParsed['host']; - $hosts[] = $drawioHost; + if (!$drawioConfigValue) { + return ''; } - return $hosts; + $drawioSource = is_string($drawioConfigValue) ? $drawioConfigValue : 'https://embed.diagrams.net/'; + $drawioSourceParsed = parse_url($drawioSource); + $drawioHost = $drawioSourceParsed['scheme'] . '://' . $drawioSourceParsed['host']; + if (isset($drawioSourceParsed['port'])) { + $drawioHost .= ':' . $drawioSourceParsed['port']; + } + + return $drawioHost; } } diff --git a/tests/SecurityHeaderTest.php b/tests/SecurityHeaderTest.php index d369e695c..5d354e553 100644 --- a/tests/SecurityHeaderTest.php +++ b/tests/SecurityHeaderTest.php @@ -139,6 +139,18 @@ class SecurityHeaderTest extends TestCase $this->assertEquals('frame-src \'self\' https://example.com https://diagrams.example.com', $scriptHeader); } + public function test_frame_src_csp_header_drawio_host_includes_port_if_existing() + { + config()->set([ + 'app.iframe_sources' => 'https://example.com', + 'services.drawio' => 'https://diagrams.example.com:8080/testing?cat=dog', + ]); + + $resp = $this->get('/'); + $scriptHeader = $this->getCspHeader($resp, 'frame-src'); + $this->assertEquals('frame-src \'self\' https://example.com https://diagrams.example.com:8080', $scriptHeader); + } + public function test_cache_control_headers_are_set_on_responses() { // Public access