{"record":{"id":"1d8a896b02f256a1","repo":"cloudflare/cloudflared","slug":"failed-to-import-private-key","errorCode":null,"errorMessage":"Failed to import private key","messagePattern":"Failed to import private key","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"release_pkgs.py","lineNumber":194,"sourceCode":"                    if file.endswith(f\"{arch}.rpm\"):\n                        new_dir = f\"./rpm/{arch}\"\n                        os.makedirs(new_dir, exist_ok=True)\n                        old_path = os.path.join(root, file)\n                        new_path = os.path.join(new_dir, file)\n                        shutil.copyfile(old_path, new_path)\n                        self._sign_rpms(new_path, gpg_key_name)\n\n    \"\"\"\n        imports gpg keys into the system so reprepro and createrepo can use it to sign packages.\n        it returns the GPG ID after a successful import\n    \"\"\"\n\n    def import_gpg_keys(self, private_key, public_key):\n        gpg = gnupg.GPG()\n        private_key = base64.b64decode(private_key)\n        import_result = gpg.import_keys(private_key)\n        if not import_result.fingerprints:\n            raise Exception(\"Failed to import private key\")\n\n        public_key = base64.b64decode(public_key)\n        gpg.import_keys(public_key)\n\n        imported_fingerprint = import_result.fingerprints[0]\n        data = gpg.list_keys(secret=True)\n\n        # Find the specific key we just imported by comparing fingerprints\n        for key in data:\n            if key[\"fingerprint\"] == imported_fingerprint:\n                return (key[\"fingerprint\"], key[\"uids\"][0])\n\n        raise Exception(f\"Could not find imported key with fingerprint {imported_fingerprint}\")\n\n    def import_multiple_gpg_keys(self, primary_private_key, primary_public_key, secondary_private_key=None, secondary_public_key=None):\n        \"\"\"\n        Import one or two GPG keypairs. Returns a list of (fingerprint, uid) with the primary first.\n        \"\"\"","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/release_pkgs.py#L176-L212","documentation":"import_gpg_keys base64-decodes the provided private key material and imports it via python-gnupg; if the import result contains no fingerprints, the key was not accepted by gpg and this exception is raised. This almost always means the key data was invalid, corrupted, or not actually a private key.","triggerScenarios":"Importing a private key whose base64 payload does not decode to valid PGP key material, a public key passed where a private key is expected, an empty string, whitespace/newline corruption from a CI secret, or a GPG keychain/agent failure.","commonSituations":"CI secrets where the base64 blob was truncated or re-wrapped; storing the key double-encoded; passing the public key file into gpg_private_key; GPG_HOME issues causing silent import failures.","solutions":["Inspect gpg's import_result output/status to see why the import failed (gpg.import_keys returns detailed results).","Verify the base64 string decodes to a valid key: base64 -d key.b64 | gpg --list-packets.","Regenerate the base64 encoding from the original key file (base64 -w0 private.key) and re-set the CI secret.","Confirm you are passing the private key (not the public key) to the private_key argument."],"exampleFix":"// before\nimport_result = gpg.import_keys(private_key)\nif not import_result.fingerprints:\n    raise Exception(\"Failed to import private key\")\n// after\nimport_result = gpg.import_keys(private_key)\nif not import_result.fingerprints:\n    raise Exception(\"Failed to import private key: {}\".format(import_result.results))","handlingStrategy":"validation","validationCode":"import base64\ndata = base64.b64decode(private_key, validate=True)\nif b\"PRIVATE KEY\" not in data and not data.startswith(b\"-----BEGIN PGP\"):\n    raise ValueError(\"private_key does not look like valid PGP key material\")","typeGuard":null,"tryCatchPattern":"try:\n    keys = importer.import_gpg_keys(priv, pub)\nexcept Exception as e:\n    logging.error(\"GPG import failed: %s\", e)\n    raise SystemExit(1)","preventionTips":["Regenerate CI secrets with base64 -w0 to avoid wrapped/truncated blobs","Confirm the private key (not the public key) is supplied as private_key","Test the import locally with gpg --import before wiring into CI"],"tags":["gpg","signing","python","ci"],"backgroundTag":"missing-credentials","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}