Differential D12170 Diff 29253 src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
| Show First 20 Lines • Show All 389 Lines • ▼ Show 20 Lines | if ($repository->isHosted()) { | ||||
| 'command injection security vulnerability. The remote URI for '. | 'command injection security vulnerability. The remote URI for '. | ||||
| 'this repository (%s) is potentially unsafe. Upgrade Mercurial '. | 'this repository (%s) is potentially unsafe. Upgrade Mercurial '. | ||||
| 'to at least 3.2.4 to clone it.', | 'to at least 3.2.4 to clone it.', | ||||
| $hg_version, | $hg_version, | ||||
| $repository->getMonogram())); | $repository->getMonogram())); | ||||
| } | } | ||||
| } | } | ||||
| try { | |||||
| $repository->execxRemoteCommand( | $repository->execxRemoteCommand( | ||||
| 'clone --noupdate -- %P %s', | 'clone --noupdate -- %P %s', | ||||
| $remote, | $remote, | ||||
| $path); | $path); | ||||
| } catch (Exception $ex) { | |||||
| $message = $ex->getMessage(); | |||||
| $message = $this->censorMercurialErrorMessage($message); | |||||
| throw new Exception($message); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * @task hg | * @task hg | ||||
| */ | */ | ||||
| private function executeMercurialUpdate() { | private function executeMercurialUpdate() { | ||||
| Show All 23 Lines | try { | ||||
| // to handle this (there are hard ways but this is not a common problem | // to handle this (there are hard ways but this is not a common problem | ||||
| // and only creates log spam, not application failures). Assume English. | // and only creates log spam, not application failures). Assume English. | ||||
| // TODO: Remove this once we're far enough in the future that deployment | // TODO: Remove this once we're far enough in the future that deployment | ||||
| // of 2.1 is exceedingly rare? | // of 2.1 is exceedingly rare? | ||||
| if ($err == 1 && preg_match('/no changes found/', $stdout)) { | if ($err == 1 && preg_match('/no changes found/', $stdout)) { | ||||
| return; | return; | ||||
| } else { | } else { | ||||
| throw $ex; | $message = $ex->getMessage(); | ||||
| $message = $this->censorMercurialErrorMessage($message); | |||||
| throw new Exception($message); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Censor response bodies from Mercurial error messages. | |||||
| * | |||||
| * When Mercurial attempts to clone an HTTP repository but does not | |||||
| * receive a response it expects, it emits the response body in the | |||||
| * command output. | |||||
| * | |||||
| * This represents a potential SSRF issue, because an attacker with | |||||
| * permission to create repositories can create one which points at the | |||||
| * remote URI for some local service, then read the response from the | |||||
| * error message. To prevent this, censor response bodies out of error | |||||
| * messages. | |||||
| * | |||||
| * @param string Uncensored Mercurial command output. | |||||
| * @return string Censored Mercurial command output. | |||||
| */ | |||||
| private function censorMercurialErrorMessage($message) { | |||||
| return preg_replace( | |||||
| '/^---%<---.*/sm', | |||||
| pht('<Response body omitted from Mercurial error message.>')."\n", | |||||
| $message); | |||||
| } | } | ||||
| /** | /** | ||||
| * @task hg | * @task hg | ||||
| */ | */ | ||||
| private function installMercurialHook() { | private function installMercurialHook() { | ||||
| $repository = $this->getRepository(); | $repository = $this->getRepository(); | ||||
| ▲ Show 20 Lines • Show All 62 Lines • Show Last 20 Lines | |||||