{"record":{"id":"86b3ba2daf045fd9","repo":"dotnet/aspnetcore","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/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/eng/common/cross/install-debs.py#L117-L153","documentation":"fetch_release_file downloads Release and Release.gpg, then runs gpgv to verify the detached signature against the (optionally) specified keyring. If gpgv returns non-zero, a plain Exception is raised containing the decoded stderr. This is the GPG signature gate that anchors the whole checksum chain when --force-check-gpg is enabled.","triggerScenarios":"Invoked from fetch_and_decompress only when check_sig is True. gpgv fails because: the key for the suite is not in the keyring, the Release file was tampered, the Release.gpg is missing/corrupt, an expired signing key, or gpgv itself is not installed/misconfigured. The non-zero returncode triggers the exception.","commonSituations":"Wrong or empty --keyring file for the suite (Debian vs Ubuntu vs ports use different keyrings); keyring package not installed (debian-ports-archive-keyring, ubuntu-keyring); the signing key has been rotated/expired since the keyring was last updated; building in a minimal container without gpgv.","solutions":["Install the correct keyring package for your suite: debian-ports-archive-keyring (Debian ports), debian-archive-keyring (Debian mainstream), or ubuntu-keyring (Ubuntu).","Pass the correct --keyring path (e.g., /usr/share/keyrings/debian-archive-keyring.gpg).","Ensure gpgv is installed and on PATH (apt-get install gnupg).","If you intentionally skip trust, drop --force-check-gpg / pass --skipsigcheck to build-rootfs.sh — but understand you lose integrity verification.","Update the keyring package if the signing key has rotated since your container image was built."],"exampleFix":"# before\npython3 install-debs.py --force-check-gpg --keyring /tmp/wrong.gpg \\\n  --suite sid --mirror http://deb.debian.org/debian ...\n# Signature verification failed: Can't check signature: public key not found\n\n# after\nsudo apt-get install -y debian-archive-keyring\npython3 install-debs.py --force-check-gpg \\\n  --keyring /usr/share/keyrings/debian-archive-keyring.gpg \\\n  --suite bookworm --mirror http://deb.debian.org/debian ...","handlingStrategy":"validation","validationCode":"# Verify gpgv and the keyring are usable before the build\nimport shutil, subprocess\nif not shutil.which('gpgv'):\n    raise SystemExit('gpgv not installed: apt-get install gnupg')\nprobe = subprocess.run(['gpgv', '--keyring', keyring, '/dev/null', '/dev/null'],\n                       capture_output=True)\nif probe.returncode not in (0, 2):\n    raise SystemExit(f'Keyring {keyring} unusable: {probe.stderr.decode()}')","typeGuard":null,"tryCatchPattern":"try:\n    release_content = await fetch_release_file(session, mirror, suite, keyring)\nexcept Exception as e:\n    if 'Signature verification failed' in str(e):\n        if 'No public key' in str(e) or 'public key not found' in str(e):\n            raise SystemExit('Install the suite\\'s keyring package (e.g., debian-archive-keyring) and re-run')\n        raise","preventionTips":["Install the correct keyring package for each suite before enabling --force-check-gpg.","Verify gpgv is on PATH in minimal containers.","Rotate local keyrings periodically to pick up new signing keys.","Distinguish 'no public key' (fixable with the right keyring) from genuine tampering."],"tags":["python","debian","gpg","signature","security","install-debs","rootfs"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}