Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 23, 2025

Fix Content Security Policy Settings

Problem: Apple Music playlist sync fails due to CSP violations blocking required external scripts and frame-ancestors restrictions.

Root Cause:

  1. The Caddyfile was setting a hardcoded CSP that overrode the app's CSP middleware
  2. Dynamic inline styles created by JavaScript needed secure CSP support without exposing nonces
  3. Frame-ancestors directive needed to support both same-origin and cross-origin HTTPS framing

Changes Made:

  • Updated CSP script-src to allow Apple MusicKit CDN and Cloudflare analytics
  • Updated CSP connect-src to allow Cloudflare Insights API
  • Updated CSP frame-ancestors to use https: 'self' for embeds (allows HTTPS + same-origin)
  • Moved dynamic styles to dedicated CSS file - secure implementation without exposing nonces
  • Removed hardcoded CSP from Caddyfile
  • Removed X-Frame-Options from Caddy

Implementation Details:

Application CSP (src/Configuration/StartupExtensions.cs):

  • script-src: Whitelists Apple MusicKit and Cloudflare CDNs + nonce support
  • style-src: Uses nonce-based security (no 'unsafe-inline', no exposed nonces)
  • frame-ancestors: Uses https: 'self' to allow HTTPS framing AND same-origin for embeds/Apple Music pages
  • connect-src: Whitelists music provider APIs and Cloudflare Insights

Secure Style Implementation:

  1. Created playlist-manager.css - Moved all playlist styles from JavaScript to a proper CSS file
  2. Updated _Layout.cshtml - Added CSS file reference (line 15)
  3. Removed dynamic style creation - JavaScript no longer creates inline styles
  4. CSP Policy - Secure nonce-based CSP: style-src 'self' 'nonce-{nonce}'
// Secure CSP - nonces only used server-side, never exposed to JavaScript
string frameAncestors = (isEmbed || isAppleMusic) ? "https: 'self'" : "'self'";

string csp = string.Join("; ", new[] {
    $"script-src 'self' 'nonce-{nonce}' https://js-cdn.music.apple.com https://static.cloudflareinsights.com",
    $"style-src 'self' 'nonce-{nonce}'",  // No 'unsafe-inline', no exposed nonces
    "frame-ancestors " + frameAncestors  // https: 'self' for embeds, 'self' for others
});

Files Modified:

  • src/Configuration/StartupExtensions.cs - CSP middleware configuration
  • Caddyfile - Removed hardcoded CSP and X-Frame-Options
  • src/Web/Views/Shared/_Layout.cshtml - Added CSS reference
  • src/Web/wwwroot/public/playlist-manager.css - NEW: Playlist styles
  • src/Web/wwwroot/public/playlist-manager.js - Removed dynamic style creation

Security Improvements:

  • ✅ Nonce-based CSP for scripts and styles - strong security
  • ✅ No 'unsafe-inline' directives - eliminates XSS attack vector
  • Nonces never exposed to JavaScript - proper CSP security model
  • ✅ Styles in dedicated CSS file - standard best practice
  • ✅ Only specific CDNs whitelisted (no wildcards)
  • frame-ancestors https: 'self' allows HTTPS framing + same-origin while blocking HTTP

Frame-Ancestors Fix:
Changed from https: to https: 'self' to properly support:

  • External HTTPS sites embedding the content (e.g., social media, other sites)

  • Same-origin framing (e.g., when dev.tunebridge.media frames its own embed endpoints)

  • Fixes Fix Content Security Policy Settings #142

Original prompt

This section details on the original issue you should resolve

<issue_title>Fix Content Security Policy Settings</issue_title>
<issue_description>### Problem
When attempting to sync playlists with Apple Music, the following Content Security Policy (CSP) errors occur:

applemusic:1  Loading the script 'https://js-cdn.music.apple.com/musickit/v3/musickit.js' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. The action has been blocked.
applemusic:1  Loading the script 'https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. The action has been blocked.

Steps to Reproduce

  1. Attempt to sync playlists with Apple Music integration enabled.
  2. Observe the CSP errors listed above in the browser console.
  3. Playlist sync is blocked due to CSP restrictions.

Expected Behavior

Apple Music playlist sync integration should work without CSP violations.

Suggested Fix

  • Update the Content Security Policy to safely allow required scripts for Apple Music integration while maintaining best security practices.
  • Review if external scripts like musickit.js and required analytics scripts can be loaded in a secure manner or use alternate methods if needed.

Additional Info

  • Affected script URLs: https://js-cdn.music.apple.com/musickit/v3/musickit.js, https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015
    • Note that the cloudflare script should be able to run across the entire site.
  • Make sure any CSP updates are thoroughly reviewed for security implications.
    </issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix Content Security Policy settings to allow Apple Music scripts Fix CSP violations blocking Apple Music integration and Cloudflare analytics Nov 23, 2025
Copilot AI requested a review from tsmarvin November 23, 2025 10:42
Copilot finished work on behalf of tsmarvin November 23, 2025 10:42
@tsmarvin
Copy link
Owner

This did not fix anything as far as I can tell @copilot
I am still getting the following error on embeds:

Framing 'https://dev.tunebridge.media/' violates the following Content Security Policy directive: "frame-ancestors 'self'". The request has been blocked.

this on the apple music page:

applemusic:1  Loading the script 'https://js-cdn.music.apple.com/musickit/v3/musickit.js' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. The action has been blocked.
applemusic:1  Loading the script 'https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. The action has been blocked.

and this message pretty much everywhere:

vp566u7m446b2vlays5w267lmqhc3kol:1  Loading the script 'https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. The action has been blocked.

Copy link
Contributor Author

Copilot AI commented Nov 23, 2025

This did not fix anything as far as I can tell @copilot
I am still getting the following error on embeds:

...

Found the issue! The Caddyfile was setting a hardcoded CSP header that overrode the application's dynamic CSP middleware. The browser was seeing Caddy's CSP (script-src 'self' 'unsafe-inline') instead of the app's nonce-based CSP with CDN whitelisting.

Fixed in commit 39281c3:

  • Removed hardcoded CSP from Caddyfile (line 36)
  • Removed X-Frame-Options from Caddyfile (line 27) to prevent conflict with CSP frame-ancestors
  • Now the application's CSP middleware will apply correctly with:
    • Nonce-based inline script security (more secure than 'unsafe-inline')
    • Whitelisted CDNs: https://js-cdn.music.apple.com and https://static.cloudflareinsights.com
    • Dynamic frame-ancestors (* for embeds and /applemusic/*, 'self' for other pages)

The CSP violations should now be resolved. After deploying, you should see the nonce in the CSP header instead of 'unsafe-inline'.

Copilot AI changed the title Fix CSP violations blocking Apple Music integration and Cloudflare analytics Fix CSP violations by removing Caddy CSP override and configuring app middleware Nov 23, 2025
Copilot finished work on behalf of tsmarvin November 23, 2025 10:56
@tsmarvin
Copy link
Owner

Sadly that didn’t change anything either @copilot

Copy link
Contributor Author

Copilot AI commented Nov 23, 2025

Sadly that didn’t change anything either @copilot

The changes look correct in the code. Since you're still seeing script-src 'self' 'unsafe-inline' (which was the old Caddyfile CSP), this suggests the updated Caddyfile hasn't been deployed yet.

To apply the fix:

  1. Redeploy with the updated Caddyfile (commit 39281c3)
  2. Restart the Caddy container to pick up the new config
  3. Clear browser cache or do a hard refresh (Ctrl+Shift+R / Cmd+Shift+R)

To verify it's working after deployment:
Check the CSP header in browser DevTools → Network tab → select any request → Response Headers. You should see:

  • Content-Security-Policy with a 'nonce-XXXXX' value (not 'unsafe-inline')
  • CDNs whitelisted: https://js-cdn.music.apple.com and https://static.cloudflareinsights.com

Have you redeployed/restarted Caddy with the updated Caddyfile?

Sadly that didn’t change anything either @copilot

Found it! The docker-compose.yml was pulling a pre-built image from Docker Hub (tsmarvin/tunebridge-test:develop) that didn't have the updated application code. The Caddyfile changes were applied (volume mounted), but the CSP middleware changes in the application weren't.

Fixed in commit 12d871f:
Updated docker-compose.yml to build from local Dockerfile instead of pulling the pre-built image.

To deploy the fix:

docker-compose up -d --build

This will rebuild the container with the updated CSP middleware code that:

  • Uses nonce-based CSP (not 'unsafe-inline')
  • Whitelists Apple MusicKit and Cloudflare CDNs
  • Allows dynamic frame-ancestors for embeds and Apple Music pages

Copilot AI changed the title Fix CSP violations by removing Caddy CSP override and configuring app middleware Fix CSP violations by removing Caddy CSP override, configuring app middleware, and fixing Docker deployment Nov 23, 2025
Copilot finished work on behalf of tsmarvin November 23, 2025 11:08
@tsmarvin
Copy link
Owner

Please revert the last change -

I updated my caddy configuration myself to remove the CSP and X-Origin settings, which did pass the CSP settings into the app, but now I'm getting the following error from the playlist page:

playlist-manager.js:555  Applying inline style violates the following Content Security Policy directive 'style-src 'self' 'nonce-+LbwX09HqKwGCTDr8ZqKTQ==''. Either the 'unsafe-inline' keyword, a hash ('sha256-5dvcur/7eA1rhl7UFlU9ssfk6D9IKaq9jsi3WjphtCA='), or a nonce ('nonce-...') is required to enable inline execution. The action has been blocked.
init @ playlist-manager.js:555

and this error from the embeds:

Framing 'https://dev.tunebridge.media/' violates the following Content Security Policy directive: "frame-ancestors *". The request has been blocked. Note that '*' matches only URLs with network schemes ('http', 'https', 'ws', 'wss'), or URLs whose scheme matches `self`'s scheme. The scheme 'https:' must be added explicitly.

@tsmarvin
Copy link
Owner

@copilot forgot to tag you - that last message is for you.

Copy link
Contributor Author

Copilot AI commented Nov 23, 2025

Please revert the last change -

I updated my caddy configuration myself to remove the CSP and X-Origin settings, which did pass the CSP settings into the app, but now I'm getting the following erro...

Fixed both issues in commit 382640b:

  1. Reverted docker-compose.yml - Removed the build configuration, back to pulling pre-built image
  2. Fixed inline style CSP violation - Added 'unsafe-inline' to style-src to allow dynamically created styles in playlist-manager.js
  3. Fixed frame-ancestors for HTTPS - Changed from frame-ancestors * to frame-ancestors https: which properly supports HTTPS framing

The CSP now uses:

  • style-src 'self' 'nonce-{nonce}' 'unsafe-inline' - Allows inline styles
  • frame-ancestors https: for embeds and Apple Music pages - Allows HTTPS framing while blocking HTTP

After deploying these changes, both errors should be resolved.

Copilot AI changed the title Fix CSP violations by removing Caddy CSP override, configuring app middleware, and fixing Docker deployment Fix CSP violations by removing Caddy CSP override and configuring app middleware Nov 23, 2025
Copilot finished work on behalf of tsmarvin November 23, 2025 20:30
Copilot AI requested a review from tsmarvin November 23, 2025 20:35
Copilot finished work on behalf of tsmarvin November 23, 2025 20:35
Copilot finished work on behalf of tsmarvin November 23, 2025 20:47
Copilot finished work on behalf of tsmarvin November 23, 2025 22:05
Copilot finished work on behalf of tsmarvin November 23, 2025 22:45
Copilot finished work on behalf of tsmarvin November 23, 2025 22:51
@tsmarvin
Copy link
Owner

@copilot please fix the embedding issue I mentioned in this comment

Copy link
Contributor Author

Copilot AI commented Nov 23, 2025

@copilot please fix the embedding issue I mentioned in this comment

Fixed in commit b698364. The CSP now uses frame-ancestors https: 'self' for embed endpoints, which allows:

  • External HTTPS sites to embed the content
  • Same-origin framing (e.g., dev.tunebridge.media framing itself)

Copilot finished work on behalf of tsmarvin November 23, 2025 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Content Security Policy Settings

2 participants