Combining Advanced Patterns
Combining Advanced Patterns
Effective CSP implementation often requires combining multiple advanced patterns:
// Advanced CSP Pattern Combinator
class AdvancedCSPCombinator {
constructor() {
this.nonceManager = new NonceManager();
this.hashManager = new HashBasedCSP();
this.strictDynamic = new StrictDynamicCSP();
}
// Hybrid approach: Nonces for dynamic, hashes for static
generateHybridPolicy(options = {}) {
const nonce = this.nonceManager.generateNonce();
const policy = {
'default-src': ["'none'"],
'script-src': [
"'self'",
`'nonce-${nonce}'`,
"'strict-dynamic'",
...this.hashManager.hashes.scripts
],
'style-src': [
"'self'",
`'nonce-${nonce}'`,
...this.hashManager.hashes.styles
],
'img-src': ["'self'", 'data:', 'https:'],
'font-src': ["'self'", 'https://fonts.gstatic.com'],
'connect-src': ["'self'"],
'worker-src': ["'self'", 'blob:'],
'frame-ancestors': ["'none'"],
'base-uri': ["'none'"],
'form-action': ["'self'"],
'upgrade-insecure-requests': ['']
};
// Add backward compatibility
if (options.backwardCompatible) {
policy['script-src'].push('https:', "'unsafe-inline'");
}
return {
nonce,
policy: this.formatPolicy(policy)
};
}
// Progressive enhancement strategy
implementProgressiveEnhancement() {
return {
// Level 1: Basic CSP (wide browser support)
level1: {
policy: "default-src 'self'; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline'",
support: 'CSP 1.0+'
},
// Level 2: Nonce-based (modern browsers)
level2: {
policy: (nonce) => `default-src 'self'; script-src 'self' 'nonce-${nonce}'; style-src 'self' 'nonce-${nonce}'`,
support: 'CSP 2.0+'
},
// Level 3: Strict-dynamic (latest browsers)
level3: {
policy: (nonce) => `default-src 'none'; script-src 'nonce-${nonce}' 'strict-dynamic'; style-src 'self' 'nonce-${nonce}'`,
support: 'CSP 3.0+'
}
};
}
// Feature detection for CSP support
generateFeatureDetectionScript() {
return `
(function() {
const cspSupport = {
basic: false,
nonce: false,
hash: false,
strictDynamic: false,
reportTo: false
};
// Test basic CSP support
try {
const meta = document.createElement('meta');
meta.httpEquiv = 'Content-Security-Policy';
meta.content = "default-src 'none'";
document.head.appendChild(meta);
document.head.removeChild(meta);
cspSupport.basic = true;
} catch (e) {}
// Test nonce support
if (document.currentScript && document.currentScript.nonce) {
cspSupport.nonce = true;
}
// Test strict-dynamic support
try {
const testPolicy = "script-src 'strict-dynamic' 'nonce-test'";
cspSupport.strictDynamic = true;
} catch (e) {}
// Store results
window.__CSP_SUPPORT__ = cspSupport;
// Report to analytics
if (window.analytics) {
window.analytics.track('CSP Support', cspSupport);
}
})();
`;
}
formatPolicy(policy) {
return Object.entries(policy)
.filter(([_, values]) => values.length > 0)
.map(([directive, sources]) =>
directive === 'upgrade-insecure-requests'
? directive
: `${directive} ${sources.join(' ')}`
)
.join('; ');
}
}