fileoverview import { CheckerFunction } from '../checks/checker' ; import { checkInvalidKeyword , checkMissingSemicolon , checkUnknownDirective } from '../checks/parser_checks' ; import { checkDeprecatedDirective , checkMissingObjectSrcDirective , checkMissingScriptSrcDirective , checkMultipleMissingBaseUriDirective , checkNonceLength , checkPlainUrlSchemes , checkScriptUnsafeInline , checkWildcards } from '../checks/security_checks' ; import { checkAllowlistFallback , checkStrictDynamic , checkUnsafeInlineFallback } from '../checks/strictcsp_checks' ; import { Csp , Directive , Version } from '../csp' ; import { Finding } from '../finding' ; interface Equalable { equals ( a ) : boolean ; } function arrayContains < T extends Equalable > ( arr , elem ) { return arr . some ( e => e . equals ( elem ) ) ; } /**
 * Computes the intersection of all of the given sets using the `equals(...)`
 * method to compare items.
 */ function setIntersection < T extends Equalable > ( sets ) { const intersection = [ ] ; if ( sets . length === 0 ) { return intersection ; } const firstSet = sets [ 0 ] ; for ( const elem of firstSet ) { if ( sets . every ( set => arrayContains ( set , elem ) ) ) { intersection . push ( elem ) ; } } return intersection ; } /**
 * Computes the union of all of the given sets using the `equals(...)` method to
 * compare items.
 */ function setUnion < T extends Equalable > ( sets ) { const union = [ ] ; for ( const set of sets ) { for ( const elem of set ) { if ( ! arrayContains ( union , elem ) ) { union . push ( elem ) ; } } } return union ; } /**
 * Checks if *any* of the given policies pass the given checker. If at least one
 * passes, returns no findings. Otherwise, returns the list of findings from the
 * first one that had any findings.
 */ function atLeastOnePasses ( parsedCsps , checker ) { const findings = [ ] ; for ( const parsedCsp of parsedCsps ) { findings . push ( checker ( parsedCsp ) ) ; } return setIntersection ( findings ) ; } /**
 * Checks if *any* of the given policies fail the given checker. Returns the
 * list of findings from the one that had the most findings.
 */ function atLeastOneFails ( parsedCsps , checker ) { const findings = [ ] ; for ( const parsedCsp of parsedCsps ) { findings . push ( checker ( parsedCsp ) ) ; } return setUnion ( findings ) ; } /**
 * Evaluate the given list of CSPs for checks that should cause Lighthouse to
 * mark the CSP as failing. Returns only the first set of failures.
 */ export function evaluateForFailure ( parsedCsps ) { const targetsXssFindings = [ ... atLeastOnePasses ( parsedCsps , checkMissingScriptSrcDirective ) , ... atLeastOnePasses ( parsedCsps , checkMissingObjectSrcDirective ) , ... checkMultipleMissingBaseUriDirective ( parsedCsps ) , ] ; const effectiveCsps = parsedCsps . map ( csp => csp . getEffectiveCsp ( Version . CSP3 ) ) ; const effectiveCspsWithScript = effectiveCsps . filter ( csp => { const directiveName = csp . getEffectiveDirective ( Directive . SCRIPT_SRC ) ; return csp . directives [ directiveName ] ; } ) ; const robust = [ ... atLeastOnePasses ( effectiveCspsWithScript , checkStrictDynamic ) , ... atLeastOnePasses ( effectiveCspsWithScript , checkScriptUnsafeInline ) , ... atLeastOnePasses ( effectiveCsps , checkWildcards ) , ... atLeastOnePasses ( effectiveCsps , checkPlainUrlSchemes ) , ] ; return [ ... targetsXssFindings , ... robust ] ; } /**
 * Evaluate the given list of CSPs for checks that should cause Lighthouse to
 * mark the CSP as OK, but present a warning. Returns only the first set of
 * failures.
 */ export function evaluateForWarnings ( parsedCsps ) { return [ ... atLeastOneFails ( parsedCsps , checkUnsafeInlineFallback ) , ... atLeastOneFails ( parsedCsps , checkAllowlistFallback ) ] ; } /**
 * Evaluate the given list of CSPs for syntax errors. Returns a list of the same
 * length as parsedCsps where each item in the list is the findings for the
 * matching Csp.
 */ export function evaluateForSyntaxErrors ( parsedCsps ) { const allFindings = [ ] ; for ( const csp of parsedCsps ) { const findings = [ ... checkNonceLength ( csp ) , ... checkUnknownDirective ( csp ) , ... checkDeprecatedDirective ( csp ) , ... checkMissingSemicolon ( csp ) , ... checkInvalidKeyword ( csp ) ] ; allFindings . push ( findings ) ; } return allFindings ; }