Skip to main content
Version: 2026.1

Content Security Policy

Overview

Pimcore Studio provides a Content Security Policy (CSP) handler that adds an additional security layer to protect from attacks like Cross-Site Scripting (XSS) by adding a Content-Security-Policy HTTP header with nonce to every Studio request. CSP is enabled by default.

Read more about Content Security Policy.

Configuration

Adding External URLs

To allow external URLs for CSP directives:

# config/config.yaml
pimcore_studio_ui:
csp_header:
additional_urls:
script-src:
- 'https://cdn.example.com/scripts/analytics.js'
style-src:
- 'https://fonts.googleapis.com'
connect-src:
- 'https://api.example.com'

Available directives: default-src, script-src, style-src, connect-src, font-src, img-src, media-src, frame-src, worker-src

Disabling CSP

# config/config.yaml
pimcore_studio_ui:
csp_header:
enabled: false

Excluding Paths

# config/config.yaml
pimcore_studio_ui:
csp_header:
exclude_paths:
- '/pimcore-studio/custom-endpoint'
- '~/pimcore-studio/api/.*~' # Regex pattern

Using Nonce in Templates

Add the nonce attribute to inline scripts to prevent CSP violations:

<script {{ pimcore_studio_csp.getNonceHtmlAttribute()|raw }}>
console.log('This script will execute safely');
</script>

Extending CSP in Your Application

If your bundle or application serves resources from external origins (Rsbuild dev servers, CDNs, module federation), register these origins using the CspEvent:

Example Subscriber

<?php
namespace MyBundle\EventSubscriber;

use Pimcore\Bundle\StudioUiBundle\Event\Csp\CspEvent;
use Pimcore\Bundle\StudioUiBundle\Security\Csp\CspOriginFileParserInterface;
use Pimcore\Bundle\StudioUiBundle\Security\Csp\ContentSecurityPolicyHandlerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final readonly class MyBundleCspSubscriber implements EventSubscriberInterface
{
public function __construct(
private CspOriginFileParserInterface $cspOriginFileParser
) {
}

public static function getSubscribedEvents(): array
{
return [
CspEvent::class => ['onCspEvent', 0], // Priority 0 runs after core subscribers
];
}

public function onCspEvent(CspEvent $event): void
{
// Option 1: Add origins extracted from files
$remoteEntryFiles = glob(__DIR__ . '/../../public/build/*/exposeRemote.js') ?: [];
if (!empty($remoteEntryFiles)) {
$origins = $this->cspOriginFileParser->extractOriginsFromFiles($remoteEntryFiles);
$event->addBuildOrigins($origins);
}

// Option 2: Manually add specific origins (added to script-src, style-src, connect-src)
$event->addBuildOrigins([
'http://localhost:3040',
'https://cdn.mybundle.com',
]);

// Option 3: Add origins to specific directives
$cspHandler = $event->getCspHandler();
$cspHandler->addAllowedUrls(
ContentSecurityPolicyHandlerInterface::FONT_OPT,
['https://fonts.googleapis.com', 'https://fonts.gstatic.com']
);
}
}

Register the Subscriber

# config/services.yaml
services:
MyBundle\EventSubscriber\MyBundleCspSubscriber:
tags: ['kernel.event_subscriber']

Alternatively, inject the ContentSecurityPolicyHandlerInterface directly into your services for configuration-time setup.

Troubleshooting

  • CSP violations: Ensure inline scripts have nonce attributes and external origins are registered
  • Dev servers: Development server origins (e.g., http://localhost:3030, http://localhost:3031) are automatically detected from entry point JSON files. Add additional bundle-specific dev servers through a CspEvent subscriber (e.g., by scanning additional files or manually specifying origins)
  • Production: Configure additional resources in additional_urls (e.g., CDN origins)