{"record":{"id":"9752cfab06111346","repo":"passbolt/passbolt_api","slug":"could-not-validate-message-data","errorCode":null,"errorMessage":"Could not validate message data.","messagePattern":"Could not validate message data\\.","errorType":"validation","errorClass":"CustomValidationException","httpStatus":422,"severity":"error","filePath":"src/Service/OpenPGP/MessageRecipientValidationService.php","lineNumber":35,"sourceCode":"namespace App\\Service\\OpenPGP;\n\nuse App\\Error\\Exception\\CustomValidationException;\n\n/**\n * Service to check if an OpenPGP message is intended for a recipient\n */\nclass MessageRecipientValidationService\n{\n    /**\n     * @param array $messageInfo see MessageValidationService::getMessageInfo\n     * @param array $keyInfo see PublicKeyValidationService::getPublicKeyInfo\n     * @throws \\App\\Error\\Exception\\CustomValidationException if the message info or key info are not workable\n     * @return bool\n     */\n    public static function isMessageForRecipient(array $messageInfo, array $keyInfo): bool\n    {\n        if (!isset($messageInfo['recipients'][0])) {\n            throw new CustomValidationException(__('Could not validate message data.'), [\n                'recipientRequired' => __('Recipient information could not be found.'),\n            ]);\n        }\n\n        // PB-43936 OpenPGP key without subkey, then the message must for main key id.\n        if (empty($keyInfo['sub_keys'])) {\n            return isset($keyInfo['key_id']) && in_array($keyInfo['key_id'], $messageInfo['recipients']);\n        }\n\n        foreach ($keyInfo['sub_keys'] as $subKey) {\n            if (isset($subKey['key_id']) && in_array($subKey['key_id'], $messageInfo['recipients'])) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/OpenPGP/MessageRecipientValidationService.php#L17-L53","documentation":"MessageRecipientValidationService::isMessageForRecipient validates that an OpenPGP armored message is encrypted for the expected recipient key. If $messageInfo has no recipients (recipients[0] missing), the message cannot be attributed to any key, so it throws CustomValidationException with 'Could not validate message data.' and a recipientRequired error.","triggerScenarios":"Decrypting/sharing operations (buildPasswordEntitiesFromDataOrFail, folder/resource assertions) receiving an armored message whose parsed metadata contains an empty recipients array — e.g. message encrypted with unsupported/legacy ciphers or corrupted packet headers.","commonSituations":"Messages produced by non-passbolt GPG tools, corrupted or truncated armored payloads, key info mismatch (PB-43936: keys without subkeys), sharing endpoints receiving malformed secrets.","solutions":["Re-generate the armored message so GnuPG/OpenPGP-PHP can parse recipient key IDs (use modern subkeys/ciphers).","Verify the message parses: gpg --list-packets on the armored block to confirm recipient packets exist.","Ensure the shared secret payload is the complete encrypted message, not a fragment.","Check the OpenPGP backend version supports the cipher/key format used."],"exampleFix":"// before\n$service->isMessageForRecipient($messageInfo, $keyInfo); // throws: no recipients\n// after\nif (!empty($messageInfo['recipients'])) {\n    $service->isMessageForRecipient($messageInfo, $keyInfo);\n}","handlingStrategy":"type-guard","validationCode":"if (!Array.isArray(messageInfo.recipients) || messageInfo.recipients.length === 0) { /* reject before call */ }","typeGuard":"function hasRecipients(m) { return Array.isArray(m?.recipients) && m.recipients.length > 0; }","tryCatchPattern":"try { isMessageForRecipient($mi, $ki); } catch (CustomValidationException $e) { /* recipientRequired error */ }","preventionTips":["Verify messages with gpg --list-packets before sharing","Re-encrypt with supported GPG versions","Never transmit truncated armored payloads"],"tags":["openpgp","gpg","validation"],"backgroundTag":"empty-required-field","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}