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 CEL XValidation 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
  • Returns a user-friendly error message instead of dumping the raw regex
  • Adds MinLength=1 to reject empty string entries (which break node bootstrap on HCP)
  • Adds MaxItems=128 and MaxLength=512 per item for CEL cost estimation (validated against fleet telemetry: max entry length 245, max item count 32)
  • 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 (tagged entries, empty strings)
  • onCreate tests verify invalid tagged/digest entries and empty strings 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

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added per-item and per-list validation to RegistrySources fields insecureRegistries, blockedRegistries, and allowedRegistries: each array now has maxItems: 128 (kubebuilder/CRD), each item has minLength: 1 and maxLength: 512, and an x-kubernetes-validations / kubebuilder XValidation enforces a registry-scope pattern hostname[:port][/path] or *.hostname while rejecting image tags and digests. Updated Go field comments and Swagger docs to document these constraints. Extended CRD tests to cover create and update acceptance/rejection cases, including on-update scenarios and atomic list revalidation.

🚥 Pre-merge checks | ✅ 9 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Microshift Test Compatibility ❓ Inconclusive Cannot examine pull request without access to repository structure, git diff, or test files to analyze. Provide access to the actual repository files, git diff output, or test file contents to verify if new Ginkgo e2e tests using unavailable MicroShift APIs are being added.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding pattern validation for registry entries in the image config, which is the core purpose of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Stable And Deterministic Test Names ✅ Passed All 25 test names are stable and deterministic with no dynamic identifiers, timestamps, UUIDs, or node/namespace names. Test names use clear, static descriptive strings that indicate what each test validates without containing any dynamic information.
Test Structure And Quality ✅ Passed PR adds YAML-based CRD validation tests, not Ginkgo Go tests. Custom check requirements for Ginkgo patterns (It blocks, BeforeEach/AfterEach, Eventually/Consistently) do not apply.
Single Node Openshift (Sno) Test Compatibility ✅ Passed This pull request does not introduce any Ginkgo e2e tests. The changes consist of updates to Go API type definitions, generated documentation, CRD schema validation rules, and YAML-based CRD validation test configuration files. The repository is the OpenShift API definitions repository which defines API schemas and types, not end-to-end test suites. The YAML test files are declarative CRD schema validation test configurations, not Ginkgo tests. Consequently, there are no multi-node or HA cluster assumptions to evaluate.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only API schema validation for Image configuration registry fields with CEL rules and kubebuilder constraints, no operator code changes.
Ote Binary Stdout Contract ✅ Passed The OTE Binary Stdout Contract check is not applicable; modified files contain only Go type definitions, auto-generated documentation, Kubernetes CRD manifests, and test configuration YAML with no executable code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR does not add any Ginkgo e2e tests; changes consist of API type definitions and CRD schema validation updates only.
Description check ✅ Passed The PR description accurately describes the changeset: adding per-item CEL XValidation to registry fields with appropriate constraints, rejecting invalid tags/digests, and detailed test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

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

Comment thread config/v1/types_image.go Outdated
@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

@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 thread config/v1/types_image.go
@joshbranham
Copy link
Copy Markdown

/jira refresh

@openshift-ci-robot
Copy link
Copy Markdown

@joshbranham: This pull request references Jira Issue OCPBUGS-43353, which is valid.

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 POST, 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:

/jira refresh

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.

Comment thread config/v1/types_image.go Outdated
// 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]+)+)?)+)?$`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We generally discourage the usage of this marker because it spits the entire regular expression string out to the end user as opposed to a helpful error message.

Instead, we prefer the use of a the +kubebuilder:validation:items:XValidation marker where the rule parameter enforces the regular expression and the message parameter returns a user-friendly error message that outlines the constraints - much like the changes you've made to the field description do.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This generally also means needing to enforce a maximum length on the input to prevent excessive cost estimations for evaluating the CEL expressions

@reedcort
Copy link
Copy Markdown
Author

reedcort commented Apr 9, 2026

@everettraven Updated to use +kubebuilder:validation:items:XValidation with a user-friendly error message instead of Pattern, and added MaxItems=512 and MaxLength=512 per item for CEL cost estimation.

Telemetry validation for limits

Queried CCX/Insights archive to confirm the limits won't break existing clusters:

Max individual entry length (245 chars):

SELECT
    cluster_id,
    entry,
    length(entry) as entry_length
FROM ccx_sensitive.raw_io_archives
CROSS JOIN UNNEST(
    concat(
        COALESCE(cast(json_extract(content, '$.spec.registrySources.blockedRegistries') as array(varchar)), ARRAY[]),
        COALESCE(cast(json_extract(content, '$.spec.registrySources.allowedRegistries') as array(varchar)), ARRAY[]),
        COALESCE(cast(json_extract(content, '$.spec.registrySources.insecureRegistries') as array(varchar)), ARRAY[])
    )
) AS t(entry)
WHERE file_path = 'config/image.json'
    AND content LIKE '%registrySources%'
ORDER BY entry_length DESC
LIMIT 20;

Max item count per list (32 entries):

SELECT
    cluster_id,
    json_array_length(json_extract(content, '$.spec.registrySources.blockedRegistries')) as blocked_count,
    json_array_length(json_extract(content, '$.spec.registrySources.allowedRegistries')) as allowed_count,
    json_array_length(json_extract(content, '$.spec.registrySources.insecureRegistries')) as insecure_count
FROM ccx_sensitive.raw_io_archives
WHERE file_path = 'config/image.json'
    AND content LIKE '%registrySources%'
ORDER BY blocked_count DESC, allowed_count DESC, insecure_count DESC
LIMIT 20;
Limit Max in fleet Set to
Entry length 245 chars 512 (2x headroom)
Items per list 32 entries 512 (16x headroom)

@openshift-ci-robot
Copy link
Copy Markdown

@reedcort: This pull request references Jira Issue OCPBUGS-43353, which is valid.

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 POST, which is one of the valid states (NEW, ASSIGNED, POST)

No GitHub users were found matching the public email listed for the QA contact in Jira (xiuwang@redhat.com), skipping review request.

Details

In response to this:

Summary

  • Add per-item CEL XValidation 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
  • Returns a user-friendly error message instead of dumping the raw regex
  • Adds MaxItems=512 and MaxLength=512 per item for CEL cost estimation (validated against fleet telemetry: max entry length 245, max item count 32)
  • 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

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.

Comment thread config/v1/types_image.go
Comment thread config/v1/types_image.go Outdated
Copy link
Copy Markdown
Contributor

@everettraven everettraven left a comment

Choose a reason for hiding this comment

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

Aside from a small comment and a question, this LGTM overall.

Thanks for doing an analysis with telemetry. A 16x overhead on the max items seems a bit excessive, I wonder if using something like 128 would be enough (4x increase)?

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.

🧹 Nitpick comments (1)
config/v1/tests/images.config.openshift.io/AAA_ungated.yaml (1)

39-62: Use canonical digest strings in negative tests to harden regression detection

The @sha256:abc123 samples are not valid digest syntax, so failures could be attributed to malformed digest format rather than the intended “no digests allowed” rule. Use a canonical 64-hex digest to make this assertion more precise.

Proposed test input refinement
-            blockedRegistries: ["registry.io/myrepo@sha256:abc123"]
+            blockedRegistries: ["registry.io/myrepo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
...
-            allowedRegistries: ["registry.io/myrepo@sha256:abc123"]
+            allowedRegistries: ["registry.io/myrepo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
...
-            insecureRegistries: ["registry.io/myrepo@sha256:abc123"]
+            insecureRegistries: ["registry.io/myrepo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/v1/tests/images.config.openshift.io/AAA_ungated.yaml` around lines 39
- 62, The negative tests use an invalid digest fragment ("@sha256:abc123");
update the three test entries named "Should not allow creating an Image..." to
use a canonical valid digest string instead of "sha256:abc123" so the failure is
about digests being disallowed and not malformed syntax; specifically replace
the registry entries in spec.registrySources.blockedRegistries[0],
spec.registrySources.allowedRegistries[0], and
spec.registrySources.insecureRegistries[0] with a proper sha256 digest
consisting of "sha256:" followed by 64 lowercase hex characters.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@config/v1/tests/images.config.openshift.io/AAA_ungated.yaml`:
- Around line 39-62: The negative tests use an invalid digest fragment
("@sha256:abc123"); update the three test entries named "Should not allow
creating an Image..." to use a canonical valid digest string instead of
"sha256:abc123" so the failure is about digests being disallowed and not
malformed syntax; specifically replace the registry entries in
spec.registrySources.blockedRegistries[0],
spec.registrySources.allowedRegistries[0], and
spec.registrySources.insecureRegistries[0] with a proper sha256 digest
consisting of "sha256:" followed by 64 lowercase hex characters.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: 9ca7589a-0200-49f5-9de7-08b52814f737

📥 Commits

Reviewing files that changed from the base of the PR and between 595d57c and c554ae4.

⛔ 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

@reedcort
Copy link
Copy Markdown
Author

reedcort commented Apr 15, 2026

Aside from a small comment and a question, this LGTM overall.

Thanks for doing an analysis with telemetry. A 16x overhead on the max items seems a bit excessive, I wonder if using something like 128 would be enough (4x increase)?

128 works for me. If no one disagrees I can update MaxItems to 128.

Adds CEL XValidation, MinLength, MaxLength, and MaxItems constraints
to insecureRegistries, blockedRegistries, and allowedRegistries fields
in RegistrySources to reject invalid entries (e.g., tagged or digest
references) that can cause container runtime failures.

Includes ratcheting tests to ensure clusters with pre-existing invalid
entries can still update other fields without being blocked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci openshift-ci bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Apr 15, 2026
@openshift-ci-robot openshift-ci-robot added jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. and removed jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Apr 15, 2026
@openshift-ci-robot
Copy link
Copy Markdown

@reedcort: This pull request references Jira Issue OCPBUGS-43353, which is invalid:

  • expected the bug to target either version "5.0." or "openshift-5.0.", but it targets "4.22.0" instead

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

Details

In response to this:

Summary

  • Add per-item CEL XValidation 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
  • Returns a user-friendly error message instead of dumping the raw regex
  • Adds MinLength=1 to reject empty string entries (which break node bootstrap on HCP)
  • Adds MaxItems=128 and MaxLength=512 per item for CEL cost estimation (validated against fleet telemetry: max entry length 245, max item count 32)
  • 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 (tagged entries, empty strings)
  • onCreate tests verify invalid tagged/digest entries and empty strings are rejected
  • Valid entry tests cover hostname, hostname/path, wildcard, hostname:port/path

🤖 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.

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

🧹 Nitpick comments (1)
config/v1/tests/images.config.openshift.io/AAA_ungated.yaml (1)

15-86: Please assert the friendly CEL message in at least one negative case.

These cases only check the field path, so they prove rejection but not the main UX requirement behind switching to items:XValidation: hiding the raw regex. Pin one representative failure to the custom message substring so that regression is covered.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/v1/tests/images.config.openshift.io/AAA_ungated.yaml` around lines 15
- 86, Update one representative negative test to also assert the user-friendly
CEL message substring (not just the field path). For example, in the test named
"Should not allow creating an Image with a tagged registry entry in
blockedRegistries" (the case that sets spec.registrySources.blockedRegistries:
["registry.io/myrepo:latest"]), add an assertion field such as
expectedMessageContains: "must not contain a tag or digest" (or the actual
CEL-friendly substring emitted by the XValidation), so the test checks both the
error field path ("spec.registrySources.blockedRegistries[0]") and that the
human-facing message hides the raw regex; keep the rest of the cases unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@config/v1/tests/images.config.openshift.io/AAA_ungated.yaml`:
- Around line 15-86: Update one representative negative test to also assert the
user-friendly CEL message substring (not just the field path). For example, in
the test named "Should not allow creating an Image with a tagged registry entry
in blockedRegistries" (the case that sets
spec.registrySources.blockedRegistries: ["registry.io/myrepo:latest"]), add an
assertion field such as expectedMessageContains: "must not contain a tag or
digest" (or the actual CEL-friendly substring emitted by the XValidation), so
the test checks both the error field path
("spec.registrySources.blockedRegistries[0]") and that the human-facing message
hides the raw regex; keep the rest of the cases unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f887ede-9d04-401f-a6f3-2a2bd4694a6b

📥 Commits

Reviewing files that changed from the base of the PR and between c554ae4 and 9754d2d.

⛔ Files ignored due to path filters (5)
  • 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/**
  • config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/zz_generated*
  • openapi/generated_openapi/zz_generated.openapi.go is excluded by !openapi/**, !**/zz_generated*
📒 Files selected for processing (3)
  • config/v1/tests/images.config.openshift.io/AAA_ungated.yaml
  • config/v1/types_image.go
  • payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • payload-manifests/crds/0000_10_config-operator_01_images.crd.yaml

Comment thread config/v1/types_image.go
Comment on lines +168 to +179
// 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 be empty, must not include tags (e.g., ":latest") or digests (e.g., "@sha256:..."),
// and must be at most 512 characters in length. The list may contain at most 128 entries.
// +optional
// +listType=atomic
// +kubebuilder:validation:MaxItems=128
// +kubebuilder:validation:items:MinLength=1
// +kubebuilder:validation:items:MaxLength=512
// +kubebuilder:validation:items:XValidation:rule="self.matches('^\\\\*(?:\\\\.(?:[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]+)+)?)+)?$')",message="each registry must be a valid hostname[:port][/path] or wildcard *.hostname format without tags or digests"
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 15, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Wildcard entries currently reject documented :port and /path scopes.

The regex splits wildcard hosts into a separate ^\\*...$ branch, so *.example.com/ns and *.example.com:5000/ns fail validation even though the updated godoc says the format is hostname[:port][/path] with an optional *. prefix. Please fold the wildcard prefix into the main hostname alternative, or narrow the docs/message if wildcarded repo scopes are intentionally unsupported.

Also applies to: 182-195, 198-211

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This seems like a good find, although I will note that I haven't personally verified the regex myself.

@reedcort do we intend for something like the examples above to be valid wildcards or only something like *.example.com?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 15, 2026

@reedcort: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/verify-crdify 9754d2d link true /test verify-crdify

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.

Copy link
Copy Markdown
Contributor

@everettraven everettraven left a comment

Choose a reason for hiding this comment

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

Aside from the comment from coderabbit related to the wildcard regular expression seeming to be a reasonable thing to look into, this LGTM

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

Labels

jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. 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. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants