hashicorp/packer · error

builder and source policy checks require predicate type %q,

Error message

builder and source policy checks require predicate type %q, got %q

What it means

Builder-ID and Source-URI policy checks are only implemented for SLSA provenance v1, whose predicate carries buildDefinition.resolvedDependencies and runDetails.builder.id. This error means the policy asked for builder or source checks but the attestation's predicateType is not https://slsa.dev/provenance/v1.

Source

Thrown at internal/attestation/verify.go:242

	}

	if statement.Type != internalprovenance.StatementType {
		return nil, fmt.Errorf("unexpected attestation statement type %q", statement.Type)
	}

	if policy.PredicateType != "" && statement.PredicateType != policy.PredicateType {
		return nil, fmt.Errorf("attestation predicate type %q does not match expected %q", statement.PredicateType, policy.PredicateType)
	}

	if policy.ArtifactPath != "" {
		if err := verifyArtifactSubject(statement.Subject, policy.ArtifactPath); err != nil {
			return nil, err
		}
	}

	if policy.BuilderID != "" || policy.SourceURI != "" {
		if statement.PredicateType != internalprovenance.SLSAProvenanceV1PredicateType {
			return nil, fmt.Errorf("builder and source policy checks require predicate type %q, got %q", internalprovenance.SLSAProvenanceV1PredicateType, statement.PredicateType)
		}

		var typedStatement struct {
			Type          string                                     `json:"_type"`
			Subject       []internalprovenance.Subject               `json:"subject"`
			PredicateType string                                     `json:"predicateType"`
			Predicate     internalprovenance.SLSAProvenancePredicate `json:"predicate"`
		}
		if err := json.Unmarshal(payload, &typedStatement); err != nil {
			return nil, fmt.Errorf("decode SLSA predicate for policy verification: %w", err)
		}

		if policy.BuilderID != "" && typedStatement.Predicate.RunDetails.Builder.ID != policy.BuilderID {
			return nil, fmt.Errorf("attestation builder id %q does not match expected %q", typedStatement.Predicate.RunDetails.Builder.ID, policy.BuilderID)
		}

		if policy.SourceURI != "" {
			matched := false

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Regenerate the attestation with a builder that emits https://slsa.dev/provenance/v1 provenance.
  2. Remove the BuilderID/SourceURI fields from the policy if you only need predicate/subject checks for non-v1 attestations.
  3. If your attestation is v0.2, normalize/convert it to v1 before verification.
  4. Verify the producing pipeline's predicateType URI is exactly https://slsa.dev/provenance/v1 (no trailing slash or version typos).

Example fix

// policy: builder check on a v0.2 attestation fails
// before
policy.SourceURI = "git+https://github.com/org/repo@refs/heads/main" // attestation is provenance/v0.2
// after: upgrade producer or use a v1 provenance attestation
{"_type":"https://in-toto.io/Statement/v1","predicateType":"https://slsa.dev/provenance/v1",...}
Defensive patterns

Strategy: validation

Validate before calling

if (policy.BuilderID != "" || policy.SourceURI != "") {
	var s struct{ PredicateType string `json:"predicateType"` }
	_ = json.Unmarshal(payload, &s)
	if s.PredicateType != "https://slsa.dev/provenance/v1" {
		return fmt.Errorf("builder/source checks need SLSA v1, got %q", s.PredicateType)
	}
}

Type guard

func isSLSAProvenanceV1(payload []byte) bool {
	var s struct{ PredicateType string `json:"predicateType"` }
	return json.Unmarshal(payload, &s) == nil && s.PredicateType == "https://slsa.dev/provenance/v1"
}

Try / catch

_, err := VerifyAttestationFile(path, policy)
if err != nil && strings.Contains(err.Error(), "builder and source policy checks require") {
	// either upgrade producer to SLSA v1 or drop BuilderID/SourceURI from policy
}

Prevention

When it happens

Trigger: VerifyAttestationFile with a policy that sets BuilderID or SourceURI while the attestation predicateType is empty, a non-SLSA predicate, or SLSA provenance v0.2.

Common situations: Enforcing builder/source policy against attestations produced by older CI tooling emitting v0.2 provenance; policy applied to generic in-toto attestations (e.g. SBOM) that have no provenance predicate; typo'd predicateType in the producing pipeline.

Related errors


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