diff --git a/src/aphront/AphrontRequest.php b/src/aphront/AphrontRequest.php --- a/src/aphront/AphrontRequest.php +++ b/src/aphront/AphrontRequest.php @@ -256,8 +256,31 @@ } $valid = $this->getUser()->validateCSRFToken($token); + + // The CSRF check may not be valid if "security.require-https" is set but + // the connection is plain HTTP. In this case, we don't send cookies to the + // client, so they won't have an anonymous session cookie and won't be able + // to pass the CSRF check. + + // Note that this normally only happens for requests from inside + // "cluster.addresses" (usually test installs on localhost). Other + // connections will be redirected to HTTPS automatically. See T12547. if (!$valid) { + $cookie_domain = $this->getCookieDomainURI(); + if (!$cookie_domain) { + $message = pht( + 'You are trying to issue a write request which requires a CSRF '. + 'check, but this connection is HTTP and "security.require-https" '. + 'is enabled, so CSRF cookies can not be set and writes can not be '. + 'verfied. To continue, use HTTPS or disable the HTTPS requirement.'); + + throw new AphrontMalformedRequestException( + pht('No Cookie Support (CSRF)'), + $message); + } + } + if (!$valid) { // Add some diagnostic details so we can figure out if some CSRF issues // are JS problems or people accessing Ajax URIs directly with their // browsers.