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

  1. Verify you are using the attestation produced by the same build that produced the artifact
  2. Ensure the artifact file name exactly equals the subject Name in the provenance (it compares filepath.Base of the path)
  3. Recompute sha256 of the artifact and diff against the subject digest to confirm which field mismatches
  4. 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

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


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/6e467433daf68f5a. Report an issue: GitHub.