Policy Optimization and Performance

Policy Optimization and Performance

CSP can impact performance if not optimized properly. Implementing performance-conscious CSP ensures security without degrading user experience:

// CSP Performance Optimizer
class CSPPerformanceOptimizer {
  constructor() {
    this.metrics = new Map();
    this.optimizations = [];
  }
  
  analyzePerformanceImpact(policy) {
    const analysis = {
      policySize: this.calculatePolicySize(policy),
      parseComplexity: this.assessParseComplexity(policy),
      resourceBlocking: this.evaluateResourceBlocking(policy),
      recommendations: []
    };
    
    // Policy size optimization
    if (analysis.policySize > 1024) {
      analysis.recommendations.push({
        issue: 'Large policy size',
        impact: 'Increased header overhead',
        solution: 'Consider using CSP meta tags for static policies'
      });
    }
    
    // Complexity optimization
    if (analysis.parseComplexity > 50) {
      analysis.recommendations.push({
        issue: 'Complex policy structure',
        impact: 'Slower policy parsing',
        solution: 'Simplify directives and consolidate sources'
      });
    }
    
    return analysis;
  }
  
  optimizePolicy(policy) {
    const optimized = {};
    
    Object.entries(policy).forEach(([directive, sources]) => {
      // Remove duplicates
      const uniqueSources = [...new Set(sources)];
      
      // Consolidate domains
      const consolidated = this.consolidateDomains(uniqueSources);
      
      // Sort for consistency
      optimized[directive] = consolidated.sort();
    });
    
    return optimized;
  }
  
  consolidateDomains(sources) {
    const domains = new Map();
    
    sources.forEach(source => {
      if (source.startsWith('https://') || source.startsWith('http://')) {
        const url = new URL(source);
        const domain = url.hostname;
        
        if (!domains.has(domain)) {
          domains.set(domain, new Set());
        }
        
        domains.get(domain).add(url.pathname);
      }
    });
    
    // Consolidate subdomains where possible
    const consolidated = [];
    domains.forEach((paths, domain) => {
      if (paths.size === 1 && paths.has('/')) {
        consolidated.push(`https://${domain}`);
      } else {
        paths.forEach(path => {
          consolidated.push(`https://${domain}${path}`);
        });
      }
    });
    
    return consolidated;
  }
  
  implementCaching() {
    return {
      clientSide: `
        // Cache CSP nonce for session
        class CSPNonceCache {
          constructor() {
            this.nonce = this.getOrCreateNonce();
          }
          
          getOrCreateNonce() {
            const cached = sessionStorage.getItem('csp-nonce');
            if (cached && this.isValid(cached)) {
              return cached;
            }
            
            const newNonce = this.extractNonce();
            sessionStorage.setItem('csp-nonce', newNonce);
            return newNonce;
          }
          
          extractNonce() {
            const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
            if (meta) {
              const match = meta.content.match(/nonce-([A-Za-z0-9+/=]+)/);
              return match ? match[1] : null;
            }
            return null;
          }
        }
      `,
      
      serverSide: `
        // Server-side CSP caching
        const CSPCache = require('node-cache');
        const cspCache = new CSPCache({ stdTTL: 600 }); // 10 minute cache
        
        function getCachedPolicy(userContext) {
          const key = generateCacheKey(userContext);
          let policy = cspCache.get(key);
          
          if (!policy) {
            policy = generatePolicy(userContext);
            cspCache.set(key, policy);
          }
          
          return policy;
        }
      `
    };
  }
}