<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e" -->

---
title: Testing Kyverno Attestation Policies: The Bug That...
description: A developer shares how a Kyverno attestation policy shipped broken twice — once due to a wrong JMESPath key prefix (predicate.invocation vs invocation), and...
canonical: https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Testing Kyverno Attestation Policies: The Bug That Shipped Twice, and What I Built to Stop a Third | daily.dev
og:description: A developer shares how a Kyverno attestation policy shipped broken twice — once due to a wrong JMESPath key prefix (predicate.invocation vs invocation), and...
og:url: https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e
og:image: https://api.daily.dev/og/posts/5MLy3g33e.png
og:image:alt: Testing Kyverno Attestation Policies: The Bug That Shipped Twice, and What I Built to Stop a Third
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Kyverno Attestation Policies: The Bug That Shipped Twice, and What I Built to Stop a Third

**[Medium](https://daily.dev/sources/medium_js)** · 7 min read · 1 upvotes · 0 comments

## Summary

A developer shares how a Kyverno attestation policy shipped broken twice — once due to a wrong JMESPath key prefix (predicate.invocation vs invocation), and once due to a copy-paste error referencing the wrong workflow filename. Both bugs passed kubectl apply --dry-run and code review undetected. The fix is a fixture-based Python test suite that extracts JMESPath conditions from ClusterPolicy YAML, evaluates them against a real captured SLSA provenance predicate, and fails fast on mismatches. A companion shell script catches cross-file identity drift by scanning all policy files for inconsistent workflow references. The resulting open-source kyverno-policy-pack includes both scripts and a CI workflow. Limitations are clearly stated: it doesn't replace live cluster testing, fixtures can go stale, and only Equals/NotEquals operators are currently covered.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@Juan_Makau/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-253cca784e7d>

## Questions this post answers

### Why does kubectl apply --dry-run not catch errors in Kyverno JMESPath attestation conditions?

Dry-run only validates that the policy YAML is syntactically valid and conforms to the ClusterPolicy CRD schema; it never evaluates the JMESPath expressions inside condition blocks against real data. From the schema's perspective a JMESPath string is just a string, so a wrong key path or stale expected value silently passes review, dry-run, and deployment.

_Developers hardening Kyverno policies can compare testing approaches for supply-chain security on daily.dev._

### How do you write a key path to access fields inside a Kyverno attestation predicate condition?

Reference fields directly against the predicate body, such as invocation.configSource.entryPoint, without prefixing with predicate., since Kyverno scopes condition evaluation directly to the predicate body rather than the full DSSE envelope. Adding a predicate. prefix resolves to nothing, silently causing the condition to never match and either blocking or admitting every image.

_Teams debugging Kyverno JMESPath scoping issues can find related fixes and discussion on daily.dev._

### How can I test that my Kyverno attestation policy conditions actually match real SLSA provenance data?

Pull every attestations[].conditions block from the policy YAML, strip Kyverno's {{ }} wrapper syntax, and evaluate the resulting JMESPath expression against a real captured SLSA provenance predicate using the jmespath library, comparing the result to the expected value with the same operator (Equals or NotEquals) Kyverno uses. This fixture-based approach, open-sourced as kyverno-policy-pack, catches wrong key paths and stale values that dry-run cannot detect.

_Engineers building CI checks for supply-chain policies can track fixture-based testing patterns on daily.dev._

## Similar posts on daily.dev

- [Vetting Kubernetes configuration with Kyverno prior to deployment](https://daily.dev/posts/vetting-kubernetes-configuration-with-kyverno-prior-to-deployment-m3cfjuial) · ITNEXT · 1 upvotes · 0 comments
- [Kyverno Explained: Why Modern Platforms Need Policy-as-Code](https://daily.dev/posts/kyverno-explained-why-modern-platforms-need-policy-as-code-wuk8roaoy) · Medium · 1 upvotes · 0 comments
- [Announcing Kyverno 1.17\!](https://daily.dev/posts/announcing-kyverno-1-17--fnlw905ut) · CNCF · 4 upvotes · 0 comments
- [Jim Bugwadia on why finding a Kubernetes problem is only half the battle for Kyverno users](https://daily.dev/posts/jim-bugwadia-on-why-finding-a-kubernetes-problem-is-only-half-the-battle-for-kyverno-users-bvgrfhwbj) · The New Stack · 1 upvotes · 0 comments
- [I made a policy engine think it was in production](https://daily.dev/posts/i-made-a-policy-engine-think-it-was-in-production-zivinf7jj) · CNCF · 0 upvotes · 0 comments

---

Tags: [#security](https://daily.dev/tags/security), [#kyverno](https://daily.dev/tags/kyverno)

[View this post on daily.dev](https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Testing Kyverno Attestation Policies: The Bug That Shipped Twice, and What I Built to Stop a Third","url":"https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e"},"datePublished":"2026-07-20T07:33:46.748Z","dateModified":"2026-09-13T19:15:24.380Z","description":"A developer shares how a Kyverno attestation policy shipped broken twice — once due to a wrong JMESPath key prefix (predicate.invocation vs invocation), and...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/bbb4a4de4e5264c435a088e8cc44e9b5?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/bbb4a4de4e5264c435a088e8cc44e9b5?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"security,kyverno","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"Testing Kyverno Attestation Policies: The Bug That Shipped Twice, and What I Built to Stop a Third"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/testing-kyverno-attestation-policies-the-bug-that-shipped-twice-and-what-i-built-to-stop-a-third-5mly3g33e#faq","mainEntity":[{"@type":"Question","name":"Why does kubectl apply --dry-run not catch errors in Kyverno JMESPath attestation conditions?","acceptedAnswer":{"@type":"Answer","text":"Dry-run only validates that the policy YAML is syntactically valid and conforms to the ClusterPolicy CRD schema; it never evaluates the JMESPath expressions inside condition blocks against real data. From the schema's perspective a JMESPath string is just a string, so a wrong key path or stale expected value silently passes review, dry-run, and deployment. Developers hardening Kyverno policies can compare testing approaches for supply-chain security on daily.dev."}},{"@type":"Question","name":"How do you write a key path to access fields inside a Kyverno attestation predicate condition?","acceptedAnswer":{"@type":"Answer","text":"Reference fields directly against the predicate body, such as invocation.configSource.entryPoint, without prefixing with predicate., since Kyverno scopes condition evaluation directly to the predicate body rather than the full DSSE envelope. Adding a predicate. prefix resolves to nothing, silently causing the condition to never match and either blocking or admitting every image. Teams debugging Kyverno JMESPath scoping issues can find related fixes and discussion on daily.dev."}},{"@type":"Question","name":"How can I test that my Kyverno attestation policy conditions actually match real SLSA provenance data?","acceptedAnswer":{"@type":"Answer","text":"Pull every attestations[].conditions block from the policy YAML, strip Kyverno's {{ }} wrapper syntax, and evaluate the resulting JMESPath expression against a real captured SLSA provenance predicate using the jmespath library, comparing the result to the expected value with the same operator (Equals or NotEquals) Kyverno uses. This fixture-based approach, open-sourced as kyverno-policy-pack, catches wrong key paths and stale values that dry-run cannot detect. Engineers building CI checks for supply-chain policies can track fixture-based testing patterns on daily.dev."}}]}
```

