{"record":{"id":"501331edfa7b78e7","repo":"passbolt/passbolt_api","slug":"the-openpgp-server-key-defined-in-the-config-cannot-be","errorCode":null,"errorMessage":"The OpenPGP server key defined in the config cannot be opened.","messagePattern":"The OpenPGP server key defined in the config cannot be opened\\.","errorType":"exception","errorClass":"Cake\\Http\\Exception\\InternalErrorException","httpStatus":500,"severity":"critical","filePath":"src/Utility/OpenPGP/OpenPGPBackend.php","lineNumber":101,"sourceCode":"     */\n    public function importServerKeyInKeyring(): void\n    {\n        $fingerprint = Configure::read('passbolt.gpg.serverKey.fingerprint');\n        $keyFilePath = Configure::read('passbolt.gpg.serverKey.private');\n\n        // If it's not in keyring try to import it\n        // Check if file containing the private key exist\n        if ($keyFilePath === null) {\n            throw new InternalErrorException('The secret key file is not defined.');\n        }\n        if (!file_exists($keyFilePath)) {\n            $msg = __('The OpenPGP server key defined in the config is not found in the file system.');\n            throw new InternalErrorException($msg);\n        }\n        $privateKey = file_get_contents($keyFilePath);\n        if ($privateKey === false) {\n            $msg = __('The OpenPGP server key defined in the config cannot be opened.');\n            throw new InternalErrorException($msg);\n        }\n        if (!$this->isParsableArmoredPrivateKey($privateKey)) {\n            $msg = __('The OpenPGP server key defined on file is not a valid private key.');\n            throw new InternalErrorException($msg);\n        }\n\n        // try to import it\n        $this->importKeyIntoKeyring($privateKey);\n        if (!$this->isKeyInKeyring($fingerprint)) {\n            $msg = __('There is an issue with the OpenPGP server key.') . ' ';\n            $msg .= __('The fingerprint does not match the one associated with the key on file.');\n            throw new InternalErrorException($msg);\n        }\n    }\n\n    /**\n     * Check if a message is valid.\n     *","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Utility/OpenPGP/OpenPGPBackend.php#L83-L119","documentation":"After confirming the configured private key file exists, importServerKeyInKeyring reads it with file_get_contents(). If that returns false (the file exists but cannot be read/opened by the process), this InternalErrorException is thrown. It signals a filesystem-level read failure rather than a missing or malformed key.","triggerScenarios":"file_get_contents($keyFilePath) === false during importServerKeyInKeyring: permission denied on the file, unreadable directory, open_basedir restriction, or the path is a directory/unreadable special file.","commonSituations":"Key file owned by root with 0600 while PHP runs as www-data; restrictive SELinux/AppArmor policy; open_basedir in php.ini excluding the key path; Docker volume mounted with wrong ownership.","solutions":["Chown/chmod the key file so the web server user can read it: `chown www-data:www-data <keyfile> && chmod 0400 <keyfile>`.","Check `ls -l` on the file and each parent directory for execute/read permission for the PHP user.","If open_basedir is set, add the key's directory to it in php.ini and restart PHP-FPM/Apache.","Verify the path is a regular file (`file <keyfile>`), not a directory or broken symlink target."],"exampleFix":"// before\n-rw------- root root /etc/passbolt/serverkey_private.asc\n// after\nchown www-data:www-data /etc/passbolt/serverkey_private.asc && chmod 0400 /etc/passbolt/serverkey_private.asc","handlingStrategy":"validation","validationCode":"$keyPath = Configure::read('passbolt.gpg.serverKey.private');\nif (!is_readable($keyPath)) {\n    throw new \\RuntimeException(\"Server key exists but is not readable by user \" . get_current_user());\n}","typeGuard":null,"tryCatchPattern":"try {\n    $backend->importServerKeyInKeyring($fingerprint, $keyPath);\n} catch (\\Cake\\Http\\Exception\\InternalErrorException $e) {\n    if (str_contains($e->getMessage(), 'cannot be opened')) {\n        clearstatcache(true, $keyPath); // diagnose permissions before retry\n    }\n    throw $e;\n}","preventionTips":["Standardize key file ownership (www-data) and mode 0400 in provisioning scripts.","Test readability as the PHP user during deploy: `sudo -u www-data test -r <keyfile>`.","Keep key directory out of open_basedir restrictions or explicitly whitelist it."],"tags":["openpgp","server-key","file-read","permissions","gnupg"],"backgroundTag":"file-read-failed","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"}