Skip to content

OCPBUGS-43353: Add pattern validation for registry entries in image config#2787

Open
reedcort wants to merge 1 commit intoopenshift:masterfrom
reedcort:OCPBUGS-43353
Open

OCPBUGS-43353: Add pattern validation for registry entries in image config#2787
reedcort wants to merge 1 commit intoopenshift:masterfrom
reedcort:OCPBUGS-43353

Conversation

@reedcort
Copy link
Copy Markdown

@reedcort reedcort commented Mar 31, 2026

Summary

  • Add per-item Pattern validation to insecureRegistries, blockedRegistries, and allowedRegistries fields in the RegistrySources struct (config/v1/types_image.go)
  • Uses the same regex pattern already used by ImageDigestMirrors.Source for consistency
  • Rejects entries with tags (e.g., :latest) or digests (e.g., @sha256:...) that would generate invalid /etc/containers/policy.json and can cause container runtime failures
  • CRD validation ratcheting automatically preserves pre-existing invalid entries on update

Background

Invalid registry entries like registry.io/myrepo:latest in spec.registrySources.blockedRegistries pass through without validation and generate an invalid /etc/containers/policy.json, which can cause container runtime failures.

Validation was initially proposed in hypershift#8070 at the Go level (webhook, controller, nodepool config). That PR was closed in favor of adding the canonical validation here at the API level, as requested by the maintainer.

Test plan

  • make update — all CRD manifests regenerated
  • make -C config/v1 test — all integration tests pass
  • make verify — passes
  • Ratcheting tests verify persisted invalid entries are preserved on update
  • onCreate tests verify invalid tagged/digest entries are rejected
  • Valid entry tests cover hostname, hostname/path, wildcard, hostname:port/path

🤖 Generated with Claude Code

@openshift-ci-robot
Copy link
Copy Markdown

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 31, 2026

Hello @reedcort! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci openshift-ci bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Mar 31, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 8c3c4841-83b1-4444-9d3a-a7c745d8173f

📥 Commits

Reviewing files that changed from the base of the PR and between 6ab1419 and 44dae4a.

⛔ Files ignored due to path filters (4)
  • config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/ImageStreamImportMode.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • openapi/generated_openapi/zz_generated.openapi.go is excluded by !openapi/**
📒 Files selected for processing (4)
  • config/v1/tests/images.config.openshift.io/AAA_ungated.yaml
  • config/v1/types_image.go
  • config/v1/zz_generated.swagger_doc_generated.go
  • payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml
✅ Files skipped from review due to trivial changes (1)
  • config/v1/zz_generated.swagger_doc_generated.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • config/v1/types_image.go
  • payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml

📝 Walkthrough

Walkthrough

Added per-item regex validation to RegistrySources' insecureRegistries, blockedRegistries, and allowedRegistries, enforcing entries to match a registry-scope format hostname[:port][/path] with an optional *. wildcard for subdomains and explicitly rejecting image tags or digests. Corresponding field comments and Swagger documentation were updated to describe the format and restrictions. The CRD YAML item schemas were modified to include the new patterns. New conformance tests were added to validate acceptance and rejection of various registry entry formats on create and update.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.4)

Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 31, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign deads2k for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/v1/types_image.go`:
- Line 176: The XValidation:rule regex used in the kubebuilder tag for registry
hostnames in types_image.go is too permissive and must be replaced with a
stricter pattern that: disallows empty labels and consecutive dots, disallows
labels that start or end with a hyphen, allows an optional leading wildcard of
the form "*.example.com", allows an optional ":port" immediately after the
hostname (port = one or more digits), and permits optional path segments
("/repo" parts) composed of lowercase letters, digits, dot, underscore or
hyphen; update the XValidation:rule value (the kubebuilder tag string containing
the regex) to enforce these constraints (i.e., ensure each label matches
[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])? and labels are separated by single
dots, optional leading "*." allowed, optional :[0-9]+ after the hostname, then
optional (/[a-z0-9._-]+)* path segments) so valid hosts like "good.example.com",
"quay.io/ns/repo", "*.example.com", and "a.b" are accepted while invalid ones
like "example..com" or "a.-b.com" are rejected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 3199948e-925c-4a7a-8be3-c0988a0268e3

📥 Commits

Reviewing files that changed from the base of the PR and between 96f1f5a and 6ab1419.

⛔ Files ignored due to path filters (4)
  • config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/ImageStreamImportMode.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • openapi/generated_openapi/zz_generated.openapi.go is excluded by !openapi/**
📒 Files selected for processing (3)
  • config/v1/types_image.go
  • config/v1/zz_generated.swagger_doc_generated.go
  • payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml

@JoelSpeed
Copy link
Copy Markdown
Contributor

@reedcort These validations are restricting existing GA APIs. How can you be confident in the maximum limits you have added, and that they won't break existing users/use cases? Do you have any telemetry data that would demonstrate the existing usage of these fields?

@reedcort
Copy link
Copy Markdown
Author

@JoelSpeed I noticed that as well. I'm updating the validation to use Pattern instead, which removes the MaxItems and MaxLength constraints entirely to avoid impacting current users.

@JoelSpeed
Copy link
Copy Markdown
Contributor

I noticed that as well. I'm updating the validation to use Pattern instead, which removes the MaxItems and MaxLength constraints entirely to avoid impacting current users.

Any change you make here is going to potentially be breaking. There are existing users of this API. You need to understand/explain how this will impact existing users before we can accept any change that makes the API more restrictive.

We actually do prefer CEL to pattern btw, but we still need to answer my previous questions. What do you know about existing usage of these API fields?

@reedcort reedcort marked this pull request as draft March 31, 2026 16:55
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 31, 2026
@reedcort
Copy link
Copy Markdown
Author

Thanks, makes sense. I'll work on gathering telemetry data on the existing usage of the fields across the fleet.

@reedcort reedcort changed the title Add CEL validation for registry entries in image config OCPBUGS-43353: Add CEL validation for registry entries in image config Apr 1, 2026
@openshift-ci-robot openshift-ci-robot added jira/severity-moderate Referenced Jira bug's severity is moderate for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Apr 1, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@reedcort: This pull request references Jira Issue OCPBUGS-43353, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @xiuwang

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Summary

  • Add per-item CEL validation rules to insecureRegistries, blockedRegistries, and allowedRegistries fields in the RegistrySources struct (config/v1/types_image.go)
  • Each entry is validated against a regex matching valid registry scopes: hostname[:port][/path], optionally with *. wildcard prefix
  • Rejects entries with tags (e.g., :latest) or digests (e.g., @sha256:...) that would generate invalid /etc/containers/policy.json and cause CRI-O to fail
  • Adds MaxItems=512 and items:MaxLength=512 bounds required by the Kubernetes CEL cost estimator

Background

Invalid registry entries like trusted.com/myrepo:latest in spec.configuration.image.registrySources.blockedRegistries pass through without validation, generate an invalid /etc/containers/policy.json, cause CRI-O startup failure, and result in nodes silently failing to join the cluster.

Validation was initially proposed in hypershift#8070 at the Go level (webhook, controller, nodepool config). That PR was closed in favor of adding the canonical CEL validation here at the API level, as requested by the maintainer.

Test plan

  • make update — all CRD manifests regenerated
  • make -C config/v1 test — all 1761 integration tests pass
  • make verify — passes (0 lint issues, 0 kube-api-linter issues)
  • Verify on a staging cluster that invalid entries are rejected at admission

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested a review from xiuwang April 1, 2026 15:38
@reedcort
Copy link
Copy Markdown
Author

reedcort commented Apr 2, 2026

@JoelSpeed I gathered telemetry data to answer your questions.

Telemetry

Queried CCX/Insights archive across the fleet:

Metric Count
Total clusters with registrySources data ~61,241
Clusters with tagged entries (e.g. :latest) ~108 (0.18%)

Approach

I plan to update the PR to use the same regex pattern already used by ImageDigestMirrors.Source in this repo (config/v1/types_image_digest_mirror_set.go), which supports both wildcard prefixes and Docker-style path separators (__, ---). This rejects tags while allowing all valid registry scopes (hostname[:port][/path]).

Kubernetes CRD validation ratcheting automatically handles existing invalid entries — on update, the API server suppresses validation errors for unchanged values. The ~108 clusters with existing tagged entries would be unaffected; only new invalid entries would be rejected.

One nuance worth noting: during testing I found that reg1.io/myrepo/myapp:latest (2+ path components) is technically valid in policy.json, while trusted.com/myrepo:latest is not — so the breakage from tagged entries is format-dependent and unpredictable for users. Adding this regex would reject both. Since these fields are called blockedRegistries/allowedRegistries/insecureRegistries — semantically they represent registry/repo scopes, not image references — I think this is the right behavior.

Do you think this validation belongs here in the API, or would it be better placed in the MCO / HyperShift operator instead?

@JoelSpeed
Copy link
Copy Markdown
Contributor

Thanks for doing the research. As long as we can add a test case that demonstrates the ratcheting behaviour of currently invalid values (see our tests folder readme and look for ratcheting to see examples), then I think we can proceed with adding the validations here

Invalid registry entries (e.g., with tags like ":latest" or digests like
"@sha256:...") in registrySources fields generate an invalid
/etc/containers/policy.json, which can cause container runtime failures.

Add per-item Pattern validation to insecureRegistries, blockedRegistries,
and allowedRegistries fields in the RegistrySources struct using the same
regex pattern already used by ImageDigestMirrors.Source. Each entry must
match a valid registry scope: hostname[:port][/path], optionally with a
wildcard prefix (*.). CRD validation ratcheting ensures pre-existing
invalid entries are preserved on update.

Includes integration tests demonstrating:
- Invalid tagged/digest entries are rejected on create
- Valid entries (hostname, path, wildcard, port) are accepted
- Ratcheting preserves persisted invalid entries when other fields change
- Modifying an atomic list with a persisted invalid entry is rejected

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@reedcort reedcort changed the title OCPBUGS-43353: Add CEL validation for registry entries in image config OCPBUGS-43353: Add pattern validation for registry entries in image config Apr 2, 2026
@reedcort
Copy link
Copy Markdown
Author

reedcort commented Apr 2, 2026

/test lint
/test integration
/test verify
/test verify-client-go
/test verify-crd-schema
/test verify-crdify
/test verify-deps
/test verify-feature-promotion

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Apr 2, 2026

PR-Agent: could not fine a component named lint in a supported language in this PR.

@reedcort
Copy link
Copy Markdown
Author

reedcort commented Apr 2, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@reedcort reedcort marked this pull request as ready for review April 6, 2026 19:45
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 6, 2026
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add pattern validation for registry entries in image config

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add per-item Pattern validation to registry entry fields in RegistrySources
  - Validates insecureRegistries, blockedRegistries, allowedRegistries
  - Rejects entries with tags (:latest) or digests (@sha256:...)
• Enforce valid registry scope format: hostname[:port][/path] with optional wildcard prefix
• CRD validation ratcheting preserves pre-existing invalid entries on update
• Comprehensive test coverage for invalid/valid entries and ratcheting behavior
Diagram
flowchart LR
  A["RegistrySources Fields"] -->|Pattern Validation| B["insecureRegistries"]
  A -->|Pattern Validation| C["blockedRegistries"]
  A -->|Pattern Validation| D["allowedRegistries"]
  B -->|Reject| E["Invalid: tags/digests"]
  C -->|Reject| E
  D -->|Reject| E
  B -->|Accept| F["Valid: hostname[:port][/path]"]
  C -->|Accept| F
  D -->|Accept| F
  F -->|Wildcard Support| G["*.example.com"]
Loading

Grey Divider

File Changes

1. config/v1/types_image.go ✨ Enhancement +18/-0

Add pattern validation to registry entry fields

• Added detailed documentation comments to insecureRegistries, blockedRegistries, and
 allowedRegistries fields
• Added kubebuilder:validation:items:Pattern annotations with regex pattern to validate registry
 scope format
• Pattern enforces hostname with valid DNS labels, optional port, optional path, and optional
 wildcard prefix
• Rejects entries containing tags (:) or digests (@) that would generate invalid policy.json

config/v1/types_image.go


2. config/v1/zz_generated.swagger_doc_generated.go 📝 Documentation +3/-3

Update swagger documentation for registry fields

• Updated swagger documentation for insecureRegistries, blockedRegistries, and
 allowedRegistries
• Added validation requirements and format specifications to field descriptions
• Clarified that entries must not include tags or digests

config/v1/zz_generated.swagger_doc_generated.go


3. openapi/generated_openapi/zz_generated.openapi.go 📝 Documentation +3/-3

Update OpenAPI schema descriptions

• Updated OpenAPI schema descriptions for registry entry fields
• Added validation format and constraint information to field descriptions
• Synchronized with swagger documentation changes

openapi/generated_openapi/zz_generated.openapi.go


View more (5)
4. config/v1/tests/images.config.openshift.io/AAA_ungated.yaml 🧪 Tests +202/-0

Add comprehensive validation and ratcheting tests

• Added 7 new onCreate tests validating rejection of tagged/digest entries in all three registry
 fields
• Added 2 onCreate tests validating acceptance of valid registry entries (hostname, path,
 wildcard, port)
• Added 3 onUpdate tests verifying ratcheting preserves persisted invalid entries when other
 fields change
• Added 2 onUpdate tests verifying atomic list re-validation prevents appending to lists with
 invalid entries

config/v1/tests/images.config.openshift.io/AAA_ungated.yaml


5. config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images.crd.yaml ⚙️ Configuration changes +20/-2

Add pattern validation to CRD manifest

• Added pattern validation to CRD manifest for allowedRegistries, blockedRegistries, and
 insecureRegistries
• Updated field descriptions with validation requirements and format specifications
• Pattern enforces valid registry scope format with DNS label constraints

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images.crd.yaml


6. config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/AAA_ungated.yaml ⚙️ Configuration changes +20/-2

Add pattern validation to featuregated CRD

• Added pattern validation to featuregated CRD manifest for registry entry fields
• Updated field descriptions with validation requirements
• Synchronized with main CRD manifest changes

config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/AAA_ungated.yaml


7. config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/ImageStreamImportMode.yaml ⚙️ Configuration changes +20/-2

Add pattern validation to ImageStreamImportMode CRD

• Added pattern validation to ImageStreamImportMode featuregated CRD manifest
• Updated field descriptions with validation requirements
• Synchronized with main CRD manifest changes

config/v1/zz_generated.featuregated-crd-manifests/images.config.openshift.io/ImageStreamImportMode.yaml


8. payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml ⚙️ Configuration changes +20/-2

Add pattern validation to payload manifest CRD

• Added pattern validation to payload manifest CRD for registry entry fields
• Updated field descriptions with validation requirements and format specifications
• Synchronized with main CRD manifest changes

payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Apr 6, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Omitted behavior undocumented lists 📘 Rule violation ⚙ Maintainability
Description
InsecureRegistries, BlockedRegistries, and AllowedRegistries are marked +optional and now
have item Pattern validation, but their comments do not document what happens when the fields are
omitted/defaulted. This violates the requirement to document optionality and omitted/default
behavior for API fields with validation markers.
Code

config/v1/types_image.go[R167-200]

	// insecureRegistries are registries which do not have a valid TLS certificates or only support HTTP connections.
+	// Each entry must be a valid registry scope in the format hostname[:port][/path],
+	// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
+	// The hostname must consist of valid DNS labels separated by dots, where each label
+	// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
+	// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
	// +optional
	// +listType=atomic
+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	InsecureRegistries []string `json:"insecureRegistries,omitempty"`
	// blockedRegistries cannot be used for image pull and push actions. All other registries are permitted.
+	// Each entry must be a valid registry scope in the format hostname[:port][/path],
+	// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
+	// The hostname must consist of valid DNS labels separated by dots, where each label
+	// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
+	// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
	//
	// Only one of BlockedRegistries or AllowedRegistries may be set.
	// +optional
	// +listType=atomic
+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	BlockedRegistries []string `json:"blockedRegistries,omitempty"`
	// allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied.
+	// Each entry must be a valid registry scope in the format hostname[:port][/path],
+	// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
+	// The hostname must consist of valid DNS labels separated by dots, where each label
+	// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
+	// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
	//
	// Only one of BlockedRegistries or AllowedRegistries may be set.
	// +optional
	// +listType=atomic
+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	AllowedRegistries []string `json:"allowedRegistries,omitempty"`
Evidence
PR Compliance ID 5 requires field comments to document optionality and omitted/default behavior for
fields with validation markers and/or +optional. The updated comment blocks for these +optional
fields add pattern constraints but still do not state the omitted/default behavior.

AGENTS.md
config/v1/types_image.go[167-200]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RegistrySources` optional list fields (`insecureRegistries`, `blockedRegistries`, `allowedRegistries`) have validation markers but their Go doc comments do not describe what happens when the field is omitted (default behavior).

## Issue Context
These fields are `+optional` and now include per-item `Pattern` validation, so the field documentation must also state omitted/default behavior in human-readable terms.

## Fix Focus Areas
- config/v1/types_image.go[167-200]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Duplicated registry regex patterns 🐞 Bug ⚙ Maintainability
Description
The same long registry-scope regex is duplicated in three separate kubebuilder annotations for
insecureRegistries, blockedRegistries, and allowedRegistries, making future updates error-prone and
risking inconsistent validation if one copy changes. A dedicated string type (as already used
elsewhere in config/v1) would centralize the pattern and keep the CRD/openapi outputs consistent.
Code

config/v1/types_image.go[R175-200]

+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	InsecureRegistries []string `json:"insecureRegistries,omitempty"`
	// blockedRegistries cannot be used for image pull and push actions. All other registries are permitted.
+	// Each entry must be a valid registry scope in the format hostname[:port][/path],
+	// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
+	// The hostname must consist of valid DNS labels separated by dots, where each label
+	// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
+	// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
	//
	// Only one of BlockedRegistries or AllowedRegistries may be set.
	// +optional
	// +listType=atomic
+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	BlockedRegistries []string `json:"blockedRegistries,omitempty"`
	// allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied.
+	// Each entry must be a valid registry scope in the format hostname[:port][/path],
+	// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
+	// The hostname must consist of valid DNS labels separated by dots, where each label
+	// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
+	// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
	//
	// Only one of BlockedRegistries or AllowedRegistries may be set.
	// +optional
	// +listType=atomic
+	// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
	AllowedRegistries []string `json:"allowedRegistries,omitempty"`
Evidence
RegistrySources repeats an identical +kubebuilder:validation:items:Pattern annotation on three
different fields, so any future regex fix must be made in three places. In contrast,
ImageDigestMirrorSet defines a dedicated string type (ImageMirror) with a Pattern annotation and
then uses that type in slices, demonstrating an existing repo pattern for avoiding this duplication.

config/v1/types_image.go[167-200]
config/v1/types_image_digest_mirror_set.go[85-87]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RegistrySources` repeats the same complex registry-scope regex three times via `+kubebuilder:validation:items:Pattern` on `InsecureRegistries`, `BlockedRegistries`, and `AllowedRegistries`. This duplication increases the chance of future divergence and inconsistent API validation.

## Issue Context
The repo already uses dedicated validated string types to avoid repeating regexes (e.g., `type ImageMirror string` with a `+kubebuilder:validation:Pattern=...` annotation).

## Fix Focus Areas
- config/v1/types_image.go[163-209]
- config/v1/types_image_digest_mirror_set.go[85-87]

## Suggested change
1. Introduce a new type, e.g.:
  - `// +kubebuilder:validation:Pattern=`<combined wildcard|host[:port][/path] regex>`
  - `type RegistryScope string`
2. Change the fields to:
  - `InsecureRegistries []RegistryScope`
  - `BlockedRegistries []RegistryScope`
  - `AllowedRegistries []RegistryScope`
3. Remove the three `items:Pattern` annotations.
4. Regenerate CRDs/OpenAPI (`make update`) and ensure the existing validation tests still pass.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 167 to 200
// insecureRegistries are registries which do not have a valid TLS certificates or only support HTTP connections.
// Each entry must be a valid registry scope in the format hostname[:port][/path],
// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
// The hostname must consist of valid DNS labels separated by dots, where each label
// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
// +optional
// +listType=atomic
// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
InsecureRegistries []string `json:"insecureRegistries,omitempty"`
// blockedRegistries cannot be used for image pull and push actions. All other registries are permitted.
// Each entry must be a valid registry scope in the format hostname[:port][/path],
// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
// The hostname must consist of valid DNS labels separated by dots, where each label
// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
//
// Only one of BlockedRegistries or AllowedRegistries may be set.
// +optional
// +listType=atomic
// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
BlockedRegistries []string `json:"blockedRegistries,omitempty"`
// allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied.
// Each entry must be a valid registry scope in the format hostname[:port][/path],
// optionally prefixed with "*." for wildcard subdomains (e.g., "*.example.com").
// The hostname must consist of valid DNS labels separated by dots, where each label
// contains only alphanumeric characters and hyphens and does not start or end with a hyphen.
// Entries must not include tags (e.g., ":latest") or digests (e.g., "@sha256:...").
//
// Only one of BlockedRegistries or AllowedRegistries may be set.
// +optional
// +listType=atomic
// +kubebuilder:validation:items:Pattern=`^\*(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+$|^((?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?)(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?$`
AllowedRegistries []string `json:"allowedRegistries,omitempty"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Omitted behavior undocumented lists 📘 Rule violation ⚙ Maintainability

InsecureRegistries, BlockedRegistries, and AllowedRegistries are marked +optional and now
have item Pattern validation, but their comments do not document what happens when the fields are
omitted/defaulted. This violates the requirement to document optionality and omitted/default
behavior for API fields with validation markers.
Agent Prompt
## Issue description
`RegistrySources` optional list fields (`insecureRegistries`, `blockedRegistries`, `allowedRegistries`) have validation markers but their Go doc comments do not describe what happens when the field is omitted (default behavior).

## Issue Context
These fields are `+optional` and now include per-item `Pattern` validation, so the field documentation must also state omitted/default behavior in human-readable terms.

## Fix Focus Areas
- config/v1/types_image.go[167-200]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 6, 2026

@reedcort: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/severity-moderate Referenced Jira bug's severity is moderate for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants