You are here

private static function Csp::reduceSourceList in Content-Security-Policy 8

Reduce a list of sources to a minimal set.

Parameters

array $sources: The array of sources.

Return value

array The reduced set of sources.

1 call to Csp::reduceSourceList()
Csp::getHeaderValue in src/Csp.php
Get the header value.

File

src/Csp.php, line 453

Class

Csp
A CSP Header.

Namespace

Drupal\csp

Code

private static function reduceSourceList(array $sources) {
  $sources = array_unique($sources);

  // 'none' overrides any other sources.
  if (in_array(Csp::POLICY_NONE, $sources)) {
    return [
      Csp::POLICY_NONE,
    ];
  }

  // Global wildcard covers all network scheme sources.
  if (in_array(Csp::POLICY_ANY, $sources)) {
    $sources = array_filter($sources, function ($source) {

      // Keep any values that are a quoted string, or non-network scheme.
      // e.g. '* https: data: example.com' -> '* data:'
      // https://www.w3.org/TR/CSP/#match-url-to-source-expression
      return strpos($source, "'") === 0 || preg_match('<^(?!(?:https?|wss?|ftp):)([a-z]+:)>', $source);
    });
    array_unshift($sources, Csp::POLICY_ANY);
  }

  // Remove protocol-prefixed hosts if protocol is allowed.
  // e.g. 'http: data: example.com https://example.com' -> 'http: data: example.com'
  $protocols = array_filter($sources, function ($source) {
    return preg_match('<^(https?|wss?|ftp):$>', $source);
  });
  if (!empty($protocols)) {
    if (in_array('http:', $protocols)) {
      $protocols[] = 'https:';
    }
    if (in_array('ws:', $protocols)) {
      $protocols[] = 'wss:';
    }
    $sources = array_filter($sources, function ($source) use ($protocols) {
      return !preg_match('<^(' . implode('|', $protocols) . ')//>', $source);
    });
  }
  return $sources;
}