CVE-2026-53999: Radius Cross-Tenant Deletion DoS | Miggo
Technical Details
Package Name
Ecosystem
Vulnerable Versions
First Patched Version
github.com/radius-project/radius
go
< 0.58.0
0.58.0
Vulnerability Intelligence
Miggo AI
Root Cause Analysis
The vulnerability exists in the Radius Kubernetes controller and allows for a cross-tenant resource deletion, following the 'Confused Deputy' pattern. The root cause is improper input validation of user-controllable annotations on Kubernetes Deployment objects.
The analysis of the security advisory and the associated patch (PR #11967) reveals the attack path. An attacker can modify the radapp.io/status annotation on a Deployment they control. The reconciler.readAnnotations function in pkg/controller/reconciler/annotations.go would then read this annotation and deserialize the JSON content without validating it. The attacker can set the container field in the JSON to the full resource ID of a container in a different tenant.
Subsequently, during the reconciliation process, specifically in the deletion phase handled by reconciler.DeploymentReconciler.startDeleteOperationIfNeeded in pkg/controller/reconciler/deployment_reconciler.go, the controller uses this untrusted container ID to perform a deletion. Because the controller operates with high privileges, it can delete resources across different tenants without proper authorization checks, leading to a denial of service for the victim tenant.
The patch addresses this by introducing two main fixes:
In annotations.go, it adds validation (validateDeploymentStatus) to ensure the data within the radapp.io/status annotation is consistent and well-formed.
More critically, in deployment_reconciler.go, it adds an ownership check within startDeleteOperationIfNeeded. Before deleting a container, the controller now fetches the container's metadata and verifies that it has a resource reference back to the specific deployment being reconciled. If the ownership does not match, the deletion is aborted, preventing the cross-tenant attack.
Vulnerable functions
reconciler.readAnnotations
pkg/controller/reconciler/annotations.go
This function is the source of the vulnerability. It reads and deserializes the user-controlled `radapp.io/status` annotation from a Kubernetes Deployment without validating that the resource IDs within it belong to the correct tenant. An attacker can inject a malicious annotation pointing to a resource in another tenant's scope.
This function acts as the vulnerability sink. It takes the unvalidated container ID from the annotation (processed by `readAnnotations`) and initiates a deletion operation. In the vulnerable version, it did not verify that the controller had the right to delete the specified container, thus acting as a 'confused deputy' and deleting resources across tenants using its own elevated privileges.
reconciler.deleteContainer
pkg/controller/reconciler/util.go
This function is the final step in the attack chain, responsible for making the API call to the Radius control plane to delete the container resource. It directly uses the container ID passed to it, which, in the case of exploitation, is the malicious ID provided by the attacker.
This function is part of the main reconciliation loop for deployments. When a deployment is marked for deletion, this function is called. It orchestrates the cleanup process, which includes calling the vulnerable `startDeleteOperationIfNeeded` function, thereby triggering the cross-tenant resource deletion.
NAME READY STATUS RESTARTS AGE
applications-rp-xxx 1/1 Running 0 2m
bicep-de-xxx 1/1 Running 0 2m
controller-xxx 1/1 Running 0 2m
ucp-xxx 1/1 Running 0 2m
Step 2: Create Attacker Tenant (tenant-a)
# Create resource group
rad group create tenant-a
# Create environment
rad env create tenant-a-env --group tenant-a
# Switch to tenant-a
rad group switch tenant-a
rad env switch tenant-a-env