diff --git a/index.html b/index.html index 03d8f2b..757889a 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ Control Vault diff --git a/public/_headers b/public/_headers index 21a03d1..b7a1e1f 100644 --- a/public/_headers +++ b/public/_headers @@ -3,7 +3,7 @@ # Toute modification de ce fichier est une modification de sécurité : revue humaine obligatoire. /* - Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; manifest-src 'self'; worker-src 'self'; object-src 'none'; base-uri 'self'; form-action 'none'; frame-ancestors 'none' + Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; manifest-src 'self'; worker-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none' X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin diff --git a/scripts/security-check.ts b/scripts/security-check.ts index 13320c7..29007c3 100644 --- a/scripts/security-check.ts +++ b/scripts/security-check.ts @@ -53,7 +53,9 @@ export function checkCsp(csp: string, opts: { requireFrameAncestors: boolean }): if (/'unsafe-inline'/.test(script)) problems.push("'unsafe-inline' interdit dans script-src"); if (/(^|\s)\*(\s|;|$)/.test(csp)) problems.push('joker * interdit'); if (!dir('object-src')?.includes("'none'")) problems.push("object-src 'none' requis"); - if (!dir('base-uri')) problems.push('base-uri requis'); + const base = dir('base-uri'); + if (!base) problems.push('base-uri requis'); + else if (base.split(/\s+/).join(' ') !== "base-uri 'none'") problems.push("base-uri 'none' requis"); if (opts.requireFrameAncestors && !dir('frame-ancestors')?.includes("'none'")) problems.push("frame-ancestors 'none' requis"); return problems; } diff --git a/tests/unit/security-check.test.ts b/tests/unit/security-check.test.ts index 38828c8..d43927f 100644 --- a/tests/unit/security-check.test.ts +++ b/tests/unit/security-check.test.ts @@ -36,6 +36,12 @@ describe('détection de secrets', () => { }); describe('CSP', () => { + it.each(["'self'", 'https://fixture.invalid', "'none' 'self'"])( + 'refuse une base de document autorisée : %s', (base) => { + expect(checkCsp(`default-src 'self'; script-src 'self'; object-src 'none'; base-uri ${base}`, + { requireFrameAncestors: false })).toContain("base-uri 'none' requis"); + }); + it('refuse unsafe-eval, unsafe-inline dans script-src et le joker', () => { expect(checkCsp("default-src 'self'; script-src 'self' 'unsafe-eval'; object-src 'none'; base-uri 'self'", { requireFrameAncestors: false })).toContain("'unsafe-eval' interdit"); expect(checkCsp("default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'", { requireFrameAncestors: false })).toContain("'unsafe-inline' interdit dans script-src");