phacility/phabricator · error · Exception

You have an old version of Mercurial (%s) which has a severe

Error message

You have an old version of Mercurial (%s) which has a severe command injection security vulnerability. The remote URI for this repository (%s) is potentially unsafe. Upgrade Mercurial to at least 3.2.4 to clone it.

What it means

Thrown before cloning a Mercurial repository when PhutilBinaryAnalyzer reports the installed hg is a version with a known command-injection vulnerability (below 3.2.4) and the remote URI contains characters that csprintf with '%R' would escape, meaning a vulnerable shell invocation could interpret them. Phabricator refuses the clone rather than risk injection; the repository monogram (e.g. R123) is included so the admin can find it.

Source

Thrown at src/applications/repository/engine/PhabricatorRepositoryPullEngine.php:678

    } else {
      $remote = $repository->getRemoteURIEnvelope();

      // NOTE: Mercurial prior to 3.2.4 has an severe command injection
      // vulnerability. See: <http://bit.ly/19B58E9>

      // On vulnerable versions of Mercurial, we refuse to clone remotes which
      // contain characters which may be interpreted by the shell.
      $hg_binary = PhutilBinaryAnalyzer::getForBinary('hg');
      $is_vulnerable = $hg_binary->isMercurialVulnerableToInjection();
      if ($is_vulnerable) {
        $cleartext = $remote->openEnvelope();
        // The use of "%R" here is an attempt to limit collateral damage
        // for normal URIs because it isn't clear how long this vulnerability
        // has been around for.

        $escaped = csprintf('%R', $cleartext);
        if ((string)$escaped !== (string)$cleartext) {
          throw new Exception(
            pht(
              'You have an old version of Mercurial (%s) which has a severe '.
              'command injection security vulnerability. The remote URI for '.
              'this repository (%s) is potentially unsafe. Upgrade Mercurial '.
              'to at least 3.2.4 to clone it.',
              $hg_binary->getBinaryVersion(),
              $repository->getMonogram()));
        }
      }

      try {
        $repository->execxRemoteCommand(
          'clone --noupdate -- %P %s',
          $remote,
          $path);
      } catch (Exception $ex) {
        $message = $ex->getMessage();
        $message = $this->censorMercurialErrorMessage($message);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Upgrade Mercurial to 3.2.4 or newer on the Phabricator host; confirm with 'hg version', which removes the check entirely
  2. If upgrading is impossible, change the repository remote URI to contain only characters that need no shell escaping
  3. Re-run the clone or pull task after the upgrade

Example fix

# before
hg version   # 2.6.2 (vulnerable) -> clone refused

# after
sudo apt-get install mercurial   # or build from source
hg version   # 4.x -> clone proceeds
Defensive patterns

Strategy: validation

Validate before calling

// Before adding a Mercurial repository, verify the binary is patched:
$hg = PhutilBinaryAnalyzer::getForBinary('hg');
if ($hg->isMercurialVulnerableToInjection()) {
  // refuse to configure the repository until hg >= 3.2.4
}

Prevention

When it happens

Trigger: The hg binary on the Phabricator host is older than 3.2.4 AND the repository remote URI contains shell metacharacters such as spaces, quotes, ampersands, or semicolons; first clone or pull of such a Mercurial repository triggers the guard before execxRemoteCommand runs.

Common situations: Long-lived servers running stock distro Mercurial (e.g. CentOS 7 ships hg 2.x); Mercurial remotes with passwords or unusual characters embedded in the URI; minimal installs where the vendor hg package was never upgraded.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/0d06aafcd1328fc9. Report an issue: GitHub.