mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Include OAuth targets in "form-action" Content-Security-Policy
Summary: Ref T4340. Some "Register/Login" and "Link External Account" buttons are forms which submit to third-party sites. Whitelist these targets when pages render an OAuth form. Safari, at least, also prevents a redirect to a third-party domain after a form submission to the local domain, so when we first redirect locally (as with Twitter and other OAuth1 providers) we need to authorize an additional URI. Test Plan: Clicked all my registration buttons locally without hitting CSP issues. Maniphest Tasks: T4340 Differential Revision: https://secure.phabricator.com/D19159
This commit is contained in:
parent
d5befb1a0e
commit
94d340fcff
6 changed files with 29 additions and 14 deletions
|
@ -24,9 +24,10 @@ abstract class AphrontResponse extends Phobject {
|
|||
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 @@ abstract class AphrontResponse extends Phobject {
|
|||
|
||||
// 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 @@ abstract class AphrontResponse extends Phobject {
|
|||
// 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 "<base>" to change the origin of relative URIs on the page.
|
||||
$csp[] = "base-uri 'none'";
|
||||
|
@ -177,7 +178,7 @@ abstract class AphrontResponse extends Phobject {
|
|||
}
|
||||
$sources = array_unique($sources);
|
||||
|
||||
return "{$type}-src ".implode(' ', $sources);
|
||||
return $type.' '.implode(' ', $sources);
|
||||
}
|
||||
|
||||
private function newContentSecurityPolicySource($uri) {
|
||||
|
|
|
@ -447,6 +447,13 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
|||
));
|
||||
}
|
||||
|
||||
$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 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
|||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
protected function getContentSecurityPolicyFormActions() {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -208,6 +208,9 @@ abstract class PhabricatorOAuth1AuthProvider
|
|||
parent::willRenderLinkedAccount($viewer, $item, $account);
|
||||
}
|
||||
|
||||
protected function getContentSecurityPolicyFormActions() {
|
||||
return $this->getAdapter()->getContentSecurityPolicyFormActions();
|
||||
}
|
||||
|
||||
/* -( Temporary Secrets )-------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -285,8 +285,8 @@ final class PhortuneStripePaymentProvider extends PhortunePaymentProvider {
|
|||
->addScript($src);
|
||||
|
||||
CelerityAPI::getStaticResourceResponse()
|
||||
->addContentSecurityPolicyURI('script', $src)
|
||||
->addContentSecurityPolicyURI('frame', $src);
|
||||
->addContentSecurityPolicyURI('script-src', $src)
|
||||
->addContentSecurityPolicyURI('frame-src', $src);
|
||||
|
||||
Javelin::initBehavior(
|
||||
'stripe-payment-form',
|
||||
|
|
|
@ -43,9 +43,9 @@ final class AphrontFormRecaptchaControl extends AphrontFormControl {
|
|||
$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(
|
||||
|
|
|
@ -584,7 +584,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
|
|||
) + $this->buildAphlictListenConfigData());
|
||||
|
||||
CelerityAPI::getStaticResourceResponse()
|
||||
->addContentSecurityPolicyURI('connect', $client_uri);
|
||||
->addContentSecurityPolicyURI('connect-src', $client_uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue