Home/Blog/How to handle CSP for third-party resources?
Web Security

How to handle CSP for third-party resources?

Learn strategies for implementing Content Security Policy while managing third-party scripts, styles, and resources safely without compromising functionality.

By Inventive HQ Team
How to handle CSP for third-party resources?

Managing Third-Party Resources with CSP

Most websites depend on third-party resources: analytics, advertising, social widgets, payment processors, and more. However, these third-party resources can be security vulnerabilities and conflict with Content Security Policy restrictions.

Balancing functionality with security requires careful planning and configuration of CSP rules for third-party resources.

Common Third-Party Resources

Analytics

Google Analytics, Mixpanel, Segment, etc. typically require:

<script src="https://www.google-analytics.com/ga.js"></script>

Advertising

Google AdSense, DoubleClick, Facebook Pixel, etc.:

<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

Fonts

Google Fonts, Adobe Fonts, etc.:

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">

Social Widgets

Facebook, Twitter, LinkedIn buttons and feeds:

<script src="https://platform.twitter.com/widgets.js"></script>

Payment Processors

Stripe, PayPal, Square, etc.:

<script src="https://js.stripe.com/v3/"></script>

CDN Resources

jQuery, Bootstrap, D3.js from CDN:

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

CSP Approach for Third-Party Resources

Step 1: Identify All Third-Party Resources

Audit your website to identify all third-party sources:

// Use browser DevTools to see all resources
// Network tab shows all requests
// Note the domains and types (script, style, font, etc.)

Or automate with a script:

# Find all script sources in HTML
grep -o 'src="[^"]*"' index.html | grep -o '"[^"]*"' | sort | uniq

Step 2: Create Whitelist Rules

Add third-party domains to your CSP directives:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.google-analytics.com https://cdn.example.com;
  style-src 'self' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' https: data:;
  connect-src 'self' https://www.google-analytics.com

Step 3: Handle Special Cases

Some third-party resources don't work well with strict CSP.

Inline Scripts in Third-Party Resources

If third-party code injects inline scripts, allow them with nonces or hashes:

<!-- Third-party widget that injects inline scripts -->
<div id="widget-container"></div>
<script src="https://widgets.example.com/embed.js"></script>

CSP approach:

script-src 'self' https://widgets.example.com 'unsafe-inline'

Or use nonces (better):

<!-- Server generates unique nonce for each request -->
<script nonce="abc123def456">
  // Third-party injected code
</script>

CSP:

script-src 'self' 'nonce-abc123def456'

Dynamic Resource Loading

Some third-party scripts load additional resources dynamically:

// Third-party library might load images, stylesheets, scripts dynamically
const widget = new ThirdPartyWidget({
  apiKey: 'xxx'
});
widget.load(); // Loads additional resources from their CDN

CSP configuration must allow both the initial script and dynamically loaded resources:

script-src 'self' https://cdn.example.com https://api.example.com;
img-src 'self' https://cdn.example.com;
style-src 'self' https://cdn.example.com

Common Third-Party Configurations

Google Analytics

script-src 'self' https://www.google-analytics.com https://googleadservices.com;
connect-src 'self' https://www.google-analytics.com https://www.googletagmanager.com

Google Fonts

style-src 'self' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com

Stripe (Payment)

script-src 'self' https://js.stripe.com;
connect-src 'self' https://api.stripe.com

Facebook Pixel

script-src 'self' https://connect.facebook.net;
img-src 'self' https://pixel.facebook.com https://www.facebook.com;
connect-src 'self' https://www.facebook.com

Twitter/X Widgets

script-src 'self' https://platform.twitter.com;
frame-src https://twitter.com https://platform.twitter.com;
style-src 'self' 'unsafe-inline'

Risk Management Strategies

1. Use Subresource Integrity (SRI)

Verify that third-party resources haven't been tampered with:

<!-- Specify hash of expected content -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
        integrity="sha384-KyZXEAg3QhqLMpG8r+Knujsl5+..."
        crossorigin="anonymous"></script>

CSP with SRI:

script-src 'self' https://code.jquery.com 'require-sri-for'

The browser verifies the hash before executing. If content doesn't match, it's blocked.

2. Use Content Delivery Networks (CDN) with Integrity

If hosting third-party resources yourself:

script-src 'self' https://mycdn.example.com

Self-hosted is more secure than relying on third-party CDN.

3. Minimize Third-Party Dependencies

Audit whether each third-party resource is necessary:

  • Do you really need this analytics library?
  • Can a lighter alternative be used?
  • Can functionality be built in-house?

Fewer third-party resources = simpler CSP = stronger security.

4. Trusted Vendors Only

Only whitelist vendors you trust and have vetted:

  • Established companies with security track records
  • Regular security audits
  • Proper data handling practices
  • Transparent terms of service

5. Regular Security Audits

Periodically audit third-party usage:

// Script to document all third-party resources
const scripts = Array.from(document.scripts).map(s => s.src).filter(Boolean);
const styles = Array.from(document.styleSheets).map(s => s.href).filter(Boolean);

console.log('Scripts:', scripts);
console.log('Styles:', styles);

Handling Legacy Third-Party Code

Some older third-party resources don't work well with strict CSP:

Option 1: Use 'unsafe-inline' Judiciously

script-src 'self' 'unsafe-inline' https://legacy-vendor.com;
style-src 'self' 'unsafe-inline' https://legacy-vendor.com

Not ideal but sometimes necessary for legacy code.

Option 2: Create a Sandboxed Iframe

Isolate problematic third-party code in an iframe with its own CSP:

<!-- Main page with strict CSP -->
<!-- Other content -->

<!-- Iframe with lenient CSP for problematic third-party code -->
<iframe id="legacy-widget" src="/legacy-widget.html"></iframe>

In /legacy-widget.html:

<!DOCTYPE html>
<html>
<head>
  <!-- Lenient CSP only for this iframe -->
  <meta http-equiv="Content-Security-Policy"
        content="default-src 'unsafe-inline' https://legacy-vendor.com">
</head>
<body>
  <!-- Legacy third-party code here -->
  <script src="https://legacy-vendor.com/problematic-script.js"></script>
</body>
</html>

This isolates the problematic code from your main application.

Option 3: Proxy Third-Party Requests

For some third-party resources, create a proxy endpoint on your server:

// Express.js proxy example
const axios = require('axios');

app.get('/proxy/analytics', async (req, res) => {
  // Proxy third-party analytics request through your server
  const response = await axios.get('https://analytics-provider.com/track', {
    params: req.query
  });
  res.json(response.data);
});

Then in your CSP:

connect-src 'self' /proxy/analytics

This prevents direct communication with the third-party domain.

Testing CSP with Third-Party Resources

Use Report-Only During Implementation

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self' [third-party domains];
  report-uri /csp-report

Monitor violations to ensure all third-party resources are whitelisted.

Test Cross-Browser

Third-party resources might behave differently in different browsers:

# Test in multiple browsers
# Chrome, Firefox, Safari, Edge

# Verify all third-party content loads
# Check browser console for CSP violations

Automated Testing

Add CSP testing to your CI/CD pipeline:

# Check for CSP violations during tests
# Lighthouse includes CSP auditing
lighthouse https://example.com --view

# Use pa11y-ci or similar tools

Best Practices for Third-Party CSP

  1. Whitelist specific domains: Never use * for third-party resources
  2. Use https only: Require secure transport with https:
  3. Apply SRI when possible: Verify third-party script integrity
  4. Monitor and audit regularly: Keep CSP updated as usage changes
  5. Start restrictive: Begin with strict CSP, then add exceptions
  6. Document decisions: Explain why each third-party domain is whitelisted
  7. Use report-only first: Test policies before enforcement
  8. Review access logs: Monitor third-party resource requests
  9. Have an update process: Plan how to handle third-party security updates
  10. Consider alternatives: Always evaluate if third-party dependency is necessary

Complete Example

A realistic CSP handling multiple common third-parties:

Content-Security-Policy:
  default-src 'self';
  script-src 'self'
    https://www.google-analytics.com
    https://www.googletagmanager.com
    https://connect.facebook.net
    https://js.stripe.com
    https://code.jquery.com;
  style-src 'self'
    https://fonts.googleapis.com
    https://cdn.example.com/styles;
  font-src 'self'
    https://fonts.gstatic.com;
  img-src 'self' https: data:;
  connect-src 'self'
    https://www.google-analytics.com
    https://api.stripe.com;
  frame-src
    https://js.stripe.com;
  report-uri /csp-report

Handling third-party resources with CSP requires balance between functionality and security. By carefully whitelisting trusted vendors, using subresource integrity, and regularly auditing dependencies, you can maintain a strong security posture while leveraging valuable third-party services.

Need Expert IT & Security Guidance?

Our team is ready to help protect and optimize your business technology infrastructure.