Whiteboard works correctly when opened from Files, but shows "offline / changes saved locally" when opened inside a Talk room. The WebSocket connection to the collaboration server is blocked by CSP.
Environment
- Nextcloud: 33.0.4.1
- Whiteboard app: 1.5.9
- Talk (spreed) app: 23.0.5
- Collaboration backend: self-hosted (Docker)
Steps to reproduce
- Configure Nextcloud Whiteboard with a self-hosted collaboration backend
- Open a Talk room
- Create or open a whiteboard file inside the Talk room
- Whiteboard shows "offline" — real-time collaboration does not work
Expected behavior
Whiteboard connects to the collaboration backend and works in real-time, same as when opened from Files.
Actual behavior
Browser console shows:
Content-Security-Policy: The page's settings blocked the loading of a resource (connect-src) at wss://whiteboard.example.com/socket.io/?EIO=4&transport=websocket because it violates the following directive: "connect-src 'self' blob: https://talk-hpb.example.com:3478 wss://talk-hpb.example.com"
Root cause
In lib/Listener/AddContentSecurityPolicyListener.php, the isWhiteboardPage() method only adds the whiteboard CSP for /apps/files, /apps/whiteboard/recording, and /s/ (public shares). It does not include /apps/spreed (Talk), so the whiteboard collaboration server domain is never added to connect-src when the page is a Talk room.
private function isWhiteboardPage(): bool {
$pathInfo = $this->request->getPathInfo();
if (!is_string($pathInfo)) {
return false;
}
return str_starts_with($pathInfo, '/apps/files')
|| str_starts_with($pathInfo, '/apps/whiteboard/recording')
|| str_starts_with($pathInfo, '/s/');
// missing: || str_starts_with($pathInfo, '/apps/spreed')
}
Proposed fix
Add /apps/spreed to the isWhiteboardPage() check:
return str_starts_with($pathInfo, '/apps/files')
|| str_starts_with($pathInfo, '/apps/whiteboard/recording')
|| str_starts_with($pathInfo, '/s/')
|| str_starts_with($pathInfo, '/apps/spreed');
Workaround
Manually patch the file on the server until a fix is released:
sed -i "s|str_starts_with(\$pathInfo, '/s/')|str_starts_with(\$pathInfo, '/s/') \|\| str_starts_with(\$pathInfo, '/apps/spreed')|" \
/var/www/html/custom_apps/whiteboard/lib/Listener/AddContentSecurityPolicyListener.php
Whiteboard works correctly when opened from Files, but shows "offline / changes saved locally" when opened inside a Talk room. The WebSocket connection to the collaboration server is blocked by CSP.
Environment
Steps to reproduce
Expected behavior
Whiteboard connects to the collaboration backend and works in real-time, same as when opened from Files.
Actual behavior
Browser console shows:
Root cause
In lib/Listener/AddContentSecurityPolicyListener.php, the isWhiteboardPage() method only adds the whiteboard CSP for /apps/files, /apps/whiteboard/recording, and /s/ (public shares). It does not include /apps/spreed (Talk), so the whiteboard collaboration server domain is never added to connect-src when the page is a Talk room.
Proposed fix
Add /apps/spreed to the isWhiteboardPage() check:
Workaround
Manually patch the file on the server until a fix is released:
sed -i "s|str_starts_with(\$pathInfo, '/s/')|str_starts_with(\$pathInfo, '/s/') \|\| str_starts_with(\$pathInfo, '/apps/spreed')|" \ /var/www/html/custom_apps/whiteboard/lib/Listener/AddContentSecurityPolicyListener.php