update certificatesigningrequests/approval
Approval alone does not write a certificate.
It only marks a pending CertificateSigningRequest approved, after which a signer may issue one.
It is rejected on its own without approve on signers for the request's exact signerName.
Combined with create on certificatesigningrequests for the kube-apiserver-client signer, it becomes privilege escalation.
T0 with following verbs:
Authenticate to the API server as any user, in any group the signer permits
scoped to signerName kubernetes.io/kube-apiserver-client
A self-submitted request is approved and the built-in controller issues a trusted certificate, so the caller never needs a CA key.
- API Group
- certificates.k8s.io
- Scope
- cluster
- Audit Level
- RequestResponse
Escalation Paths
List the User subjects already bound to cluster-admin via kubectl get clusterrolebinding.
The name is distribution specific: cluster-admin on kubeadm, clusterAdmin and clusterUser on AKS.
Create a CSR using a CN matching one of those usernames and request the kubernetes.io/kube-apiserver-client signer.
Approve the CSR.
This requires both update on certificatesigningrequests/approval and approve on signers for that exact signerName.
The built-in signing controller issues a real, CA-signed certificate automatically.
No CA key or extra access is needed from the caller.
The cert authenticates as the matched username, inheriting all its RBAC permissions.
It works until expiry.
Individual revocation requires CA rotation.
Additional rights needed:
· scoped to signerName kubernetes.io/kube-apiserver-client
· no CA key needed
Note:
The CSR API remains dangerous for kube-apiserver client certificates, but the direct built-in system:masters request is rejected by signer policy.
Custom signers or certificates for other bound high-privilege identities can still be escalation paths.
The submission guard rejects only the literal group system:masters, so an O=system:nodes request is accepted
Request a certificate with O=system:nodes and CN=system:node: followed by the name of a real node
Approving it returns a CA-signed client certificate, issued in seconds and valid for years
The Node authorizer then grants the Secrets, ConfigMaps and PVCs referenced by pods scheduled on that node
Objects no pod on that node references are refused as having no relationship to it, and bulk list is refused, so the reach is that node workload set
A TokenRequest bound to a pod on that node mints that pod ServiceAccount token, including one carrying a cloud identity audience
There is no revocation for client certificates, so deleting the request leaves an issued certificate valid until it expires
On a single node cluster every pod runs on that node, so the node workload set is the whole cluster and the practical reach approaches full compromise
Additional rights needed:
· scoped to signerName kubernetes.io/kube-apiserver-client
· no CA key needed
Note:
Not patched and not a defect: only system:masters is guarded at submission.
Remediation is preventive, since an issued certificate cannot be revoked and only rotating the CA invalidates it.

