CVE-2026-61672
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement
CVE-2026-61672 is a high vulnerability (CVSS 7.1) in Projectcapsule Capsule, published September 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.33%, the 26th percentile. Fixed in github.com/projectcapsule/capsule 0.13.7.
Capsule is a multi-tenancy and policy-based framework for Kubernetes. Prior to 0.13.7, ForbiddenListSpec.ExactMatch in pkg/api/forbidden_list.go sorts denied metadata keys case-insensitively and then uses sort.SearchStrings, which assumes byte-order sorting. When an administrator's forbidden list mixes capitalized and lowercase keys or otherwise has different case-insensitive and byte ordering, the binary search can return false for a key that is present. An authenticated tenant owner can then pass the missed key through api.ValidateForbidden and bypass configured namespace, Service, or delegated node metadata restrictions, potentially influencing cluster policies, network exposure, or scheduling outside the tenant boundary. Uniformly lowercase lists whose two orderings coincide are not affected. This issue is fixed in version 0.13.7.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.1
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement
Capsule is a multi-tenancy and policy-based framework for Kubernetes. Prior to 0.13.7, ForbiddenListSpec.ExactMatch in pkg/api/forbidden_list.go sorts denied metadata keys case-insensitively and then uses sort.SearchStrings, which assumes byte-order sorting. When an administrator's forbidden list mixes capitalized and lowercase keys or otherwise has different case-insensitive and byte ordering, the binary search can return false for a key that is present. An authenticated tenant owner can then pass the missed key through api.ValidateForbidden and bypass configured namespace, Service, or delegated node metadata restrictions, potentially influencing cluster policies, network exposure, or scheduling outside the tenant boundary. Uniformly lowercase lists whose two orderings coincide are not affected. This issue is fixed in version 0.13.7.
- Record
CVE-2026-61672- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-697, CWE-863
- Updated
- 2026-11-02
EUVDEUVD-2026-83164
7.1
Capsule is a multi-tenancy and policy-based framework for Kubernetes. Prior to 0.13.7, ForbiddenListSpec.ExactMatch in pkg/api/forbidden_list.go sorts denied metadata keys case-insensitively and then uses sort.SearchStrings, which assumes byte-order sorting. When an administrator's forbidden list mixes capitalized and lowercase keys or otherwise has different case-insensitive and byte ordering, the binary search can return false for a key that is present. An authenticated tenant owner can then pass the missed key through api.ValidateForbidden and bypass configured namespace, Service, or delegated node metadata restrictions, potentially influencing cluster policies, network exposure, or scheduling outside the tenant boundary. Uniformly lowercase lists whose two orderings coincide are not affected. This issue is fixed in version 0.13.7.
- Record
EUVD-2026-83164- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-gjw4-3v3v-rqxg
7.1
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement
Summary
Capsule lets a cluster administrator forbid specific metadata keys that tenant owners must not place on their own resources: Tenant.spec.namespaceOptions.forbiddenLabels / forbiddenAnnotations (namespaces), Tenant.spec.serviceOptions.forbiddenLabels / forbiddenAnnotations (Services), and the cluster-wide forbidden worker-node labels/annotations. These lists are an isolation control — they exist to stop a tenant owner from setting metadata that other controllers or admission plugins key on (Pod Security Admission labels, kubernetes.io/metadata.name, LoadBalancer/externalIP service annotations, scheduler annotations, vendor labels that grant network reach, etc.). The validating webhooks enforce them through api.ValidateForbidden, which calls ForbiddenListSpec.ExactMatch(key) for every key the tenant submits.
ExactMatch is broken. It sorts the denied list case-insensitively (sort.SliceStable with a strings.ToLower comparator) and then performs a byte-order binary search (sort.SearchStrings) over the result. sort.SearchStrings is only correct on a slice sorted in plain byte-ascending order. Whenever the denied list contains an entry whose case-insensitive position differs from its byte position — which happens any time the list mixes a capitalised key with lowercase keys, because ASCII uppercase letters (0x41–0x5A) sort before lowercase (0x61–0x7A) by byte but are interleaved by ToLower — the binary search lands on the wrong index and ExactMatch returns false for a key that is literally present in the denied list. The webhook then allows the forbidden metadata.
A tenant owner (who legitimately holds patch/create rights on their own tenant-owned namespaces and Services) can therefore set a metadata key the administrator explicitly forbade, defeating the control and reaching metadata-driven cross-tenant / system effects of exactly the kind Capsule's forbidden lists are meant to prevent. The bug is deterministic, requires no race, and is present unchanged on main HEAD.
Affected code (v0.13.5)
pkg/api/forbidden_list.go — the comparison primitive:
func (in ForbiddenListSpec) ExactMatch(value string) (ok bool) {
if len(in.Exact) > 0 {
sort.SliceStable(in.Exact, func(i, j int) bool {
return strings.ToLower(in.Exact[i]) < strings.ToLower(in.Exact[j]) // case-INSENSITIVE order
})
i := sort.SearchStrings(in.Exact, value) // binary search assuming BYTE order
ok = i < len(in.Exact) && in.Exact[i] == value
}
return ok
}
sort.SearchStrings returns the smallest index i such that in.Exact[i] >= value under raw byte comparison. If the slice is not byte-sorted, that index is wrong and the subsequent in.Exact[i] == value equality check fails even though value is in the slice — a false "not forbidden".
pkg/api/forbidden_list.go — the public entry point the webhooks call:
func ValidateForbidden(metadata map[string]string, forbiddenList ForbiddenListSpec) error {
if reflect.DeepEqual(ForbiddenListSpec{}, forbiddenList) {
return nil
}
for key := range metadata {
var forbidden, matched bool
forbidden = forbiddenList.ExactMatch(key) // <-- buggy
matched = forbiddenList.RegexMatch(key)
if forbidden || matched {
return NewForbiddenError(key, forbiddenList)
}
}
return nil
}
Reached from (all in internal/webhook/):
namespace/validation/user_metadata.go→validateUserMetadata→api.ValidateForbidden(labels, options.ForbiddenLabels)andapi.ValidateForbidden(annotations, options.ForbiddenAnnotations).service/validating.go→api.ValidateForbidden(svc.Labels, tnt.Spec.ServiceOptions.ForbiddenLabels)and...ForbiddenAnnotations.node/user_metadata.go→getForbiddenNodeLabels/getForbiddenNodeAnnotationscallforbiddenLabels.ExactMatch(...)directly.
(The sibling allow-list primitive AllowedListSpec.ExactMatch in pkg/api/allowed_list.go has the identical defect,…
- Record
GHSA-gjw4-3v3v-rqxg- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-697, CWE-863
- Updated
- 2026-11-02
NVD
7.1
Capsule is a multi-tenancy and policy-based framework for Kubernetes. Prior to 0.13.7, ForbiddenListSpec.ExactMatch in pkg/api/forbidden_list.go sorts denied metadata keys case-insensitively and then uses sort.SearchStrings, which assumes byte-order sorting. When an administrator's forbidden list mixes capitalized and lowercase keys or otherwise has different case-insensitive and byte ordering, the binary search can return false for a key that is present. An authenticated tenant owner can then pass the missed key through api.ValidateForbidden and bypass configured namespace, Service, or delegated node metadata restrictions, potentially influencing cluster policies, network exposure, or scheduling outside the tenant boundary. Uniformly lowercase lists whose two orderings coincide are not affected. This issue is fixed in version 0.13.7.
- Record
CVE-2026-61672- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-697, CWE-863
- Updated
- 2026-11-02
OSV
7.1
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement
Capsule is a multi-tenancy and policy-based framework for Kubernetes. Prior to 0.13.7, ForbiddenListSpec.ExactMatch in pkg/api/forbidden_list.go sorts denied metadata keys case-insensitively and then uses sort.SearchStrings, which assumes byte-order sorting. When an administrator's forbidden list mixes capitalized and lowercase keys or otherwise has different case-insensitive and byte ordering, the binary search can return false for a key that is present. An authenticated tenant owner can then pass the missed key through api.ValidateForbidden and bypass configured namespace, Service, or delegated node metadata restrictions, potentially influencing cluster policies, network exposure, or scheduling outside the tenant boundary. Uniformly lowercase lists whose two orderings coincide are not affected. This issue is fixed in version 0.13.7.
- Record
CVE-2026-61672- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-697, CWE-863
- Updated
- 2026-11-02
OSVGHSA-gjw4-3v3v-rqxg
7.1
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement
Summary
Capsule lets a cluster administrator forbid specific metadata keys that tenant owners must not place on their own resources: Tenant.spec.namespaceOptions.forbiddenLabels / forbiddenAnnotations (namespaces), Tenant.spec.serviceOptions.forbiddenLabels / forbiddenAnnotations (Services), and the cluster-wide forbidden worker-node labels/annotations. These lists are an isolation control — they exist to stop a tenant owner from setting metadata that other controllers or admission plugins key on (Pod Security Admission labels, kubernetes.io/metadata.name, LoadBalancer/externalIP service annotations, scheduler annotations, vendor labels that grant network reach, etc.). The validating webhooks enforce them through api.ValidateForbidden, which calls ForbiddenListSpec.ExactMatch(key) for every key the tenant submits.
ExactMatch is broken. It sorts the denied list case-insensitively (sort.SliceStable with a strings.ToLower comparator) and then performs a byte-order binary search (sort.SearchStrings) over the result. sort.SearchStrings is only correct on a slice sorted in plain byte-ascending order. Whenever the denied list contains an entry whose case-insensitive position differs from its byte position — which happens any time the list mixes a capitalised key with lowercase keys, because ASCII uppercase letters (0x41–0x5A) sort before lowercase (0x61–0x7A) by byte but are interleaved by ToLower — the binary search lands on the wrong index and ExactMatch returns false for a key that is literally present in the denied list. The webhook then allows the forbidden metadata.
A tenant owner (who legitimately holds patch/create rights on their own tenant-owned namespaces and Services) can therefore set a metadata key the administrator explicitly forbade, defeating the control and reaching metadata-driven cross-tenant / system effects of exactly the kind Capsule's forbidden lists are meant to prevent. The bug is deterministic, requires no race, and is present unchanged on main HEAD.
Affected code (v0.13.5)
pkg/api/forbidden_list.go — the comparison primitive:
func (in ForbiddenListSpec) ExactMatch(value string) (ok bool) {
if len(in.Exact) > 0 {
sort.SliceStable(in.Exact, func(i, j int) bool {
return strings.ToLower(in.Exact[i]) < strings.ToLower(in.Exact[j]) // case-INSENSITIVE order
})
i := sort.SearchStrings(in.Exact, value) // binary search assuming BYTE order
ok = i < len(in.Exact) && in.Exact[i] == value
}
return ok
}
sort.SearchStrings returns the smallest index i such that in.Exact[i] >= value under raw byte comparison. If the slice is not byte-sorted, that index is wrong and the subsequent in.Exact[i] == value equality check fails even though value is in the slice — a false "not forbidden".
pkg/api/forbidden_list.go — the public entry point the webhooks call:
func ValidateForbidden(metadata map[string]string, forbiddenList ForbiddenListSpec) error {
if reflect.DeepEqual(ForbiddenListSpec{}, forbiddenList) {
return nil
}
for key := range metadata {
var forbidden, matched bool
forbidden = forbiddenList.ExactMatch(key) // <-- buggy
matched = forbiddenList.RegexMatch(key)
if forbidden || matched {
return NewForbiddenError(key, forbiddenList)
}
}
return nil
}
Reached from (all in internal/webhook/):
namespace/validation/user_metadata.go→validateUserMetadata→api.ValidateForbidden(labels, options.ForbiddenLabels)andapi.ValidateForbidden(annotations, options.ForbiddenAnnotations).service/validating.go→api.ValidateForbidden(svc.Labels, tnt.Spec.ServiceOptions.ForbiddenLabels)and...ForbiddenAnnotations.node/user_metadata.go→getForbiddenNodeLabels/getForbiddenNodeAnnotationscallforbiddenLabels.ExactMatch(...)directly.
(The sibling allow-list primitive AllowedListSpec.ExactMatch in pkg/api/allowed_list.go has the identical defect,…
- Record
GHSA-gjw4-3v3v-rqxg- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-697, CWE-863
- Updated
- 2026-11-02
OSVGO-2026-6520 No score
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement in github.com/projectcapsule/capsule
Capsule: Tenant owner bypasses Capsule's forbidden namespace/service/node label and annotation enforcement in github.com/projectcapsule/capsule
- Record
GO-2026-6520- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/projectcapsule/capsuleGo |
through 0.13.6 | 0.13.7 |
github.com/projectcapsule/capsuleGo |
before 0.13.7 | 0.13.7 |
History
| When | Changed | Sources |
|---|---|---|
| 2026-11-02 | created | CVE List, EUVD, GitHub Advisories, NVD, OSV |
References
github.com/projectcapsule/capsule/security/advisories/GHSA-gjw4-3v3v-rqxg
github.com/projectcapsule/capsule/pull/1982
github.com/projectcapsule/capsule/commit/755cef54bf4a1bc56d6692130132bc70755bef46
github.com/projectcapsule/capsule/releases/tag/v0.13.7
github.com/advisories/GHSA-gjw4-3v3v-rqxg
github.com/CVEProject/cvelistV5/tree/main/cves/2026/61xxx/CVE-2026-61672.json
nvd.nist.gov/vuln/detail/CVE-2026-61672
github.com/projectcapsule/capsule
Left out here: the rest of 2 source descriptions. The JSON record has them.