Skip to main content

Content Security Policy (CSP) Configuration

Content Security Policy (CSP) is a security feature that helps prevent cross-site scripting (XSS) attacks. When integrating FramePay, you need to configure your CSP to allow the necessary domains.

Overview​

FramePay loads payment fields via secure iframes and requires specific CSP directives to function properly. This guide covers:

  • 🔒 Required CSP directives
  • 🌐 Allowed domains
  • ⚙️ Configuration methods
  • 🎯 Best practices

Required CSP Directives​

Minimum Configuration​

To use FramePay with card payments only, include these directives:

<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline' framepay.payments.ai;
connect-src 'self' framepay.payments.ai *.payments.ai;
style-src 'self' 'unsafe-inline' framepay.payments.ai;
frame-src 'self' framepay.payments.ai;
img-src 'self' data: framepay.payments.ai;
font-src 'self';
">

Full Configuration (with Digital Wallets)​

If you're using Apple Pay, Google Pay, or PayPal, add their domains:

<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline'
framepay.payments.ai
*.paypal.com
*.google.com
*.cdn-apple.com;
connect-src 'self'
framepay.payments.ai
*.payments.ai
*.paypal.com
*.google.com
*.apple.com;
style-src 'self' 'unsafe-inline'
framepay.payments.ai
fonts.googleapis.com;
frame-src 'self'
framepay.payments.ai
*.paypal.com
*.google.com;
img-src 'self' data:
framepay.payments.ai
*.paypal.com
*.google.com;
font-src 'self'
fonts.gstatic.com;
">

Configuration Methods​

Method 1: HTML Meta Tag​

Add the CSP meta tag in your HTML <head> section:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com *.cdn-apple.com;
connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com;
style-src 'self' 'unsafe-inline' framepay.payments.ai fonts.googleapis.com;
frame-src 'self' framepay.payments.ai *.paypal.com *.google.com;
img-src 'self' data: framepay.payments.ai *.paypal.com *.google.com;
font-src 'self' fonts.gstatic.com;
">
<title>Checkout</title>
</head>
<body>
<!-- Your content here -->
</body>
</html>

Configure CSP via HTTP headers on your server. This is the recommended approach for production.

Node.js/Express​

const express = require('express');
const app = express();

app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com *.cdn-apple.com; " +
"connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com; " +
"style-src 'self' 'unsafe-inline' framepay.payments.ai fonts.googleapis.com; " +
"frame-src 'self' framepay.payments.ai *.paypal.com *.google.com; " +
"img-src 'self' data: framepay.payments.ai *.paypal.com *.google.com; " +
"font-src 'self' fonts.gstatic.com;"
);
next();
});

Nginx​

location / {
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com *.cdn-apple.com; connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com; style-src 'self' 'unsafe-inline' framepay.payments.ai fonts.googleapis.com; frame-src 'self' framepay.payments.ai *.paypal.com *.google.com; img-src 'self' data: framepay.payments.ai *.paypal.com *.google.com; font-src 'self' fonts.gstatic.com;";
}

Apache​

<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com *.cdn-apple.com; connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com; style-src 'self' 'unsafe-inline' framepay.payments.ai fonts.googleapis.com; frame-src 'self' framepay.payments.ai *.paypal.com *.google.com; img-src 'self' data: framepay.payments.ai *.paypal.com *.google.com; font-src 'self' fonts.gstatic.com;"
</IfModule>

Next.js​

// next.config.js
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com *.cdn-apple.com",
"connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com",
"style-src 'self' 'unsafe-inline' framepay.payments.ai fonts.googleapis.com",
"frame-src 'self' framepay.payments.ai *.paypal.com *.google.com",
"img-src 'self' data: framepay.payments.ai *.paypal.com *.google.com",
"font-src 'self' fonts.gstatic.com"
].join('; ')
}
]
}
]
}
}

CSP Directive Breakdown​

default-src 'self'​

Sets the default policy for all content types. 'self' allows content only from your own domain.

script-src​

Controls which JavaScript sources are allowed:

  • 'self' - Your own domain
  • 'unsafe-inline' - Required for FramePay inline scripts
  • framepay.payments.ai - FramePay CDN
  • *.paypal.com - PayPal SDK (if using PayPal)
  • *.google.com - Google Pay SDK (if using Google Pay)
  • *.cdn-apple.com - Apple Pay SDK (if using Apple Pay)

⚠️ Security Note: 'unsafe-inline' reduces CSP protection. For production, consider using nonces for better security.

connect-src​

Controls which domains can be contacted via XHR, WebSocket, or EventSource:

  • 'self' - Your own domain
  • framepay.payments.ai - FramePay API
  • *.payments.ai - Payments AI API
  • *.paypal.com - PayPal API
  • *.google.com - Google Pay API

style-src​

Controls stylesheet sources:

  • 'self' - Your own stylesheets
  • 'unsafe-inline' - Required for inline styles
  • framepay.payments.ai - FramePay CSS
  • fonts.googleapis.com - Google Fonts (if used)

frame-src​

Controls which sources can be loaded in iframes (crucial for FramePay):

  • 'self' - Your own domain
  • framepay.payments.ai - FramePay payment fields
  • *.paypal.com - PayPal iframe
  • *.google.com - Google Pay iframe

img-src​

Controls image sources:

  • 'self' - Your own images
  • data: - Required for data URIs (card brand icons)
  • framepay.payments.ai - FramePay images
  • *.paypal.com - PayPal logos
  • *.google.com - Google Pay logos

font-src​

Controls font sources:

  • 'self' - Your own fonts
  • fonts.gstatic.com - Google Fonts (if used)

Payment Method Specific Configuration​

Card Payments Only​

<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline' framepay.payments.ai;
connect-src 'self' framepay.payments.ai *.payments.ai;
style-src 'self' 'unsafe-inline' framepay.payments.ai;
frame-src 'self' framepay.payments.ai;
img-src 'self' data: framepay.payments.ai;
">

Apple Pay​

Add these domains for Apple Pay:

script-src: *.cdn-apple.com
connect-src: *.apple.com

Google Pay​

Add these domains for Google Pay:

script-src: *.google.com
connect-src: *.google.com
frame-src: *.google.com
img-src: *.google.com

PayPal​

Add these domains for PayPal:

script-src: *.paypal.com
connect-src: *.paypal.com
frame-src: *.paypal.com
img-src: *.paypal.com

Using Nonces (Production)​

For better security, use nonces instead of 'unsafe-inline':

Backend (Node.js/Express)​

const crypto = require('crypto');

app.use((req, res, next) => {
// Generate nonce for this request
const nonce = crypto.randomBytes(16).toString('base64');
res.locals.nonce = nonce;

res.setHeader(
'Content-Security-Policy',
`default-src 'self'; ` +
`script-src 'self' 'nonce-${nonce}' framepay.payments.ai; ` +
`style-src 'self' 'nonce-${nonce}' framepay.payments.ai;`
);
next();
});

Frontend​

<!-- Use the nonce in your script tags -->
<script nonce="<%= nonce %>">
Framepay.initialize({
publishableKey: 'pk_sandbox_xxx',
// ... config
});
</script>

Testing CSP Configuration​

Browser Console​

Open your browser's developer console (F12) and look for CSP violations:

Refused to load the script 'https://example.com/script.js' because it
violates the following Content Security Policy directive...

CSP Report Mode​

Test your CSP without blocking resources using Content-Security-Policy-Report-Only:

<meta http-equiv="Content-Security-Policy-Report-Only" content="
default-src 'self';
script-src 'self' 'unsafe-inline' framepay.payments.ai;
report-uri /csp-violation-report-endpoint;
">

This will report violations without blocking them, allowing you to test safely.

Online Tools​

Use these tools to validate your CSP:

Common Issues​

Issue: FramePay not loading​

Symptom: FramePay fields don't appear

Solution: Ensure script-src includes framepay.payments.ai and frame-src allows framepay.payments.ai

script-src 'self' 'unsafe-inline' framepay.payments.ai;
frame-src 'self' framepay.payments.ai;

Issue: Card brand icons not showing​

Symptom: Visa, Mastercard logos don't appear

Solution: Add data: to img-src:

img-src 'self' data: framepay.payments.ai;

Issue: Wallet buttons not working​

Symptom: Apple Pay/Google Pay/PayPal buttons don't respond

Solution: Add wallet provider domains to all relevant directives:

script-src 'self' 'unsafe-inline' framepay.payments.ai *.paypal.com *.google.com;
connect-src 'self' framepay.payments.ai *.payments.ai *.paypal.com *.google.com;
frame-src 'self' framepay.payments.ai *.paypal.com *.google.com;

Issue: HTTPS mixed content​

Symptom: Console shows mixed content warnings

Solution: Ensure your page is served over HTTPS in production. CSP cannot fix HTTP served over HTTPS.

Best Practices​

✅ Do​

  • Use HTTP headers over meta tags when possible
  • Start with Content-Security-Policy-Report-Only for testing
  • Be as restrictive as possible while allowing necessary domains
  • Use nonces or hashes instead of 'unsafe-inline' in production
  • Document your CSP configuration
  • Monitor CSP violation reports

❌ Don't​

  • Use 'unsafe-eval' - it's not required for FramePay
  • Allow * wildcards - they defeat the purpose of CSP
  • Forget to test on all payment methods you support
  • Mix HTTP and HTTPS content
  • Skip CSP validation in staging environments

Environment-Specific Configuration​

Development​

Content-Security-Policy-Report-Only: ...

Use report-only mode to identify issues without breaking functionality.

Staging​

Content-Security-Policy: ...

Enforce CSP but with more permissive settings for testing.

Production​

Content-Security-Policy: ... (strict configuration)

Use the strictest possible CSP with nonces and minimal wildcards.

Additional Security Headers​

Consider adding these headers alongside CSP:

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
Referrer-Policy: strict-origin-when-cross-origin

Resources​

Next Steps​