Skip to content

Add denylist for system namespaces in targetNamespace validation#3507

Open
mvanhorn wants to merge 2 commits into
tektoncd:mainfrom
mvanhorn:feat/3248-deny-system-namespaces
Open

Add denylist for system namespaces in targetNamespace validation#3507
mvanhorn wants to merge 2 commits into
tektoncd:mainfrom
mvanhorn:feat/3248-deny-system-namespaces

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Changes

CommonSpec.validate() previously accepted any non-empty targetNamespace on Kubernetes, so a component could be told to install into a well-known system namespace such as kube-system, kube-public, kube-node-lease, or default. On OpenShift only openshift-operators was blocked.

This adds a defense-in-depth denylist that rejects those four reserved system namespaces on both Kubernetes and OpenShift, while preserving the existing OpenShift-only openshift-operators rejection. Because validate() is the shared method called by every component validator, the denylist applies across components with no caller changes.

While wiring this up I found that TektonResult bypassed the shared validation entirely: TektonResult.Validate calls TektonResultSpec.validate, which never invoked the embedded CommonSpec.validate. This change also calls the common validation from TektonResultSpec.validate so the denylist (and the pre-existing empty-field check) is enforced consistently for TektonResult too.

Tests cover the happy path, each denied namespace on both platforms, the preserved openshift-operators rejection, the empty-namespace case, and the TektonResult path.

Fixes #3248

Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

See the contribution guide for more details.

Release Notes

Reject well-known system namespaces (kube-system, kube-public, kube-node-lease, default) in `targetNamespace` validation across Tekton components.

mvanhorn added 2 commits June 17, 2026 04:28
CommonSpec.validate() previously accepted any non-empty targetNamespace on
Kubernetes, allowing components to be installed into well-known system
namespaces such as kube-system, kube-public, kube-node-lease, or default.

Add a defense-in-depth denylist that rejects those four reserved namespaces
on both Kubernetes and OpenShift, while preserving the existing
OpenShift-only openshift-operators rejection. Because validate() is the
shared method called by every component validator, the denylist applies to
all of them with no caller changes.

Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
TektonResult.Validate calls TektonResultSpec.validate, which did not call
the embedded CommonSpec.validate, so the new system-namespace denylist (and
the pre-existing empty-field check) was bypassed for TektonResult. Wire the
common validation into TektonResultSpec.validate so the denylist is enforced
consistently across every CommonSpec-backed component.

Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
@tekton-robot tekton-robot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Jun 17, 2026
@tekton-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please assign pratap0007 after the PR has been reviewed.
You can assign the PR to them by writing /assign @pratap0007 in a comment when ready.

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

@tekton-robot tekton-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jun 17, 2026

func (ta *CommonSpec) validate(path string) *apis.FieldError {
var errs *apis.FieldError
targetNamespace := ta.GetTargetNamespace()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is cleaner than calling GetTargetNamespace() multile time

},
Spec: TektonResultSpec{
CommonSpec: CommonSpec{
TargetNamespace: "kube-system",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this skips validation kube-public, kube-node-lease, default, and the OpenShift openshift-operators case, without any failing test at the TektonResult level.

@jkhelil

jkhelil commented Jun 18, 2026

Copy link
Copy Markdown
Member

@mvanhorn thank you for you contribution, would you add the validation to pkg/apis/operator/v1alpha1/tektonscheduler_validation.go:27–41
TektonScheduler embeds CommonSpec but its Validate() only calls ts.Spec.MultiClusterConfig.validate() so it never calls CommonSpec.validate().

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds defense-in-depth validation to prevent installing Tekton components into well-known Kubernetes system namespaces via spec.targetNamespace, and ensures TektonResult applies the shared CommonSpec validation path so the denylist (and existing empty check) are enforced consistently.

Changes:

  • Add a reserved system namespace denylist (kube-system, kube-public, kube-node-lease, default) to CommonSpec.validate() across platforms, while preserving the OpenShift-only openshift-operators restriction.
  • Ensure TektonResultSpec.validate() invokes the embedded CommonSpec.validate() so TektonResult no longer bypasses shared validation.
  • Extend unit tests to cover denylisted namespaces and the TektonResult validation path.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
pkg/apis/operator/v1alpha1/common_validation.go Adds reserved namespace denylist enforcement to shared CommonSpec validation.
pkg/apis/operator/v1alpha1/common_validation_test.go Updates CommonSpec validation tests for reserved namespace denylist (Kubernetes + one OpenShift case).
pkg/apis/operator/v1alpha1/tektonresult_validation.go Ensures TektonResultSpec runs shared CommonSpec validation.
pkg/apis/operator/v1alpha1/tektonresult_validation_test.go Adds a test covering TektonResult’s denylisted targetNamespace validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 41 to 44
{name: "ns-openshift-operators", targetNamespace: "openshift-operators", err: "", isOpenshift: false},
{name: "openshift-ns-default", targetNamespace: "default", err: "invalid value: default: spec.targetNamespace\n'default' is a reserved system namespace and is not allowed", isOpenshift: true},
{name: "openshift-ns-openshift-operators", targetNamespace: "openshift-operators", err: "invalid value: openshift-operators: spec.targetNamespace\n'openshift-operators' namespace is not allowed", isOpenshift: true},
{name: "openshift-ns-openshift-pipelines", targetNamespace: "openshift-pipelines", err: "", isOpenshift: true},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add denylist for system namespaces in targetNamespace validation

4 participants