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();
});