60 $this->response->header(
61 "$headerName: $policy"
81 $cspConfig =
$context->getConfig()->get(
'CSPHeader' );
82 $cspConfigReportOnly =
$context->getConfig()->get(
'CSPReportOnlyHeader' );
84 $csp->sendCSPHeader( $cspConfig, self::FULL_MODE );
85 $csp->sendCSPHeader( $cspConfigReportOnly, self::REPORT_ONLY_MODE );
103 if ( $reportOnly === self::REPORT_ONLY_MODE ) {
104 return 'Content-Security-Policy-Report-Only';
105 } elseif ( $reportOnly === self::FULL_MODE ) {
106 return 'Content-Security-Policy';
108 throw new UnexpectedValueException( $reportOnly );
119 if ( $policyConfig ===
false ) {
123 if ( $policyConfig ===
true ) {
137 $defaultSrc = [
'*',
'data:',
'blob:' ];
141 $scriptSrc = [
"'unsafe-eval'",
"'self'" ];
142 if ( !isset( $policyConfig[
'useNonces'] ) || $policyConfig[
'useNonces'] ) {
143 $scriptSrc[] =
"'nonce-" . $this->nonce .
"'";
146 $scriptSrc = array_merge( $scriptSrc, $additionalSelfUrlsScript );
147 if ( isset( $policyConfig[
'script-src'] )
148 && is_array( $policyConfig[
'script-src'] )
150 foreach ( $policyConfig[
'script-src'] as $src ) {
155 if ( ( !isset( $policyConfig[
'unsafeFallback'] )
156 || $policyConfig[
'unsafeFallback'] )
163 $scriptSrc[] =
"'unsafe-inline'";
169 if ( isset( $policyConfig[
'default-src'] )
170 && $policyConfig[
'default-src'] !==
false
172 $defaultSrc = array_merge(
173 [
"'self'",
'data:',
'blob:' ],
176 if ( is_array( $policyConfig[
'default-src'] ) ) {
177 foreach ( $policyConfig[
'default-src'] as $src ) {
183 if ( !isset( $policyConfig[
'includeCORS'] ) || $policyConfig[
'includeCORS'] ) {
185 if ( !in_array(
'*', $defaultSrc ) ) {
186 $defaultSrc = array_merge( $defaultSrc, $CORSUrls );
190 if ( !in_array(
'*', $scriptSrc ) ) {
191 $scriptSrc = array_merge( $scriptSrc, $CORSUrls );
195 Hooks::run(
'ContentSecurityPolicyDefaultSource', [ &$defaultSrc, $policyConfig, $mode ] );
196 Hooks::run(
'ContentSecurityPolicyScriptSource', [ &$scriptSrc, $policyConfig, $mode ] );
199 if ( is_array( $defaultSrc ) ) {
200 $cssSrc = array_merge( $defaultSrc, [
"'unsafe-inline'" ] );
203 if ( isset( $policyConfig[
'report-uri'] ) && $policyConfig[
'report-uri'] !==
true ) {
204 if ( $policyConfig[
'report-uri'] ===
false ) {
214 if ( !is_array( $defaultSrc )
215 || !in_array(
'*', $defaultSrc )
216 || !in_array(
'data:', $defaultSrc )
217 || !in_array(
'blob:', $defaultSrc )
228 $imgSrc = [
'*',
'data:',
'blob:' ];
230 $whitelist =
wfMessage(
'external_image_whitelist' )
231 ->inContentLanguage()
233 if ( preg_match(
'/^\s*[^\s#]/m', $whitelist ) ) {
234 $imgSrc = [
'*',
'data:',
'blob:' ];
241 $directives[] =
'script-src ' . implode(
' ', $scriptSrc );
244 $directives[] =
'default-src ' . implode(
' ', $defaultSrc );
247 $directives[] =
'style-src ' . implode(
' ', $cssSrc );
250 $directives[] =
'img-src ' . implode(
' ', $imgSrc );
253 $directives[] =
'report-uri ' . $reportUri;
256 Hooks::run(
'ContentSecurityPolicyDirectives', [ &$directives, $policyConfig, $mode ] );
258 return implode(
'; ', $directives );
270 'action' =>
'cspreport',
273 if ( $mode === self::REPORT_ONLY_MODE ) {
274 $apiArguments[
'reportonly'] =
'1';
303 if ( preg_match(
'/^[a-z][a-z0-9+.-]*:$/i', $url ) ) {
308 if ( !$bits && strpos( $url,
'/' ) ===
false ) {
314 if ( $bits && isset( $bits[
'host'] )
315 && $bits[
'host'] !== $this->mwConfig->get(
'ServerName' )
317 $result = $bits[
'host'];
318 if ( $bits[
'scheme'] !==
'' ) {
319 $result = $bits[
'scheme'] . $bits[
'delimiter'] .
$result;
321 if ( isset( $bits[
'port'] ) ) {
322 $result .=
':' . $bits[
'port'];
335 $additionalUrls = [];
337 $pathVars = [
'LoadScript',
'ExtensionAssetsPath',
'ResourceBasePath' ];
339 foreach ( $pathVars as $path ) {
340 $url = $this->mwConfig->get( $path );
342 if ( $preparedUrl ) {
343 $additionalUrls[] = $preparedUrl;
346 $RLSources = $this->mwConfig->get(
'ResourceLoaderSources' );
347 foreach ( $RLSources as $wiki => $sources ) {
348 foreach ( $sources as $id =>
$value ) {
351 $additionalUrls[] = $url;
356 return array_unique( $additionalUrls );
371 $additionalSelfUrls = [];
378 $callback =
function ( $repo, &
$urls ) {
379 $urls[] = $repo->getZoneUrl(
'public' );
380 $urls[] = $repo->getZoneUrl(
'transcoded' );
381 $urls[] = $repo->getZoneUrl(
'thumb' );
382 $urls[] = $repo->getDescriptionStylesheetUrl();
385 $callback( $localRepo, $pathUrls );
389 $pathGlobals = [
'LoadScript',
'ExtensionAssetsPath',
'StylePath',
'ResourceBasePath' ];
390 foreach ( $pathGlobals as $path ) {
391 $pathUrls[] = $this->mwConfig->get( $path );
393 foreach ( $pathUrls as $path ) {
395 if ( $preparedUrl !==
false ) {
396 $additionalSelfUrls[] = $preparedUrl;
399 $RLSources = $this->mwConfig->get(
'ResourceLoaderSources' );
401 foreach ( $RLSources as $wiki => $sources ) {
402 foreach ( $sources as $id =>
$value ) {
405 $additionalSelfUrls[] = $url;
410 return array_unique( $additionalSelfUrls );
426 $additionalUrls = [];
427 $CORSSources = $this->mwConfig->get(
'CrossSiteAJAXdomains' );
428 foreach ( $CORSSources as
$source ) {
429 if ( strpos(
$source,
'?' ) !==
false ) {
435 $additionalUrls[] = $url;
438 return $additionalUrls;
467 return (
bool)preg_match(
'!Firefox/4[0-2]\.!', $ua );
478 $config->
get(
'CSPHeader' ),
479 $config->
get(
'CSPReportOnlyHeader' )
481 foreach ( $configs as $headerConfig ) {
483 $headerConfig ===
true ||
484 ( is_array( $headerConfig ) &&
485 !isset( $headerConfig[
'useNonces'] ) ) ||
486 ( is_array( $headerConfig ) &&
487 isset( $headerConfig[
'useNonces'] ) &&
488 $headerConfig[
'useNonces'] )
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
getAdditionalSelfUrls()
Get additional host names for the wiki (e.g.
__construct( $nonce, WebResponse $response, Config $mwConfig)
static isNonceRequired(Config $config)
Should we set nonce attribute.
prepareUrlForCSP( $url)
Given a url, convert to form needed for CSP.
makeCSPDirectives( $policyConfig, $mode)
Determine what CSP policies to set for this page.
static falsePositiveBrowser( $ua)
Does this browser give false positive reports?
getHeaderName( $reportOnly)
Get the name of the HTTP header to use.
static sendHeaders(IContextSource $context)
Send CSP headers based on wiki config.
escapeUrlForCSP( $url)
CSP spec says ',' and ';' are not allowed to appear in urls.
string $nonce
The nonce to use for inline scripts (from OutputPage)
getReportUri( $mode)
Get the default report uri.
getCORSSources()
include domains that are allowed to send us CORS requests.
getAdditionalSelfUrlsScript()
Get additional script sources.
sendCSPHeader( $csp, $reportOnly)
Send a single CSP header based on a given policy config.
Config $mwConfig
The site configuration object.
static singleton()
Get a RepoGroup instance.
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
namespace being checked & $result
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "<div ...>$1</div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
Interface for configuration instances.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Interface for objects which can provide a MediaWiki context on request.