From e33c244882ccd4dbdb50a7c8a13b2e076b724bd0 Mon Sep 17 00:00:00 2001 From: zhangbingbing Date: Wed, 11 Nov 2026 15:53:43 +0800 Subject: [PATCH 1/2] fix(kubernetes): disable privilege escalation for unprivileged workloads Signed-off-by: zhangbingbing --- gpustack_runtime/deployer/kubernetes.py | 13 +++++++ .../deployer/test_privilege_escalation.py | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/gpustack_runtime/deployer/test_privilege_escalation.py diff --git a/gpustack_runtime/deployer/kubernetes.py b/gpustack_runtime/deployer/kubernetes.py index 69128c3..d55f40d 100644 --- a/gpustack_runtime/deployer/kubernetes.py +++ b/gpustack_runtime/deployer/kubernetes.py @@ -692,6 +692,17 @@ def _resolve_runtime_class_name( pod.spec.runtime_class_name = runtime_class_name +def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None: + security = container.security_context or kubernetes.client.V1SecurityContext() + capabilities = security.capabilities + # Kubernetes cannot disable escalation for privileged containers or CAP_SYS_ADMIN. + security.allow_privilege_escalation = bool( + security.privileged + or (capabilities and "SYS_ADMIN" in (capabilities.add or [])), + ) + container.security_context = security + + def _resolve_privileged(container: Container, kdp: bool) -> bool: """ Resolve whether a container runs privileged. @@ -1765,6 +1776,8 @@ def _create_pod( ), ) + _set_privilege_escalation(container) + # Append the container. if c.profile == ContainerProfileEnum.INIT: pod.spec.init_containers = pod.spec.init_containers or [] diff --git a/tests/gpustack_runtime/deployer/test_privilege_escalation.py b/tests/gpustack_runtime/deployer/test_privilege_escalation.py new file mode 100644 index 0000000..d55e5f8 --- /dev/null +++ b/tests/gpustack_runtime/deployer/test_privilege_escalation.py @@ -0,0 +1,36 @@ +from __future__ import annotations as __future_annotations__ + +import kubernetes +import pytest + +from gpustack_runtime.deployer.kubernetes import _set_privilege_escalation + + +@pytest.mark.parametrize( + "security, expected", + [ + (None, False), + (kubernetes.client.V1SecurityContext(privileged=False), False), + (kubernetes.client.V1SecurityContext(privileged=True), True), + ( + kubernetes.client.V1SecurityContext( + capabilities=kubernetes.client.V1Capabilities(add=["SYS_ADMIN"]), + ), + True, + ), + ( + kubernetes.client.V1SecurityContext( + capabilities=kubernetes.client.V1Capabilities(add=["IPC_LOCK"]), + run_as_user=1000, + ), + False, + ), + ], +) +def test_privilege_escalation_matches_final_security_context(security, expected): + container = kubernetes.client.V1Container(name="model", security_context=security) + _set_privilege_escalation(container) + assert container.security_context.allow_privilege_escalation is expected + if security is not None: + assert container.security_context is security + assert container.security_context.run_as_user == security.run_as_user From 2f9112e6f23f4ab350e71e98a9aaf14154746493 Mon Sep 17 00:00:00 2001 From: zbb88888 Date: Wed, 11 Nov 2026 17:34:02 +0800 Subject: [PATCH 2/2] fix(kubernetes): normalize escalation-sensitive capabilities Signed-off-by: zbb88888 --- gpustack_runtime/deployer/kubernetes.py | 8 ++++++-- .../deployer/test_privilege_escalation.py | 12 ++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/gpustack_runtime/deployer/kubernetes.py b/gpustack_runtime/deployer/kubernetes.py index d55f40d..bb819d9 100644 --- a/gpustack_runtime/deployer/kubernetes.py +++ b/gpustack_runtime/deployer/kubernetes.py @@ -695,10 +695,14 @@ def _resolve_runtime_class_name( def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None: security = container.security_context or kubernetes.client.V1SecurityContext() capabilities = security.capabilities - # Kubernetes cannot disable escalation for privileged containers or CAP_SYS_ADMIN. + added_capabilities = { + capability.upper().removeprefix("CAP_") + for capability in (capabilities.add or []) + } if capabilities else set() + # Kubernetes cannot disable escalation for privileged containers, SYS_ADMIN, or ALL. security.allow_privilege_escalation = bool( security.privileged - or (capabilities and "SYS_ADMIN" in (capabilities.add or [])), + or added_capabilities.intersection({"SYS_ADMIN", "ALL"}), ) container.security_context = security diff --git a/tests/gpustack_runtime/deployer/test_privilege_escalation.py b/tests/gpustack_runtime/deployer/test_privilege_escalation.py index d55e5f8..c4d0005 100644 --- a/tests/gpustack_runtime/deployer/test_privilege_escalation.py +++ b/tests/gpustack_runtime/deployer/test_privilege_escalation.py @@ -12,12 +12,12 @@ (None, False), (kubernetes.client.V1SecurityContext(privileged=False), False), (kubernetes.client.V1SecurityContext(privileged=True), True), - ( - kubernetes.client.V1SecurityContext( - capabilities=kubernetes.client.V1Capabilities(add=["SYS_ADMIN"]), - ), - True, - ), + *[ + (kubernetes.client.V1SecurityContext( + capabilities=kubernetes.client.V1Capabilities(add=[value]), + ), True) + for value in ["SYS_ADMIN", "CAP_SYS_ADMIN", "sys_admin", "cap_sys_admin", "ALL", "CAP_ALL"] + ], ( kubernetes.client.V1SecurityContext( capabilities=kubernetes.client.V1Capabilities(add=["IPC_LOCK"]),