VYPR
Medium severity6.7GHSA Advisory· Published Aug 27, 2025· Updated Apr 15, 2026

CVE-2025-5187

CVE-2025-5187

Description

A vulnerability exists in the NodeRestriction admission controller in Kubernetes clusters where node users can delete their corresponding node object by patching themselves with an OwnerReference to a cluster-scoped resource. If the OwnerReference resource does not exist or is subsequently deleted, the given node object will be deleted via garbage collection.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
k8s.io/kubernetesGo
< 1.31.121.31.12
k8s.io/kubernetesGo
>= 1.32.0-alpha.0, < 1.32.81.32.8
k8s.io/kubernetesGo
>= 1.33.0-alpha.0, < 1.33.41.33.4

Affected products

1

Patches

1
a2d98cac56a0

Merge pull request #133470 from natherz97/node-deletion-release-1.31

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 11, 2025via ghsa
2 files changed · +35 6
  • plugin/pkg/admission/noderestriction/admission.go+5 0 modified
    @@ -489,6 +489,11 @@ func (p *Plugin) admitNode(nodeName string, a admission.Attributes) error {
     			return admission.NewForbidden(a, fmt.Errorf("node %q is not allowed to modify taints", nodeName))
     		}
     
    +		// Don't allow a node to update its own ownerReferences.
    +		if !apiequality.Semantic.DeepEqual(node.OwnerReferences, oldNode.OwnerReferences) {
    +			return admission.NewForbidden(a, fmt.Errorf("node %q is not allowed to modify ownerReferences", nodeName))
    +		}
    +
     		// Don't allow a node to update labels outside the allowed set.
     		// This would allow a node to add or modify its labels in a way that would let it steer privileged workloads to itself.
     		modifiedLabels := getModifiedLabels(node.Labels, oldNode.Labels)
    
  • plugin/pkg/admission/noderestriction/admission_test.go+30 6 modified
    @@ -247,10 +247,14 @@ func (a *admitTestCase) run(t *testing.T) {
     
     func Test_nodePlugin_Admit(t *testing.T) {
     	var (
    -		mynode = &user.DefaultInfo{Name: "system:node:mynode", Groups: []string{"system:nodes"}}
    -		bob    = &user.DefaultInfo{Name: "bob"}
    +		trueRef = true
    +		mynode  = &user.DefaultInfo{Name: "system:node:mynode", Groups: []string{"system:nodes"}}
    +		bob     = &user.DefaultInfo{Name: "bob"}
    +
    +		mynodeObjMeta          = metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid"}
    +		mynodeObjMetaOwnerRefA = metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid", OwnerReferences: []metav1.OwnerReference{{Name: "fooerA", Controller: &trueRef}}}
    +		mynodeObjMetaOwnerRefB = metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid", OwnerReferences: []metav1.OwnerReference{{Name: "fooerB", Controller: &trueRef}}}
     
    -		mynodeObjMeta    = metav1.ObjectMeta{Name: "mynode", UID: "mynode-uid"}
     		mynodeObj        = &api.Node{ObjectMeta: mynodeObjMeta}
     		mynodeObjConfigA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
     			ConfigMap: &api.ConfigMapNodeConfigSource{
    @@ -267,9 +271,11 @@ func Test_nodePlugin_Admit(t *testing.T) {
     				KubeletConfigKey: "kubelet",
     			}}}}
     
    -		mynodeObjTaintA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "A"}}}}
    -		mynodeObjTaintB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "B"}}}}
    -		othernodeObj    = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}}
    +		mynodeObjTaintA    = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "A"}}}}
    +		mynodeObjTaintB    = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{Taints: []api.Taint{{Key: "mykey", Value: "B"}}}}
    +		mynodeObjOwnerRefA = &api.Node{ObjectMeta: mynodeObjMetaOwnerRefA}
    +		mynodeObjOwnerRefB = &api.Node{ObjectMeta: mynodeObjMetaOwnerRefB}
    +		othernodeObj       = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}}
     
     		coremymirrorpod, v1mymirrorpod           = makeTestPod("ns", "mymirrorpod", "mynode", true)
     		coreothermirrorpod, v1othermirrorpod     = makeTestPod("ns", "othermirrorpod", "othernode", true)
    @@ -1052,6 +1058,24 @@ func Test_nodePlugin_Admit(t *testing.T) {
     			attributes: admission.NewAttributesRecord(setForbiddenUpdateLabels(mynodeObj, "new"), setForbiddenUpdateLabels(mynodeObj, "old"), nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
     			err:        `is not allowed to modify labels: foo.node-restriction.kubernetes.io/foo, node-restriction.kubernetes.io/foo, other.k8s.io/foo, other.kubernetes.io/foo`,
     		},
    +		{
    +			name:       "forbid update of my node: add owner reference",
    +			podsGetter: existingPods,
    +			attributes: admission.NewAttributesRecord(mynodeObjOwnerRefA, mynodeObj, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
    +			err:        "node \"mynode\" is not allowed to modify ownerReferences",
    +		},
    +		{
    +			name:       "forbid update of my node: remove owner reference",
    +			podsGetter: existingPods,
    +			attributes: admission.NewAttributesRecord(mynodeObj, mynodeObjOwnerRefA, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
    +			err:        "node \"mynode\" is not allowed to modify ownerReferences",
    +		},
    +		{
    +			name:       "forbid update of my node: change owner reference",
    +			podsGetter: existingPods,
    +			attributes: admission.NewAttributesRecord(mynodeObjOwnerRefA, mynodeObjOwnerRefB, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Update, &metav1.UpdateOptions{}, false, mynode),
    +			err:        "node \"mynode\" is not allowed to modify ownerReferences",
    +		},
     
     		// Other node object
     		{
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.