How to fingerprint build artifacts & package tarballs for supply-chain checks
- Step 1Get the artifact you want to pin — Download the dependency tarball (
npm packoutput, a vendored.tgz), the release binary, or the build output you intend to trust. Any file works — the tool hashes raw bytes, not parsed package metadata. - Step 2Fingerprint it to capture the expected hash — Drop the artifact and run. Read the
sha256field — that's your pin. Record it (and thesizeBytesfrom the server-safe path) in your lockfile note, aCHECKSUMSfile, or a CI secret. SHA-1/256/512 come from Web Crypto; MD5 from an embedded routine. - Step 3Store the pin somewhere your pipeline reads — Commit the expected SHA-256 to a
SHA256SUMS/CHECKSUMSfile or a config that your CI step can read. Pin the byte count too if you capturedsizeBytes— a wrong size is an even faster fail than a wrong hash. - Step 4Re-fingerprint the artifact on every pipeline run — In CI, recompute the artifact's SHA-256 — either with
sha256sum/shasumin the runner, or via the server-safe runner endpoint — and capture the digest the same way you captured the pin. - Step 5Compare and fail on mismatch — String-compare the recomputed SHA-256 against the pin (case-insensitively — hex is case-insensitive). Equal: proceed. Different: stop the pipeline — the artifact was swapped, rebuilt non-deterministically, or corrupted in transit.
- Step 6Re-pin deliberately when you upgrade — When you intentionally bump a dependency or change a build, fingerprint the new artifact and update the stored SHA-256 in the same commit as the version bump. A pin change in a diff is auditable; an unexplained mismatch in CI is an alert.
What this hash pins — and what it doesn't
A raw-byte SHA-256 of an artifact vs. ecosystem-specific integrity fields. They're related but not interchangeable — match like-for-like.
| Artifact / record | Pin with the report's… | Notes |
|---|---|---|
A .tgz from npm pack or a vendored tarball | sha256 (raw bytes of the file) | Cross-check with sha256sum package.tgz in CI |
| A release binary / installer | sha256 (and sizeBytes for a size pin) | Match against the vendor's published SHA256SUMS line |
A package-lock.json integrity field | Not this tool's output | That field is sha512- base64 (an SRI string), not lowercase hex — see edge cases |
| An OCI/Docker image config digest | Not directly comparable | Image digests hash a manifest, not a single file you'd drop here |
A .asc / .sig next to a release | Not a hash — a PGP signature | Verify with pgp-message-signer, then pin the file's SHA-256 |
Browser vs. server-safe output (which to wire into CI)
Both paths compute the same four digests; the server-safe path adds the byte count and is what you script in a pipeline.
| Path | Output | Use it for |
|---|---|---|
| Browser (drag-drop) | JSON { sha1, sha256, sha512, md5 }, lowercase hex | Manually capturing a pin once; downloads as <filename>.hashes.json |
| Server-safe (paired runner) | JSON { md5, sha1, sha256, sha512, sizeBytes } | Scripting CI verification without uploading the artifact |
| Equivalent CLI | sha256sum, shasum -a 256/512, md5sum | Cross-checking either path from a terminal — identical values |
Limits and scope
Per-file, in-memory hashing. Size caps apply to the file you drop; text/SRI strings aren't accepted — this hashes a file.
| Property | Value | Notes |
|---|---|---|
| File-size limit (Free / Pro / Pro-media / Developer) | 10 MB / 100 MB / 500 MB / 2 GB | Whole artifact read into memory; oversize files rejected before hashing |
| Files per run | 1 (the first dropped file) | Pin artifacts one at a time, or script the runner for batches |
| Minimum plan | Free | Available on every tier |
| Options | None | No algorithm picker — all four computed every run |
Cookbook
Pipeline-oriented recipes. The tool produces the digests; the verification is comparing a recomputed hash against a stored pin. CLI equivalents are shown so you can replicate the check in any runner.
Pin a vendored dependency tarball, then enforce it in CI
Vet a dependency once, capture its SHA-256, commit it, and have CI recompute-and-compare on every run. A swapped tarball fails the build instead of shipping.
Capture (once, after vetting): vendor/leftpad-1.3.0.tgz -> sha256: 3f79bb7b435b05321651daefd374cd... echo "3f79bb7b435b05321651daefd374cd... vendor/leftpad-1.3.0.tgz" > CHECKSUMS Enforce (every CI run): sha256sum -c CHECKSUMS # OK -> proceed ; FAILED -> stop the build
Verify a downloaded release binary against the vendor's SHA256SUMS
Before bundling a third-party CLI into your image, confirm the binary matches the project's published SHA-256. Fingerprint it and match the sha256 line against the vendor's signed checksum file.
Report (sha256): b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c Vendor SHA256SUMS: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c tool-linux-amd64 Match -> safe to bundle. Terminal: sha256sum tool-linux-amd64
Hash a private internal package without uploading it
An internal, unpublished package can't be sent to a third party. Use the server-safe runner so the file is hashed locally and only the digest comes back. Pin the SHA-256 and the sizeBytes together.
POST artifact -> local runner
http://127.0.0.1:9789/v1/tools/multi-hash-fingerprinter/run
Response:
{
"md5": "...", "sha1": "...",
"sha256": "fcde2b2edba56bf408601fb721fe9b5c338d10ee...",
"sha512": "...",
"sizeBytes": 184320
}
Pin sha256 + sizeBytes; the file never left the machine.Detect a non-deterministic build
If a 'reproducible' build produces a different artifact on a clean rebuild, the SHA-256 changes. Fingerprint two builds of the same commit: a mismatch means the build is non-deterministic (embedded timestamps, paths, or ordering) and needs to be fixed before you can pin it.
Build A (commit abc123) -> sha256: 2c26b46b68ffc68ff99b453c1d304134... Build B (commit abc123) -> sha256: 7d865e959b2466918c9863afca942d0f... Differ on the SAME commit -> build is non-deterministic. Fix the source of nondeterminism before pinning a hash.
Honor an upstream that still publishes MD5 or SHA-1
Some long-lived projects only publish an MD5 or SHA-1 for legacy reasons. For corruption-detection on a download from a trusted source, match that digest — it's already in the report — while still pinning SHA-256 internally for real security.
Upstream page: MD5 9e107d9d372bb6826bd81d3542a419d6 Report md5: 9e107d9d372bb6826bd81d3542a419d6 -> match (corruption check) Internally, pin the report's sha256, not the md5: sha256: 9b74c9897bac770ffc029102a200c5de... (MD5/SHA-1 are collision-broken; don't make a trust decision on them.)
Edge cases and what actually happens
Comparing against a `package-lock.json` integrity field
Different formatAn npm integrity value looks like sha512-Abc123…== — that's an SRI string: the algorithm name, then the digest in base64, not lowercase hex. The report's sha512 is the same algorithm but hex-encoded, so the strings won't match by eye. They encode the same hash in different alphabets; to compare you'd convert base64 to hex (or vice-versa). Don't treat the literal mismatch as a tampered file.
Trying to hash an SRI string or a URL
Wrong inputThis tool hashes a file, not a text string or a URL. There's no paste box. To pin an artifact, download the actual file and drop it. (To score a typed secret/password string instead, that's a different tool: password-entropy-auditor.)
An OCI/Docker image digest won't match
Not comparableAn image's sha256: digest hashes a manifest/config blob, not a single file you'd drop here. Fingerprinting an exported .tar of an image gives you a hash of that tar, which is not the registry digest. For pinning images, use the registry digest directly; use this tool for individual file artifacts.
Same commit, different artifact hash
Non-deterministic buildIf two clean builds of the identical source produce different SHA-256s, the build embeds nondeterministic data — timestamps, absolute paths, file ordering, or locale. That's a real signal worth fixing, not a tool error. To pinpoint where two artifacts diverge, drop both into file-integrity-monitor, which reports the first differing byte offset. Make the build reproducible first, then the hash becomes a stable pin.
Artifact exceeds your tier's size limit
Rejected: too largeThe whole file is read into memory before hashing: Free 10 MB, Pro 100 MB, Pro-media 500 MB, Developer 2 GB. A large image tarball or installer over your cap is rejected with an "exceeds the … limit for your plan" error. There's no streaming path; for very large artifacts, hash in CI with sha256sum or via the runner on a higher tier.
Published checksum is uppercase, report is lowercase
ExpectedThe report emits lowercase hex (the shasum/sha256sum convention); some vendors and Windows certutil print uppercase. Hex is case-insensitive as a value — lowercase ab12… equals uppercase AB12…. Compare case-insensitively or lowercase the published value; it's not a mismatch.
You have a `.asc`/`.sig`, not a checksum
Wrong toolA signature proves *who* released an artifact via a public key; a hash only proves the bytes match a published value. They're complementary. Verify the signature with pgp-message-signer, then pin the artifact's SHA-256 for your pipeline's byte-level check.
MD5/SHA-1 match but you needed real assurance
Insecure algorithmMD5 and SHA-1 are collision-broken — an attacker can craft two different files with the same MD5/SHA-1. A match against a trusted reference detects accidental corruption, but it is not adversary-proof. For supply-chain trust decisions, pin and compare the SHA-256 or SHA-512 line, never MD5/SHA-1.
Hosted API endpoint won't accept an upload
By designThe hosted /api/v1/tools/multi-hash-fingerprinter/run endpoint is intentionally upload-free — it returns pairing instructions, not a hash of an uploaded file. That's the privacy guarantee. To script verification, install the runner (/docs/runner) and POST to the local endpoint so the artifact stays on your machine.
Frequently asked questions
How do I use this to catch a tampered dependency?
Vet a dependency artifact once, fingerprint it, and store the resulting SHA-256 as a pin (in a CHECKSUMS file, a lockfile note, or a CI config). On every pipeline run, recompute the artifact's SHA-256 and compare it to the pin. If they differ, the artifact was swapped, corrupted, or rebuilt — fail the build. The hash is byte-derived, so any tampering, however small, flips it completely.
Does this match `sha256sum` so my CI step agrees with it?
Yes, byte-for-byte. The browser path uses the Web Crypto API and the server-safe path uses Node's crypto, both standard SHA-256 implementations, and the output is lowercase hex exactly like sha256sum and shasum -a 256. A hash you capture here will equal what sha256sum prints in your runner, so there's no tool drift to debug.
Can I fingerprint a private package without uploading it?
Yes — that's the point of the server-safe path. Install the @jadapps/runner and POST the file to the local endpoint at http://127.0.0.1:9789/v1/tools/multi-hash-fingerprinter/run. The file is hashed on your machine and only the digests come back. The hosted endpoint is deliberately upload-free, so an internal or proprietary artifact never leaves your environment.
Why doesn't my hash match the `integrity` field in package-lock.json?
Because that field isn't lowercase hex. An npm integrity value is a Subresource Integrity string like sha512-…==: the algorithm name followed by the digest encoded in base64. The report's sha512 is the same hash function but hex-encoded. They represent the same digest in different encodings, so they won't string-match directly — convert one encoding to the other to compare. It's not evidence of tampering.
What does the sizeBytes field give me?
The server-safe response includes sizeBytes, the exact byte length of the artifact, alongside the four digests. Pinning size as well as hash gives you a faster, cheaper first-line check: a wrong size is an instant fail before you even compare a 64-char digest, and it makes accidental truncation obvious. The browser path returns the four digests without sizeBytes.
Can I verify a Docker image digest with this?
Not directly. An OCI/Docker sha256: digest is the hash of an image manifest/config blob, not of a single file you'd drop here. Hashing an exported image tar gives you a hash of that tar, which is a different value from the registry digest. Use the registry's own digest to pin images, and use this tool for individual file artifacts like tarballs, binaries, and build outputs.
Which algorithm should I pin on?
SHA-256 for almost everything — it's the supply-chain default and matches what registries, mirrors, and SHA256SUMS files use. Pin SHA-512 if you want extra margin on critical releases. Don't pin trust on MD5 or SHA-1: they're collision-broken, so a match can't be trusted against a deliberate attacker. All four are in the report, so you can also match an upstream that only publishes a legacy digest while pinning SHA-256 internally.
How do I handle an intentional dependency upgrade?
Re-pin deliberately. When you bump a version on purpose, fingerprint the new artifact, and update the stored SHA-256 in the same commit as the version change. That way the pin update is part of the reviewable diff. An unexplained hash mismatch in CI (without a corresponding pin change) is then unambiguously an alert, not noise.
Is MD5 safe to use for a quick checksum here?
Only for detecting accidental corruption of a download from a source you already trust — it's fine for that. It is not safe for any security decision: an attacker can craft two different files with the same MD5 (and the same is true of SHA-1). For supply-chain integrity, where the whole point is defending against deliberate substitution, always pin and compare SHA-256 or SHA-512.
How big an artifact can I fingerprint?
Up to your tier's security file-size limit: Free 10 MB, Pro 100 MB, Pro-media 500 MB, Developer 2 GB. The whole file is read into memory before hashing — there's no streaming — so a large image tarball is bounded by both the cap and browser memory. For artifacts beyond your cap, recompute the hash with sha256sum directly in CI or run the server-safe path on a higher tier.
What about verifying the publisher, not just the bytes?
A checksum proves the file matches a published value; it doesn't prove who published it. If an attacker controls the mirror, they can swap both the file and its checksum. The stronger pattern is to verify a PGP signature over a published SHA256SUMS list with pgp-message-signer, then pin and recompute the artifact's SHA-256 against that signed list.
Can I batch-verify many artifacts at once?
Not in a single browser run — each run hashes the first dropped file only. For batch verification, script the server-safe runner: POST each artifact to the local endpoint and compare each returned sha256 against its pin. This keeps every file local while letting you check a whole release's worth of artifacts in a loop.
Privacy first
Every JAD Security operation runs entirely in your browser. Files, passwords, and PGP private keys never leave your device — verified by zero outbound network requests during processing.