{"record":{"id":"1cf9725cd094d4fc","repo":"Stirling-Tools/Stirling-PDF","slug":"gitleaks-checksum-mismatch-expected-expected-g","errorCode":null,"errorMessage":"gitleaks checksum mismatch: expected {expected}, got {digest}","messagePattern":"gitleaks checksum mismatch: expected (.+?), got (.+?)","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"critical","filePath":"scripts/pre-commit/install_gitleaks.py","lineNumber":87,"sourceCode":"def main() -> int:\n    if cached_version() == VERSION:\n        return 0\n\n    key = platform_key()\n    expected = SHA256.get(key)\n    if expected is None:\n        raise SystemExit(f\"No pinned gitleaks checksum for {key}\")\n\n    suffix = \"zip\" if key.startswith(\"windows\") else \"tar.gz\"\n    asset = f\"gitleaks_{VERSION}_{key}.{suffix}\"\n    url = f\"https://github.com/gitleaks/gitleaks/releases/download/v{VERSION}/{asset}\"\n    print(f\"Downloading gitleaks {VERSION} ({asset})\", flush=True)\n\n    BIN.parent.mkdir(parents=True, exist_ok=True)\n    archive, _ = urllib.request.urlretrieve(url)\n    digest = hashlib.sha256(Path(archive).read_bytes()).hexdigest()\n    if digest != expected:\n        raise SystemExit(f\"gitleaks checksum mismatch: expected {expected}, got {digest}\")\n\n    member = \"gitleaks.exe\" if IS_WINDOWS else \"gitleaks\"\n    if suffix == \"zip\":\n        with zipfile.ZipFile(archive) as zf:\n            data = zf.read(member)\n    else:\n        with tarfile.open(archive) as tf:\n            extracted = tf.extractfile(member)\n            if extracted is None:\n                raise SystemExit(f\"{member} not found in {asset}\")\n            data = extracted.read()\n    BIN.write_bytes(data)\n    BIN.chmod(0o755)\n    return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/scripts/pre-commit/install_gitleaks.py#L69-L105","documentation":"SystemExit raised by install_gitleaks.main when the SHA256 digest of the downloaded gitleaks archive does not match the pinned expected checksum. This is a tamper/integrity check — a mismatch means the downloaded artifact differs from the vetted release (corruption, MITM, or a release that changed after pinning).","triggerScenarios":"The downloaded archive's sha256 differs from the pinned value. Caused by: gitleaks re-published the release asset (force tag), a CDN/mirror served a different artifact, network corruption, or the pinned checksum is simply wrong/stale.","commonSituations":"The VERSION pin was updated but SHA256 pins were copied from the wrong release. A transient download corruption. gitleaks re-released under the same tag.","solutions":["Recompute the correct sha256 of the official release asset and update the SHA256 pin for the key.","Re-download in case of transient corruption.","Verify the VERSION and checksums come from the same gitleaks release notes.","If intentional re-release, document it and update all affected platform pins."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Recompute and verify the checksum independently\nimport hashlib\ndigest = hashlib.sha256(Path(archive).read_bytes()).hexdigest()\nassert digest == expected, f\"checksum mismatch: expected {expected}, got {digest}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin VERSION and SHA256 checksums from the same gitleaks release.","Re-download on transient corruption before declaring a mismatch.","Treat any mismatch as a potential supply-chain issue and investigate."],"tags":["pre-commit","supply-chain","checksum","integrity","security","python"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}