Kustomize OCI Image Digest Matching Fix


kustomize had a quiet week on master: one commit, two files, 36 lines added. The change is small but operationally sharp. Teams that pin workloads with digest algorithms other than sha256 could see their images: overrides silently ignored during kustomize build.

Activity on kustomize between June 16 and June 23 was minimal. The default branch picked up a single fix from match image digests with any algorithm, not only sha256. Diff stats: 2 files changed, 36 insertions, 1 deletion.

That is not a feature drop. It closes a mismatch between two helpers in the same package. Split in api/internal/image/image.go already parsed any digest string after @. IsImageMatched only recognized @sha256:. If your manifest used nginx@sha512:... or another OCI valid algorithm, the name check failed before any rewrite logic ran.

The symptom is easy to miss. kustomize build succeeds. The rendered YAML still shows the old registry path or digest you thought you replaced. No error, no warning. The ImageTagTransformer path calls IsImageMatched first; on false it returns nil and leaves the scalar unchanged.

Before the fix, IsImageMatched compiled a pattern that hard coded the digest prefix:

pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.{}-]*)?(@sha256:[a-zA-Z0-9_.{}-]*)?$")

That worked for the common case. Most production pins use sha256 because container registries and CI scanners default to it. It failed for sha512 pins, composite algorithm names like multihash+base58, or any reference that followed the OCI image descriptor digest rules without using sha256.

The June 20 fix generalizes the algorithm segment:

pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.{}-]*)?(@[a-zA-Z0-9]+([.+_-][a-zA-Z0-9]+)*:[a-zA-Z0-9_.{}-]*)?$")

Algorithm components can now be separated by +, ., _, or -, matching the grammar described in the image spec. The commit message notes this aligns matching behavior with what Split already accepted. Review feedback pushed the regex beyond a naive [a-zA-Z][a-zA-Z0-9]* algorithm token so registered and unregistered OCI algorithms both match.

Winners: overlays that retag or retarget images pinned by sha512, or teams experimenting with alternative digest schemes. Losers: none for typical sha256 users. The old path still matches. The tradeoff is slightly broader acceptance of malformed references that happen to fit the pattern, which is the same class of risk the previous sha256 only regex carried.

The functional change lives almost entirely in api/internal/image/image.go. api/internal/image/image_test.go gained four table driven cases in the same commit:

  • nginx@sha512:xyz matches name nginx
  • nginx:12345@sha512:xyz matches with both tag and digest present
  • A full length sha512 digest from the OCI descriptor examples matches
  • nginx@multihash+base58:QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 matches

Those cases encode the intended contract for operators. If your kustomization images entry names nginx and the workload references that image with any OCI valid digest suffix, the transformer should now enter the rewrite branch. Existing sha256 cases in the test file were untouched, which limits regression risk for the majority of clusters.

Kustomize applies images: entries through the builtin ImageTagTransformer, which walks resource fields and rewrites container image scalars when the name matches. The flow in the updater is sequential: match name, split components, apply newName, newTag, digest, or tagSuffix, then write the scalar back.

Teams using digest only pins in base manifests and overlay specific registry mirrors are the most likely to have hit the bug. Example: base Deployment lists my.registry/app@sha512:abc..., overlay sets images: [{name: my.registry/app, newName: mirror.internal/app}]. Before the fix, IsImageMatched returned false, so the overlay left the original reference intact. After upgrading, the same kustomization should emit mirror.internal/app@sha512:abc... or apply digest overrides when configured.

This does not change how kustomize resolves tags to digests. It only fixes name matching when a digest is already present in the manifest string. Operators still need separate tooling to fetch and pin digests. The fix removes a silent no op in the transform layer.

Sha256 pinned fleets should see no behavior change. If you standardize on sha256 everywhere, this commit is internal hygiene. The value shows up when you audit non sha256 pins or when a security policy mandates sha512 for certain artifacts.

Pick up a kustomize build that includes 9f89960c or wait for the next tagged release that vendors this master commit. Re run kustomize build on overlays that combine images: with digest pinned bases and diff against your last known good output. Any reference that suddenly rewrites was previously stuck.

Watch for follow up on image matching at registry scope. This fix operates on the image name segment only; domain and port parsing still flow through Split with separate rules. If you use complex host:port/path references with exotic digest algorithms, keep those manifests in CI diff checks.

No deprecations or flag changes landed in this window. The activity is narrow. Treat it as a correctness patch for a corner case that became more common as registries and supply chain tools diversify digest algorithms beyond sha256.