diff --git a/src/aphront/response/AphrontResponse.php b/src/aphront/response/AphrontResponse.php index 73c4e68f00..892417fcb1 100644 --- a/src/aphront/response/AphrontResponse.php +++ b/src/aphront/response/AphrontResponse.php @@ -1,405 +1,412 @@ request = $request; return $this; } public function getRequest() { return $this->request; } final public function addContentSecurityPolicyURI($kind, $uri) { if ($this->contentSecurityPolicyURIs === null) { $this->contentSecurityPolicyURIs = array( 'script-src' => array(), 'connect-src' => array(), 'frame-src' => array(), 'form-action' => array(), ); } if (!isset($this->contentSecurityPolicyURIs[$kind])) { throw new Exception( pht( 'Unknown Content-Security-Policy URI kind "%s".', $kind)); } $this->contentSecurityPolicyURIs[$kind][] = (string)$uri; return $this; } final public function setDisableContentSecurityPolicy($disable) { $this->disableContentSecurityPolicy = $disable; return $this; } /* -( Content )------------------------------------------------------------ */ public function getContentIterator() { return array($this->buildResponseString()); } public function buildResponseString() { throw new PhutilMethodNotImplementedException(); } /* -( Metadata )----------------------------------------------------------- */ public function getHeaders() { $headers = array(); if (!$this->frameable) { $headers[] = array('X-Frame-Options', 'Deny'); } if ($this->getRequest() && $this->getRequest()->isHTTPS()) { $hsts_key = 'security.strict-transport-security'; $use_hsts = PhabricatorEnv::getEnvConfig($hsts_key); if ($use_hsts) { $duration = phutil_units('365 days in seconds'); } else { // If HSTS has been disabled, tell browsers to turn it off. This may // not be effective because we can only disable it over a valid HTTPS // connection, but it best represents the configured intent. $duration = 0; } $headers[] = array( 'Strict-Transport-Security', "max-age={$duration}; includeSubdomains; preload", ); } $csp = $this->newContentSecurityPolicyHeader(); if ($csp !== null) { $headers[] = array('Content-Security-Policy', $csp); } $headers[] = array('Referrer-Policy', 'no-referrer'); return $headers; } private function newContentSecurityPolicyHeader() { if ($this->disableContentSecurityPolicy) { return null; } $csp = array(); $cdn = PhabricatorEnv::getEnvConfig('security.alternate-file-domain'); if ($cdn) { $default = $this->newContentSecurityPolicySource($cdn); } else { - $default = "'self'"; + // If an alternate file domain is not configured and the user is viewing + // a Phame blog on a custom domain or some other custom site, we'll still + // serve resources from the main site. Include the main site explicitly. + + $base_uri = PhabricatorEnv::getURI('/'); + $base_uri = $this->newContentSecurityPolicySource($base_uri); + + $default = "'self' {$base_uri}"; } $csp[] = "default-src {$default}"; // We use "data:" URIs to inline small images into CSS. This policy allows // "data:" URIs to be used anywhere, but there doesn't appear to be a way // to say that "data:" URIs are okay in CSS files but not in the document. $csp[] = "img-src {$default} data:"; // We use inline style="..." attributes in various places, many of which // are legitimate. We also currently use a