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 '';
+ }
+
+ $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 $hosts;
+ return $drawioHost;
}
}
$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