Skip to content

[Bug] Whiteboard CSP listener fails to add collaboration backend to connect-src, preventing collaboration #1250

Description

@Masoud-Ghanbari

Environment

  • Nextcloud Server: 34.0.1.2
  • Whiteboard app: 1.5.9
  • Whiteboard Collaboration Backend: 1.5.9 (ghcr.io/nextcloud-releases/whiteboard:stable)
  • Deployment:
    • Nextcloud running on a dedicated server
    • Whiteboard backend running on Docker
    • Nginx reverse proxy
    • HTTPS enabled

Problem

Whiteboard opens normally, but real-time collaboration does not work.

The browser never establishes a WebSocket connection to the collaboration backend because the backend URL is missing from the generated Content Security Policy.

Browser console shows:

Connecting to 'wss://whiteboard.example.com/socket.io/?EIO=4&transport=websocket'
violates the following Content Security Policy directive:

connect-src
'self'
blob:
...
wss://notification.example.com

The Whiteboard backend is not included in connect-src.

As a result:

  • no WebSocket connection is attempted
  • no request reaches the Whiteboard backend
  • Docker logs remain empty
  • collaboration never starts

Backend verification

The backend itself works correctly.

Polling succeeds:

GET /socket.io/?EIO=4&transport=polling
200 OK
0{"sid":"...","upgrades":["websocket"], ...}

WebSocket upgrade also succeeds through Nginx.

JWT configuration is correct.

collabBackendUrl is configured correctly.

Therefore the backend and reverse proxy are functioning correctly.

Investigation

The CSP listener is correctly registered:

$context->registerEventListener(
    AddContentSecurityPolicyEvent::class,
    AddContentSecurityPolicyListener::class
);

The listener contains the following early return:

if (!$this->isPageLoad() || !$this->isWhiteboardPage()) {
    return;
}

Workaround

As a test, I removed the conditional completely in apps/whiteboard/lib/Listener/AddContentSecurityPolicyListener.php file:

public function handle(Event $event): void {
    if (!$event instanceof AddContentSecurityPolicyEvent) {
        return;
    }

    $domains = $this->configService->getCollabBackendCspConnectDomains();

    $policy = new EmptyContentSecurityPolicy();

    foreach ($domains as $domain) {
        $policy->addAllowedConnectDomain($domain);
    }

    $event->addPolicy($policy);
}

Immediately after this modification:

  • wss://whiteboard.example.com appeared in the CSP
  • the browser connected successfully
  • WebSocket connection was established
  • collaboration started working normally

No other configuration changes were required.

Suspected cause

One of these conditions appears to incorrectly evaluate to false:

isPageLoad()

or

isWhiteboardPage()

preventing the CSP from being added even though the Whiteboard viewer is active.

This may be a regression affecting Nextcloud 34.x, where the current request path or script name no longer matches the assumptions made by the listener.

Expected behavior

Whenever a Whiteboard document is opened and collaboration is required, the Whiteboard collaboration backend should always be added to the generated connect-src CSP so the browser can establish the Socket.IO/WebSocket connection.

Actual behavior

The CSP listener exits early, the collaboration backend is omitted from connect-src, and all WebSocket connections are blocked by the browser before reaching the backend.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions