diff --git a/src/aphront/response/AphrontResponse.php b/src/aphront/response/AphrontResponse.php index e0f0730081..27c603b091 100644 --- a/src/aphront/response/AphrontResponse.php +++ b/src/aphront/response/AphrontResponse.php @@ -24,6 +24,24 @@ abstract class AphrontResponse { $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", + ); + } + return $headers; } diff --git a/src/applications/config/option/PhabricatorSecurityConfigOptions.php b/src/applications/config/option/PhabricatorSecurityConfigOptions.php index 462da00f38..7fdb0bbf32 100644 --- a/src/applications/config/option/PhabricatorSecurityConfigOptions.php +++ b/src/applications/config/option/PhabricatorSecurityConfigOptions.php @@ -223,6 +223,26 @@ final class PhabricatorSecurityConfigOptions pht( 'If you enable this, you are allowing Phabricator to '. 'potentially make requests to external servers.')), + $this->newOption('security.strict-transport-security', 'bool', false) + ->setLocked(true) + ->setBoolOptions( + array( + pht('Use HSTS'), + pht('Do Not Use HSTS'), + )) + ->setSummary(pht('Enable HTTP Strict Transport Security (HSTS).')) + ->setDescription( + pht( + 'HTTP Strict Transport Security (HSTS) sends a header which '. + 'instructs browsers that the site should only be accessed '. + 'over HTTPS, never HTTP. This defuses an attack where an '. + 'adversary gains access to your network, then proxies requests '. + 'through an unsecured link.'. + "\n\n". + 'Do not enable this option if you serve (or plan to ever serve) '. + 'unsecured content over plain HTTP. It is very difficult to '. + 'undo this change once users browsers have accepted the '. + 'setting.')), $this->newOption('security.allow-conduit-act-as-user', 'bool', false) ->setBoolOptions( array(