phacility/phabricator · error · Exception

Provide a public key, not a private key!

Error message

Provide a public key, not a private key!

What it means

In newFromRawKey(), after splitting on whitespace, Phabricator checks preg_match('/private\s*key/i', $entire_key) to detect private key material (lines like '-----BEGIN OPENSSH PRIVATE KEY-----') and throws with a targeted message before generic parsing fails. It exists so users get told they pasted the wrong half of the key pair.

Source

Thrown at src/applications/auth/sshkey/PhabricatorAuthSSHPublicKey.php:40

    return $public_key;
  }

  public static function newFromRawKey($entire_key) {
    $entire_key = trim($entire_key);
    if (!strlen($entire_key)) {
      throw new Exception(pht('No public key was provided.'));
    }

    $parts = str_replace("\n", '', $entire_key);

    // The third field (the comment) can have spaces in it, so split this
    // into a maximum of three parts.
    $parts = preg_split('/\s+/', $parts, 3);

    if (preg_match('/private\s*key/i', $entire_key)) {
      // Try to give the user a better error message if it looks like
      // they uploaded a private key.
      throw new Exception(pht('Provide a public key, not a private key!'));
    }

    switch (count($parts)) {
      case 1:
        throw new Exception(
          pht('Provided public key is not properly formatted.'));
      case 2:
        // Add an empty comment part.
        $parts[] = '';
        break;
      case 3:
        // This is the expected case.
        break;
    }

    list($type, $body, $comment) = $parts;

    $recognized_keys = array(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Paste the public key file instead: ~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub (generate with ssh-keygen if none exists)
  2. If a private key was submitted to any form or stored anywhere shared, treat it as compromised: remove it and rotate the key pair
Defensive patterns

Strategy: validation

Validate before calling

// Before parsing a raw public key, mirror the library's own check:
if (preg_match('/private\s*key/i', $submitted_key_text)) {
  return pht('You pasted a private key. Upload the .pub file instead.');
}
$public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($submitted_key_text);

Type guard

function isPublicSshKeyMaterial($raw_key) {
  return !preg_match('/private\s*key/i', $raw_key);
}

Try / catch

try {
  $public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($raw);
} catch (Exception $ex) {
  // Both private-key-pasted and format errors land here:
  // surface the message next to the key input field.
  $e_key = $ex->getMessage();
}

Prevention

When it happens

Trigger: Uploading an SSH key whose text contains 'private key' - i.e. pasting the contents of the private key file (id_ed25519, id_rsa) into a public key (authorized key) field.

Common situations: Users pasting ~/.ssh/id_rsa instead of ~/.ssh/id_rsa.pub; confusion about which file to upload in SSH key settings pages.

Related errors


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