diff --git a/src/aphront/response/AphrontResponse.php b/src/aphront/response/AphrontResponse.php --- a/src/aphront/response/AphrontResponse.php +++ b/src/aphront/response/AphrontResponse.php @@ -24,9 +24,10 @@ final public function addContentSecurityPolicyURI($kind, $uri) { if ($this->contentSecurityPolicyURIs === null) { $this->contentSecurityPolicyURIs = array( - 'script' => array(), - 'connect' => array(), - 'frame' => array(), + 'script-src' => array(), + 'connect-src' => array(), + 'frame-src' => array(), + 'form-action' => array(), ); } @@ -125,14 +126,14 @@ // On a small number of pages, including the Stripe workflow and the // ReCAPTCHA challenge, we embed external Javascript directly. - $csp[] = $this->newContentSecurityPolicy('script', $default); + $csp[] = $this->newContentSecurityPolicy('script-src', $default); // We need to specify that we can connect to ourself in order for AJAX // requests to work. - $csp[] = $this->newContentSecurityPolicy('connect', "'self'"); + $csp[] = $this->newContentSecurityPolicy('connect-src', "'self'"); // DarkConsole and PHPAST both use frames to render some content. - $csp[] = $this->newContentSecurityPolicy('frame', "'self'"); + $csp[] = $this->newContentSecurityPolicy('frame-src', "'self'"); // This is a more modern flavor of of "X-Frame-Options" and prevents // clickjacking attacks where the page is included in a tiny iframe and @@ -152,7 +153,7 @@ // This can result in some trickiness with file downloads if applications // try to start downloads by submitting a dialog. Redirect to the file's // download URI instead of submitting a form to it. - $csp[] = "form-action 'self'"; + $csp[] = $this->newContentSecurityPolicy('form-action', "'self'"); // Block use of "" to change the origin of relative URIs on the page. $csp[] = "base-uri 'none'"; @@ -177,7 +178,7 @@ } $sources = array_unique($sources); - return "{$type}-src ".implode(' ', $sources); + return $type.' '.implode(' ', $sources); } private function newContentSecurityPolicySource($uri) { diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php --- a/src/applications/auth/provider/PhabricatorAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorAuthProvider.php @@ -447,6 +447,13 @@ )); } + $static_response = CelerityAPI::getStaticResourceResponse(); + $static_response->addContentSecurityPolicyURI('form-action', (string)$uri); + + foreach ($this->getContentSecurityPolicyFormActions() as $csp_uri) { + $static_response->addContentSecurityPolicyURI('form-action', $csp_uri); + } + return phabricator_form( $viewer, array( @@ -505,4 +512,8 @@ throw new PhutilMethodNotImplementedException(); } + protected function getContentSecurityPolicyFormActions() { + return array(); + } + } diff --git a/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php b/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php --- a/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php +++ b/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php @@ -208,6 +208,9 @@ parent::willRenderLinkedAccount($viewer, $item, $account); } + protected function getContentSecurityPolicyFormActions() { + return $this->getAdapter()->getContentSecurityPolicyFormActions(); + } /* -( Temporary Secrets )-------------------------------------------------- */ diff --git a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php --- a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php +++ b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php @@ -285,8 +285,8 @@ ->addScript($src); CelerityAPI::getStaticResourceResponse() - ->addContentSecurityPolicyURI('script', $src) - ->addContentSecurityPolicyURI('frame', $src); + ->addContentSecurityPolicyURI('script-src', $src) + ->addContentSecurityPolicyURI('frame-src', $src); Javelin::initBehavior( 'stripe-payment-form', diff --git a/src/view/form/control/AphrontFormRecaptchaControl.php b/src/view/form/control/AphrontFormRecaptchaControl.php --- a/src/view/form/control/AphrontFormRecaptchaControl.php +++ b/src/view/form/control/AphrontFormRecaptchaControl.php @@ -43,9 +43,9 @@ $pubkey = PhabricatorEnv::getEnvConfig('recaptcha.public-key'); CelerityAPI::getStaticResourceResponse() - ->addContentSecurityPolicyURI('script', $js) - ->addContentSecurityPolicyURI('script', 'https://www.gstatic.com/') - ->addContentSecurityPolicyURI('frame', 'https://www.google.com/'); + ->addContentSecurityPolicyURI('script-src', $js) + ->addContentSecurityPolicyURI('script-src', 'https://www.gstatic.com/') + ->addContentSecurityPolicyURI('frame-src', 'https://www.google.com/'); return array( phutil_tag( diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -584,7 +584,7 @@ ) + $this->buildAphlictListenConfigData()); CelerityAPI::getStaticResourceResponse() - ->addContentSecurityPolicyURI('connect', $client_uri); + ->addContentSecurityPolicyURI('connect-src', $client_uri); } }