passbolt/passbolt_api · error · CustomValidationException

Could not validate key revocation.

Error message

Could not validate key revocation.

What it means

Wrapper error thrown by buildRevokedKeyEntityFromDataOrFail when a ValidationException/CustomValidationException occurs while validating the revoked organization key — either the original active key lookup (findActiveKeyByFingerprintOrFail) or PublicKeyValidationService::parseAndValidatePublicKey with the revoked-key rules fails. Errors are nested under 'account_recovery_organization_revoked_key'.

Solutions

  1. Inspect errors.account_recovery_organization_revoked_key for the nested rule failure
  2. Ensure the armored_key is a proper revocation certificate generated with `gpg --gen-revoke <fingerprint>` (armored)
  3. Ensure the fingerprint matches the currently active organization recovery key
  4. Validate locally that the certificate parses: `gpg --import --import-options show-only <revoke.asc>`

Example fix

// before
{"armored_key": "<normal public key>", "fingerprint": "<fp>"}
// after
gpg --armor --gen-revoke <fp> > revoke.asc
{"armored_key": "<contents of revoke.asc>", "fingerprint": "<fp>"}
Defensive patterns

Strategy: validation

Validate before calling

// A revocation cert looks like a public key block; ensure it parses and matches the active fp
if (!armored_key.includes('-----BEGIN PGP PUBLIC KEY BLOCK-----')) {
  throw new Error('Provide an armored revocation certificate');
}
if (fingerprint !== activeOrgKeyFingerprint) {
  throw new Error('Fingerprint must match the active organization key');
}

Type guard

function isRevocationPayloadForActiveKey(p, activeFp) {
  return typeof p.armored_key === 'string'
    && p.armored_key.includes('BEGIN PGP PUBLIC KEY BLOCK')
    && p.fingerprint === activeFp;
}

Try / catch

try {
  await api.disableOrganizationPolicy(revocationPayload);
} catch (e) {
  const nested = e.body?.errors?.account_recovery_organization_revoked_key;
  console.error(nested); // shows which rule (or key lookup) failed
}

Prevention

When it happens

Trigger: Calling set() or disablePolicy() (policy disable flow) where the submitted revocation certificate's armored_key fails revoked-key validation rules, or the fingerprint doesn't correspond to an active organization key.

Common situations: Admin submits the current public key instead of a revocation certificate; revocation key has a fingerprint matching no active key; malformed or truncated revocation armor during policy disable.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/8109688de2082bf4. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryOrganizationPolicies/AbstractAccountRecoveryOrganizationPolicySetService.php:310

     * Check user provided valid valid account_recovery_organization_revoked_key
     * Return patched entity corresponding to the key to revoke (e.g. to update in DB)
     *
     * @param \App\Utility\UserAccessControl $uac user access control
     * @throws \App\Error\Exception\CustomValidationException if any of the check on fingerprint or armored key data fails
     * @return \Passbolt\AccountRecovery\Model\Entity\AccountRecoveryOrganizationPublicKey currently in use key patched with new revoked armored_key
     */
    public function buildRevokedKeyEntityFromDataOrFail(UserAccessControl $uac): AccountRecoveryOrganizationPublicKey
    {
        try {
            $data = $this->getData('account_recovery_organization_revoked_key');
            $entity = $this->AccountRecoveryOrganizationPublicKeys->buildAndValidateEntity($uac, $data);
            $oldEntity = $this->findActiveKeyByFingerprintOrFail($entity->fingerprint);
            PublicKeyValidationService::parseAndValidatePublicKey(
                $entity->armored_key,
                PublicKeyValidationService::getRevokedKeyRules()
            );
        } catch (ValidationException | CustomValidationException $exception) {
            throw new CustomValidationException(__('Could not validate key revocation.'), [
                'account_recovery_organization_revoked_key' => $exception->getErrors(),
            ]);
        } catch (Exception $exception) {
            throw new CustomValidationException(__('Could not validate key revocation.'), [
                'account_recovery_organization_revoked_key' => [
                    'armored_key' => [
                        'invalidArmoredKey' => $exception->getMessage(),
                    ],
                ],
            ]);
        }

        // Check revocation cryptographically
        // parseAndValidatePublicKey only do superficial signature check
        if (!(new PublicKeyRevocationCheckService())->check($entity->armored_key)) {
            throw new CustomValidationException(__('Could not validate key revocation.'), [
                'account_recovery_organization_revoked_key' => __('Could not validate key revocation.'),
            ]);

View on GitHub (pinned to 31c1bbc10f)