hashicorp/packer · error
attestation subject does not match artifact %q
Error message
attestation subject does not match artifact %q
What it means
After hashing the artifact, verifyArtifactSubject searches the provenance subjects for one whose Name equals the artifact's base filename and whose sha256 digest matches (case-insensitively) the computed hash. If none matches, the attestation's subject does not describe this artifact — i.e. the provenance was generated for a different build/output.
Source
Thrown at internal/attestation/verify.go:396
}
return fmt.Errorf("sigstore bundle signature does not match any attestation signature")
}
func verifyArtifactSubject(subjects []internalprovenance.Subject, artifactPath string) error {
digest, err := sha256File(artifactPath)
if err != nil {
return fmt.Errorf("hash artifact %q: %w", artifactPath, err)
}
artifactName := filepath.Base(artifactPath)
for _, subject := range subjects {
if subject.Name == artifactName && strings.EqualFold(subject.Digest["sha256"], digest) {
return nil
}
}
return fmt.Errorf("attestation subject does not match artifact %q", artifactPath)
}
func sha256File(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", err
}
defer func() { _ = file.Close() }()
hasher := sha256.New()
if _, err := io.Copy(hasher, file); err != nil {
return "", err
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
View on GitHub (pinned to eb36e3c3e4)
Solutions
- Verify you are using the attestation produced by the same build that produced the artifact
- Ensure the artifact file name exactly equals the subject Name in the provenance (it compares filepath.Base of the path)
- Recompute sha256 of the artifact and diff against the subject digest to confirm which field mismatches
- Re-generate the attestation after renaming or rebuilding the artifact
Example fix
// before: artifact rebuilt after attestation, hash mismatch
verifyPolicy(attestationFromOldBuild, "/out/app-linux-amd64")
// after: regenerate attestation for the current artifact
att := generateProvenance("/out/app-linux-amd64")
verifyPolicy(att, "/out/app-linux-amd64") Defensive patterns
Strategy: validation
Validate before calling
digest, err := sha256File(artifactPath)
if err != nil { return err }
name := filepath.Base(artifactPath)
for _, s := range subjects {
if s.Name == name && strings.EqualFold(s.Digest["sha256"], digest) { return nil }
}
return fmt.Errorf("artifact %s (sha256 %s) not covered by attestation subjects", name, digest) Try / catch
if err := verifyArtifactSubject(subjects, path); err != nil {
return fmt.Errorf("attestation does not describe %s — regenerate attestation for this build: %w", path, err)
} Prevention
- Regenerate attestations whenever the artifact is rebuilt or renamed
- Keep artifact filenames stable across builds (subject Name is the base filename)
- Pair each artifact with its attestation by build ID, not by directory convention
- Recompute sha256 locally and compare with the subject before invoking verification
When it happens
Trigger: verifyPolicy compares a provenance attestation whose subjects list contains no entry with name == filepath.Base(artifactPath) and a matching sha256 — wrong artifact passed to verification, or attestation from a different build (hash differs) or different artifact name (rename).
Common situations: Artifact rebuilt after attestation generation (hash changed); artifact renamed after signing (basename mismatch); verifying against the wrong attestation file in a directory of many attestations; subject name includes a path/prefix that does not equal the bare filename.
Related errors
- artifact is nil
- marshal attestation payload: %w
- write attestation %q: %w
- signing_mode %q does not support Sigstore bundle emission
- decode envelope payload: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/6e467433daf68f5a.
Report an issue: GitHub.