Secure Software Development / Advanced: components, evidence, and response / Lesson 14
Distinguish artifact integrity from build provenance
Review digests, producer claims, trusted verification, and release expectations without signing or deploying anything.
On this page
Lesson goals
- Explain what a digest comparison establishes and leaves unknown.
- Connect provenance to the exact artifact and approved producer expectations.
Separate the questions about a software artifact
An artifact can be unchanged from a downloaded copy yet come from an unintended source or untrusted builder. Integrity comparison, producer identity, source revision, build process, and approval are different claims. For the workshop release, identify the exact artifact under review and the expectations for its producer and inputs. A filename such as secure-release.zip carries no evidence by itself. Provenance can describe how an artifact was produced, but a description has value only when its authenticity, binding, and policy expectations are verified through an approved trust model.
Use hashes for the claim they support
A cryptographic digest allows comparison with an expected digest obtained through a trusted channel. The first program computes local SHA-256 values for two public byte strings and demonstrates change detection. It is not signature verification, trusted distribution, or proof of build execution. If an attacker can replace both an artifact and its unauthenticated checksum, matching them proves little about origin. Keep the expected value’s provenance in the review. A digest is also not encryption and should not be used to conceal a secret value by publishing its hash without a separate security design.
import hashlib
original = b"workshop-release-lab-v1"
changed = b"workshop-release-lab-v2"
expected = hashlib.sha256(original).hexdigest()
assert hashlib.sha256(original).hexdigest() == expected
assert hashlib.sha256(changed).hexdigest() != expected
assert len(expected) == 64
print("local byte-change detection checked")
local byte-change detection checked
The complete program hashes in-memory classroom strings only. It reads no release artifact and verifies no signature or identity. The expected digest is computed in the same program for demonstration, so it supplies no independent source trust.
Bind producer evidence to policy expectations
A provenance verifier needs to know which producers and build expectations are trusted for this artifact. Checking an authenticated statement’s subject digest, builder identity, source, and relevant parameters are distinct steps under the chosen format and policy. The second program models a decision after authenticity has supposedly been verified elsewhere; its boolean is a declared fixture fact, not a signature check. It uses a custom record, not a complete SLSA attestation. The explicit limitation prevents a convenient dictionary comparison from being presented as supply-chain verification.
def accept_reviewed_statement(statement):
return statement["authenticityVerified"] is True and statement["builder"] == "approved-lab-builder" and statement["sourceRevision"] == "lab-revision-8" and statement["artifactMatches"] is True
case = {"authenticityVerified":True, "builder":"approved-lab-builder", "sourceRevision":"lab-revision-8", "artifactMatches":True}
assert accept_reviewed_statement(case) is True
assert accept_reviewed_statement({**case, "builder":"other-builder"}) is False
assert accept_reviewed_statement({**case, "artifactMatches":False}) is False
print("declared provenance-policy facts checked")
declared provenance-policy facts checked
The complete program checks three declared policy cases using ordinary boolean comparisons. It performs no cryptographic verification and creates no attestation. A real verifier must establish the authenticity and artifact-binding facts instead of accepting them from a caller.
Review the build boundary as a system
Build security also depends on source controls, reviewed configuration, dependency resolution, isolation, and who can alter the process or its evidence. A signed statement from an untrusted or compromised producer does not automatically satisfy the release policy. Reproducibility can provide another useful comparison, but it is a separate property and may require carefully controlled inputs. Do not claim it from a deterministic JSON serialization example. Use the selected SLSA version as a reference for the threat model and verification questions while recording which properties the actual platform supports and verifies.
Preserve exact artifact and verification results
A release package should connect the reviewed source, build identity, artifact digest, component inventory, test evidence, and actual verification result. Missing provenance or an unexpected producer should remain a visible decision condition, not be replaced with a broad accept-anything fallback. Keep all platform configuration and signing operations outside these local exercises. The course checks public bytes and declared policy facts only. That limited evidence is useful for understanding the design, while actual signature validation, trusted roots, hosted builders, and deployment remain unexecuted boundaries requiring separate authorization and verification.
Common errors and fixes
Matching checksum is called trusted origin
- Why it happens
- The expected checksum is not independently authenticated.
- How to fix it
- Review the trust source and verify provenance under policy.
- Prevent it next time
- Separate integrity and producer-authenticity claims.
A caller supplies authenticityVerified=true
- Why it happens
- A claimed fact bypasses the verifier.
- How to fix it
- Establish authenticity at the trusted verification boundary.
- Prevent it next time
- Treat client provenance labels as untrusted input.
A signed artifact from any builder is accepted
- Why it happens
- Identity is verified without checking approved expectations.
- How to fix it
- Compare producer, source, parameters, and artifact binding.
- Prevent it next time
- Maintain a reviewed producer policy and meaningful failure behavior.
Check your understanding
1. Does hashing the artifact and its copied checksum file prove an approved build produced it?
Show worked solution
No. A hash comparison can detect a mismatch against the selected expected value, but it does not establish who supplied that value or how the artifact was built. Verify trusted producer evidence and artifact binding under the approved policy, then record actual results rather than inferred provenance.
2. Why does the local policy model require artifactMatches separately from builder?
Show worked solution
A statement can name an approved builder yet describe a different artifact. Binding the exact reviewed bytes to the authenticated statement is a separate necessary fact. The model assumes that fact for teaching; a real verifier must establish it cryptographically and enforce the full selected policy.
Key takeaways
- Integrity, origin, build process, and approval are distinct claims.
- Provenance must be authenticated, bound, and checked against expectations.
- Local hashes and policy models do not verify a hosted supply chain.