hashicorp/packer · error

decode SLSA predicate for policy verification: %w

Error message

decode SLSA predicate for policy verification: %w

What it means

After confirming the statement is SLSA provenance v1, verifyPolicy re-decodes the payload into a typed structure that includes the SLSAProvenancePredicate. This error wraps any JSON decoding failure of that typed structure, e.g. when the predicate object is missing, not an object, or its fields (runDetails, buildDefinition) have incompatible shapes.

Source

Thrown at internal/attestation/verify.go:252

	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
			for _, dependency := range typedStatement.Predicate.BuildDefinition.ResolvedDependencies {
				if dependency.URI == policy.SourceURI {
					matched = true
					break
				}
			}
			if !matched {
				return nil, fmt.Errorf("attestation does not contain expected source URI %q", policy.SourceURI)
			}
		}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Inspect the attestation's `predicate` field; ensure it exists and follows the SLSA provenance v1 schema (buildDefinition, runDetails).
  2. Regenerate the attestation with an up-to-date, spec-compliant producer.
  3. Validate the attestation against the SLSA v1 JSON schema before verification.
  4. Check the underlying wrapped decode error (%w) for the exact JSON path/type that failed.

Example fix

// before
{"predicateType":"https://slsa.dev/provenance/v1"} // predicate missing
// after
{"predicateType":"https://slsa.dev/provenance/v1","predicate":{"buildDefinition":{...},"runDetails":{...}}}
Defensive patterns

Strategy: type-guard

Validate before calling

var s struct {
	PredicateType string `json:"predicateType"`
	Predicate     struct {
		RunDetails      json.RawMessage `json:"runDetails"`
		BuildDefinition json.RawMessage `json:"buildDefinition"`
	} `json:"predicate"`
}
if err := json.Unmarshal(payload, &s); err != nil || len(s.Predicate.RunDetails) == 0 {
	return fmt.Errorf("malformed SLSA v1 predicate")
}

Type guard

func hasSLSAV1PredicateShape(payload []byte) bool {
	var s struct {
		Predicate struct {
			RunDetails      json.RawMessage `json:"runDetails"`
			BuildDefinition json.RawMessage `json:"buildDefinition"`
		} `json:"predicate"`
	}
	return json.Unmarshal(payload, &s) == nil && s.Predicate.RunDetails != nil && s.Predicate.BuildDefinition != nil
}

Try / catch

_, err := VerifyAttestationFile(path, policy)
if err != nil && strings.Contains(err.Error(), "decode SLSA predicate") {
	var syntaxErr *json.SyntaxError
	if errors.As(err, &syntaxErr) {
		log.Printf("bad JSON at offset %d", syntaxErr.Offset)
	}
}

Prevention

When it happens

Trigger: VerifyAttestationFile with a policy containing BuilderID or SourceURI, on an attestation whose predicateType claims v1 but whose predicate body is absent, null, or does not match the SLSA v1 schema (wrong nesting, wrong field types).

Common situations: Hand-crafted or tool-mangled attestations that label themselves v1 but omit the predicate; predicates following an incompatible draft schema; corrupted/truncated JSON files.

Related errors


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