{"record":{"id":"67a08ae33d66f2f4","repo":"dotnet/yarp","slug":"signature-verification-failed-result-stderr-deco","errorCode":null,"errorMessage":"Signature verification failed: {result.stderr.decode('utf-8')}","messagePattern":"Signature verification failed: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"eng/common/cross/install-debs.py","lineNumber":135,"sourceCode":"    release_gpg_url = f\"{mirror}/dists/{suite}/Release.gpg\"\n\n    with tempfile.NamedTemporaryFile() as release_file, tempfile.NamedTemporaryFile() as release_gpg_file:\n        await download_file(session, release_url, release_file.name)\n        await download_file(session, release_gpg_url, release_gpg_file.name)\n\n        print(\"Verifying signature of Release with Release.gpg.\")\n        # Use gpgv rather than gpg for verification. gpgv verifies a detached\n        # signature against a fixed keyring without involving gpg-agent or\n        # keyboxd, which makes it robust on hosts running GnuPG 2.4+ (e.g. Azure\n        # Linux) where \"gpg --keyring\" routes through keyboxd and can fail.\n        verify_command = [\"gpgv\"]\n        if keyring:\n            verify_command += [\"--keyring\", keyring]\n        verify_command += [release_gpg_file.name, release_file.name]\n        result = subprocess.run(verify_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\n        if result.returncode != 0:\n            raise Exception(f\"Signature verification failed: {result.stderr.decode('utf-8')}\")\n\n        print(\"Signature verified successfully.\")\n\n        with open(release_file.name) as f:\n            return f.read()\n\ndef parse_release_file(content, path):\n    \"\"\"Parses the Release file and returns sha256 checksum of the specified path.\"\"\"\n\n    # data looks like this:\n    # <checksum>  <size>  <path>\n    matches = re.findall(r'^ (\\S*) +(\\S*) +(\\S*)$', content, re.MULTILINE)\n\n    for entry in matches:\n        # the file has both md5 and sha256 checksums, we want sha256 which has a length of 64\n        if entry[2] == path and len(entry[0]) == 64:\n            return entry[0]\n","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/eng/common/cross/install-debs.py#L117-L153","documentation":"This exception is raised in fetch_release_file when the gpgv subprocess returns a non-zero exit code, meaning the detached GPG signature in Release.gpg does not verify against the Release file using the provided keyring. The script uses gpgv (not gpg) for robustness on GnuPG 2.4+ hosts. The error includes stderr from gpgv, which typically explains the specific failure (expired key, missing key, bad signature). Signature verification is a security control -- it ensures the Release file (and by extension the package index checksums) were published by the repository maintainers and have not been tampered with.","triggerScenarios":"fetch_release_file (lines 113-135) downloads Release and Release.gpg, constructs a gpgv command with optional --keyring, runs it via subprocess.run, and checks result.returncode. Non-zero triggers this exception. Causes: the signing key is not present in the provided keyring; the key has expired or been revoked; the Release or Release.gpg file was corrupted in transit; gpgv is not installed or not on PATH; the keyring file path is wrong or unreadable; the mirror is serving a tampered Release file.","commonSituations":"Missing or wrong keyring package (e.g. debian-ports-archive-keyring for ports, ubuntu-archive-keyring for Ubuntu); the repository's signing key was rotated and the local keyring is outdated; using an Ubuntu keyring against a Debian mirror or vice versa; gpgv not installed in the build container; keyring file path passed via --keyring is incorrect or the file lacks read permissions; the mirror is compromised or serving a man-in-the-middle attack (rare but this is exactly what the check is designed to catch).","solutions":["Read the gpgv stderr in the exception message -- it will say 'No public key' (missing key), 'BAD signature' (tampered), or 'signature verification failed' (corrupted).","Install the correct keyring package for the distribution: debian-ports-archive-keyring (Debian ports), debian-archive-keyring (Debian mainstream), or ubuntu-archive-keyring (Ubuntu).","Update the keyring to the latest version to get current signing keys.","Verify the --keyring path is correct and the file is readable: ls -l <keyring-path>.","Ensure gpgv is installed: which gpgv (install gnupg package if missing).","If you trust the mirror and cannot resolve the key issue, disable verification by omitting --force-check-gpg -- but understand this removes the integrity guarantee.","Switch to the official mirror to rule out a compromised or misconfigured third-party mirror."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Pre-check: verify gpgv is installed and the keyring file exists and is readable.\nimport shutil, os\nif not shutil.which('gpgv'):\n    print(\"ERROR: gpgv not found. Install the gnupg package.\")\nif keyring and not os.path.isfile(keyring):\n    print(f\"ERROR: Keyring file not found: {keyring}\")\nelif keyring and not os.access(keyring, os.R_OK):\n    print(f\"ERROR: Keyring file not readable: {keyring}\")","typeGuard":null,"tryCatchPattern":"# Catch signature verification failure and provide actionable guidance\ntry:\n    release_content = await fetch_release_file(session, mirror, suite, keyring)\nexcept Exception as e:\n    stderr_msg = str(e)\n    if 'No public key' in stderr_msg:\n        print(\"Signing key not in keyring. Install/update the appropriate keyring package.\")\n    elif 'BAD signature' in stderr_msg:\n        print(\"SECURITY ALERT: Release file signature is invalid. \"\n              \"Do not proceed -- the mirror may be compromised.\")\n    raise","preventionTips":["Install the correct keyring package for your distribution before enabling --force-check-gpg.","Keep the keyring package updated to get current signing keys (keys are rotated periodically).","Verify gpgv is installed and on PATH before running the script.","If you cannot resolve the key issue, omit --force-check-gpg but understand the security trade-off.","Use official mirrors to reduce the risk of encountering a tampered Release file."],"tags":["python","debian","gpg","gpgv","signature","security","keyring","apt"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}