Checksum Security & CDN
Master checksum security: cryptographic hashing, integrity verification, and CDN security patterns.
What is checksum security for a CDN?
Checksum security verifies that bytes delivered through a Content Delivery Network (CDN) are exactly the bytes a trusted release produced. A cryptographic hash turns a file into a fixed-size digest. The verifier hashes the downloaded file and blocks it when that result differs from the expected digest.
This matters because a CDN copies assets across many edge locations. A corrupted cache entry, stale deployment, compromised edge, or altered third-party script can otherwise reach users at global scale. The core invariant is: verify delivered bytes against a digest obtained through a trust path the asset distributor cannot silently rewrite.
Detect changed bytes
Digest
A cryptographic hash such as SHA-256 or SHA-384 maps any file size to a fixed-size value. Even a small byte change should produce a different digest.
Anchor the comparison
Trusted reference
The expected digest must come from authenticated HTML, a signed release manifest, or another protected control plane. A digest beside the asset in the same writable location is only a claim.
Stop unsafe execution
Enforcement
The browser, origin, or deployment pipeline must fail closed on mismatch. Detection without blocking, alerting, and recovery leaves the user on the unsafe path.
A verified asset has two paths
The asset bytes travel through the CDN. The expected digest travels through a protected release path. Verification is meaningful because those paths do not share the same write authority.
Produce
Build job
Create immutable asset bytes and compute the digest once.
Trust
Release record
Bind the asset URL, digest, algorithm, and release identity.
Distribute
CDN edge
Cache and serve the versioned object near users.
Enforce
Verifier
Recompute, compare, block mismatch, and report evidence.
Integrity is not authenticity by itself
A checksum answers a narrow question: “Did these bytes match this expected value?” It does not answer “Who published the expected value?” If an attacker can replace both the file and its digest, the comparison still succeeds.
Use the controls as a stack:
- TLS authenticates the endpoint and protects the digest or signed manifest while it travels.
- A release signature lets a verifier authenticate a manifest even when storage and CDN operators are not trusted to author releases.
- Subresource Integrity (SRI) tells a browser which digest an external script or stylesheet must match before execution or application.
- Immutable versioned URLs prevent one cache key from referring to different releases over time.
- Authorization and protected build credentials limit who may create a release in the first place.
The decisive boundary
Keep the expected digest outside the asset's writable failure domain. Separate buckets are not separate trust boundaries when the same compromised credential can rewrite both.
Lab 1: separate byte matching from publisher trust
The lab computes real Web Crypto digests. Change one instruction in the asset, switch the algorithm, and move the expected value between an independent release record and an edge-controlled sidecar. Watch how “digest match” and “safe to execute” become different decisions.
Loading integrity lab
Publish integrity metadata as part of the release
Treat asset bytes, integrity metadata, and the document that references them as one versioned release. A safe sequence is:
1 Create
Build immutable bytes
Use a content-hashed filename such as
app.7f3a.js. Once published, never overwrite that key with new bytes.2 Bind
Compute and attest
Generate SHA-256 or SHA-384 from the exact artifact. Put the URL and digest in authenticated HTML or a signed manifest.
3 Stage
Distribute before reference
Upload the asset, warm or verify representative edges, then publish the HTML that references it. Retain the previous release for rollback.
4 Enforce
Verify and observe
Block mismatches, record release and edge identifiers, and alert on a rate that distinguishes isolated corruption from a broad deployment fault.
For browser SRI, place the generated token in the script or stylesheet's integrity attribute. Use crossorigin="anonymous" for a cross-origin asset and configure the asset response so the CORS check succeeds. Browsers accept SRI algorithms from the SHA-2 family: SHA-256, SHA-384, and SHA-512.
Example 1: generate an SRI token
This dependency-free Python CLI hashes the exact file that will be uploaded. Its Base64 output can be inserted into authenticated HTML.
Example 2: verify a signed release record
This Node.js example signs a manifest in the build role and verifies both its signature and asset digest in the serving role. The generated key pair keeps the example executable; production keeps the private key offline from the CDN and pins or securely distributes the public key.
Choose algorithms for an adversarial setting
256 bits
SHA-256 digest
32 raw bytes; suitable general-purpose cryptographic integrity.
384 bits
SHA-384 digest
48 raw bytes; a common SRI choice for browser assets.
512 bits
SHA-512 digest
64 raw bytes; larger metadata without replacing trust.
0 identities
Hash alone
A digest does not authenticate its publisher.
Algorithm speed is rarely the main CDN design decision because release artifacts are normally hashed once and verified from local bytes. Choose for collision and preimage resistance, interoperability, and lifecycle support:
- Use SHA-256 or SHA-384 for new security-sensitive integrity checks.
- Do not use MD5 or SHA-1 against an attacker. Their collision resistance is broken, even though they can still detect many accidental changes.
- Use a non-cryptographic hash only for partitioning, deduplication hints, or accidental-error checks where no adversary can choose the input.
- Store the algorithm with the digest so verifiers can reject unknown or retired algorithms and support controlled migration.
Lab 2: trace CDN failures without weakening the boundary
A mismatch can mean an attack, disk corruption, a stale edge, or a deployment ordering bug. The browser should still block first. Switch delivery scenarios, inspect the active path, and select nodes to see which component owns each response.
Respond to a production mismatch
Design the failure path before the first incident:
- Contain: prevent the asset from executing or being applied. Do not retry the same unverified mutable URL until it happens to work.
- Scope: group reports by release ID, asset digest, CDN point of presence, cache status, and time window.
- Compare: hash the build artifact, origin object, and sampled edge response. Verify the release record's signature or authenticated source separately.
- Recover: route to a separately verified copy, purge the affected object, or roll back the HTML and asset references as one release.
- Preserve evidence: retain mismatched bytes, headers, manifest, edge ID, and deployment events before deletion or purge removes the evidence.
- Close the gap: rotate exposed credentials, repair deployment ordering, and test the exact failure in staging and canary edges.
A fallback needs its own proof
Loading /fallback.js after an SRI failure is safe only when that fallback has an independently trusted digest or is covered by the authenticated application release. “Local” is a location, not a security property.
Production review checklist
Before shipping a CDN integrity design, verify that:
- Asset URLs are immutable and a release never overwrites bytes under an existing versioned key.
- The expected digest is generated from the uploaded artifact, not from a different build workspace output.
- The asset and its expected digest cannot both be rewritten by one CDN or storage credential.
- Browser SRI and CORS behavior is tested for the actual cross-origin response headers.
- A mismatch blocks execution and emits enough release, edge, and asset context to investigate.
- Rollback restores a complete known-good document and asset set instead of mixing release generations.
- The previous verified release remains available during cache propagation and incident response.
- Hash algorithm migration supports overlap without silently accepting retired algorithms forever.