diff --git a/src/applications/passphrase/controller/PassphraseCredentialEditController.php b/src/applications/passphrase/controller/PassphraseCredentialEditController.php --- a/src/applications/passphrase/controller/PassphraseCredentialEditController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialEditController.php @@ -155,8 +155,13 @@ ->setTransactionType($type_username) ->setNewValue($v_username); - $min_secret = str_replace($bullet, '', trim($v_decrypt)); - if (strlen($min_secret)) { + // If some value other than a sequence of bullets was provided for + // the credential, update it. In particular, note that we are + // explicitly allowing empty secrets: one use case is HTTP auth where + // the username is a secret token which covers both identity and + // authentication. + + if (!preg_match('/^('.$bullet.')+$/', trim($v_decrypt))) { // If the credential was previously destroyed, restore it when it is // edited if a secret is provided. $xactions[] = id(new PassphraseCredentialTransaction()) diff --git a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php --- a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php @@ -46,16 +46,19 @@ } if ($request->isFormPost()) { - if ($credential->getSecret()) { + $secret = $credential->getSecret(); + if (!$secret) { + $body = pht('This credential has no associated secret.'); + } else if (!strlen($secret->openEnvelope())) { + $body = pht('This credential has an empty secret.'); + } else { $body = id(new PHUIFormLayoutView()) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Plaintext')) ->setReadOnly(true) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) - ->setValue($credential->getSecret()->openEnvelope())); - } else { - $body = pht('This credential has no associated secret.'); + ->setValue($secret->openEnvelope())); } // NOTE: Disable workflow on the cancel button to reload the page so