diff --git a/review-enrichment/src/analyzers/iac-misconfig.ts b/review-enrichment/src/analyzers/iac-misconfig.ts index 9734099bc6..960cb4bcec 100644 --- a/review-enrichment/src/analyzers/iac-misconfig.ts +++ b/review-enrichment/src/analyzers/iac-misconfig.ts @@ -112,6 +112,10 @@ const DOCKER_SOCKET_MOUNT_RE = const HSTS_DISABLED_RE = /\bStrict-Transport-Security\b[^\n]*\bmax-age\s*=\s*0\b/i; const REFERRER_UNSAFE_URL_RE = /\bReferrer-Policy\b[^\n]*\bunsafe-url\b/i; const COOKIE_NOT_HTTPONLY_RE = /\bhttp[_-]?only\b[\s"'=:,-]*false\b/i; +const COOP_UNSAFE_NONE_RE = + /\bCross-Origin-Opener-Policy\b[^\n]*\bunsafe-none\b/i; +const COEP_UNSAFE_NONE_RE = + /\bCross-Origin-Embedder-Policy\b[^\n]*\bunsafe-none\b/i; function* patchLines(patch: string): Generator { let start = 0; @@ -541,6 +545,18 @@ export function scanPatchForIacMisconfig( ) { return findings; } + if ( + COOP_UNSAFE_NONE_RE.test(body) && + pushFinding(findings, seen, path, newLine, "coop-unsafe-none", maxFindings) + ) { + return findings; + } + if ( + COEP_UNSAFE_NONE_RE.test(body) && + pushFinding(findings, seen, path, newLine, "coep-unsafe-none", maxFindings) + ) { + return findings; + } newLine++; } diff --git a/review-enrichment/src/render.ts b/review-enrichment/src/render.ts index 571acdca44..12718ce59c 100644 --- a/review-enrichment/src/render.ts +++ b/review-enrichment/src/render.ts @@ -360,6 +360,10 @@ export function renderBrief( return "sets `Referrer-Policy: unsafe-url`, leaking the full URL (path and query) to cross-origin destinations"; case "cookie-not-httponly": return "sets `httpOnly: false` on a cookie, exposing it to JavaScript so an XSS can read it"; + case "coop-unsafe-none": + return "sets `Cross-Origin-Opener-Policy: unsafe-none`, allowing cross-origin pages to retain opener access"; + case "coep-unsafe-none": + return "sets `Cross-Origin-Embedder-Policy: unsafe-none`, disabling cross-origin isolation requirements for embedded resources"; } }; diff --git a/review-enrichment/src/types.ts b/review-enrichment/src/types.ts index 4a75803e29..9a04db60e3 100644 --- a/review-enrichment/src/types.ts +++ b/review-enrichment/src/types.ts @@ -270,7 +270,9 @@ export interface IacMisconfigFinding { | "docker-socket-mount" | "hsts-disabled" | "referrer-policy-leak" - | "cookie-not-httponly"; + | "cookie-not-httponly" + | "coop-unsafe-none" + | "coep-unsafe-none"; } /** A newly-added dependency whose install compiles native code (npm node-gyp addon) or has no prebuilt wheel diff --git a/review-enrichment/test/iac-misconfig.test.ts b/review-enrichment/test/iac-misconfig.test.ts index eabb8d64e3..b65ce6e5bf 100644 --- a/review-enrichment/test/iac-misconfig.test.ts +++ b/review-enrichment/test/iac-misconfig.test.ts @@ -461,6 +461,8 @@ test("scanPatchForIacMisconfig flags insecure HTTP security-header settings", () ["+ add_header Strict-Transport-Security \"max-age=0\";", "hsts-disabled"], ["+ add_header Referrer-Policy \"unsafe-url\";", "referrer-policy-leak"], ["+ httpOnly: false", "cookie-not-httponly"], + ["+ add_header Cross-Origin-Opener-Policy \"unsafe-none\";", "coop-unsafe-none"], + ["+ add_header Cross-Origin-Embedder-Policy \"unsafe-none\";", "coep-unsafe-none"], ]; for (const [added, kind] of cases) { const findings = scanPatchForIacMisconfig( @@ -482,6 +484,10 @@ test("scanPatchForIacMisconfig does not flag secure HTTP header values (incl. Ca "+ add_header Cache-Control \"max-age=0\";", "+ add_header Referrer-Policy \"strict-origin-when-cross-origin\";", "+ httpOnly: true", + "+ add_header Cross-Origin-Opener-Policy \"same-origin\";", + "+ add_header Cross-Origin-Embedder-Policy \"require-corp\";", + // A bare `unsafe-none` config key without a COOP/COEP header token must NOT fire either rule. + "+ unsafe-none = false", ]; for (const added of safe) { assert.deepEqual(