Frame Ancestors and Clickjacking Issues
Frame Ancestors and Clickjacking Issues
Frame-ancestors violations occur when sites attempt to embed your content in ways that violate your CSP:
// Common Error: Frame ancestors violation
// Console: Refused to frame 'https://example.com' because an ancestor violates the
// following Content Security Policy directive: "frame-ancestors 'self'"
// PROBLEM: Incorrect frame-ancestors configuration
// Too restrictive:
Content-Security-Policy: frame-ancestors 'none';
// SOLUTION 1: Allow specific trusted domains
Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com;
// SOLUTION 2: Dynamic frame-ancestors based on partnership
class FrameAncestorsManager {
constructor() {
this.partners = new Map();
}
addPartner(domain, options = {}) {
this.partners.set(domain, {
allowed: true,
paths: options.paths || ['*'],
validUntil: options.validUntil || null
});
}
generateFrameAncestorsPolicy(request) {
const referer = request.headers.referer;
const allowedAncestors = ["'self'"];
if (referer) {
const refererDomain = new URL(referer).origin;
const partner = this.partners.get(refererDomain);
if (partner && partner.allowed) {
// Check if partnership is still valid
if (!partner.validUntil || new Date() < partner.validUntil) {
allowedAncestors.push(refererDomain);
}
}
}
return `frame-ancestors ${allowedAncestors.join(' ')}`;
}
}
// SOLUTION 3: Provide embedding instructions
// Create an embed endpoint with relaxed CSP
app.get('/embed/*', (req, res, next) => {
// Special CSP for embeddable content
res.setHeader('Content-Security-Policy',
"frame-ancestors *; " +
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline'; " +
"style-src 'self' 'unsafe-inline';"
);
next();
});