helm/reana/templates/roles.yaml binds the runtime ServiceAccount to the same <prefix>-deployment-manager ClusterRole as the infrastructure ServiceAccount:
- kind: ServiceAccount
name: {{ include "reana.prefixed_runtime_svaccount_name" . }}
namespace: {{ .Values.namespace_runtime }}
That ClusterRole carries cluster-wide get/list/create/update/watch on nodes, secrets, deployments, services, ingresses and * on storageclasses — broader than what any pod in the runtime namespace actually needs.
In practice the blast radius is narrow: user-step job pods (reana-job-controller/kubernetes_job_manager.py:204) and interactive sessions (reana-workflow-controller/k8s.py:92) set automountServiceAccountToken: False, so they never carry the SA token. Only the trusted run-batch orchestrator pod uses the runtime SA, and its workload is REANA-controlled code, not arbitrary user code. So this is not a "compromised user workload escapes the namespace" issue, just a least-privilege one.
Suggested fix is to split the ClusterRole into:
- a true ClusterRole for genuinely cluster-scoped operations (nodes/metrics, cluster-wide CR watches, storageclasses);
- a Role bound per namespace for pod/service/configmap CRUD.
Bind the runtime SA only to the per-namespace Role plus the minimal ClusterRole subset it actually needs. The wide ClusterRole is also what currently makes Dask + Traefik plumbing "just work" cross-namespace, so any narrowing must keep those flows green.
Related to #955
helm/reana/templates/roles.yamlbinds the runtime ServiceAccount to the same<prefix>-deployment-managerClusterRole as the infrastructure ServiceAccount:That ClusterRole carries cluster-wide
get/list/create/update/watchon nodes, secrets, deployments, services, ingresses and*onstorageclasses— broader than what any pod in the runtime namespace actually needs.In practice the blast radius is narrow: user-step job pods (
reana-job-controller/kubernetes_job_manager.py:204) and interactive sessions (reana-workflow-controller/k8s.py:92) setautomountServiceAccountToken: False, so they never carry the SA token. Only the trustedrun-batchorchestrator pod uses the runtime SA, and its workload is REANA-controlled code, not arbitrary user code. So this is not a "compromised user workload escapes the namespace" issue, just a least-privilege one.Suggested fix is to split the ClusterRole into:
Bind the runtime SA only to the per-namespace Role plus the minimal ClusterRole subset it actually needs. The wide ClusterRole is also what currently makes Dask + Traefik plumbing "just work" cross-namespace, so any narrowing must keep those flows green.
Related to #955