Repository navigation
Harden tenant hostname ValidatingAdmissionPolicies with case-insensitive comparison (defense-in-depth) #3205
Description
Activity
- addedsecurity/lowLow severity security findingLow severity security findingpriority/backlogGeneral backlog priority. Lower than priority/important-longtermGeneral backlog priority. Lower than priority/important-longtermkind/cleanupCategorizes issue or PR as related to cleanup of code, process, or technical debtCategorizes issue or PR as related to cleanup of code, process, or technical debtarea/networkingIssues or PRs related to networking (ingress, gateway, vpn, metallb, kube-ovn)Issues or PRs related to networking (ingress, gateway, vpn, metallb, kube-ovn)
on Jul 4, 2026 - addedsecurity/mediumMedium severity security findingMedium severity security findingkind/bugCategorizes issue or PR as related to a bugCategorizes issue or PR as related to a bugpriority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next releaseMust be staffed and worked on either currently, or very soon, ideally in time for the next releaseand removedsecurity/lowLow severity security findingLow severity security findingpriority/backlogGeneral backlog priority. Lower than priority/important-longtermGeneral backlog priority. Lower than priority/important-longtermkind/cleanupCategorizes issue or PR as related to cleanup of code, process, or technical debtCategorizes issue or PR as related to cleanup of code, process, or technical debt
on Jul 16, 2026 lexfrei commented
on Jul 16, 2026 ContributorAuthorMore actionsRe-labelled after checking the uppercase-root-host half against the rendered CEL rather than the description.
This issue reads the problem as hardening, on the grounds that the resource-side host is validated lowercase so casing cannot be used to sidestep the comparison. That holds for the hostname operand. It does not hold for the two apex operands: the
namespace.cozystack.io/hostlabel value (Kubernetes permits uppercase in a label value) and the templated_cluster.root-host, which is free-form platform config — the platform chart has novalues.schema.json, and the value is read verbatim from thecozystackConfigMap. The Ingress policy templates that value into its outside-root exclusion.With
root-host: Example.ORG, the exclusion compares a lowercase host against the uppercase literal, never matches, and so stops excluding — the policy then admits any non-wildcard host. Evaluated with cel-go against the rendered pre-fix expression, a tenant whose apex isalice.example.orgis admitted fordashboard.example.org, for another tenant'svictim.example.org, and for the bare root apexexample.org. Post-fix all three are denied, and the anti-wildcard gate holds in both.That is a bypass of the control rather than defense-in-depth, hence
security/low→security/mediumandkind/cleanup→kind/bug. It stays belowhighbecause it is not tenant-reachable: only a trusted caller can set the root host, and a cluster carrying an uppercase one is already visibly broken, since the dashboard's own Ingress renders mixed-case and is rejected by hostname validation before it exists.priority/important-soonbecause the Ingress policy has only shipped in 1.6.0-rc so far — no stable release carries this, so no backport is needed, but it should land before 1.6.0 GA.- added a commit that references this issue
on Aug 12, 2026
Summary
The tenant hostname
ValidatingAdmissionPolicyobjects compare hostnames against the tenant apex using case-sensitive CEL operators (==,endsWith,startsWith). Automated review of #3200 flagged this as a potential case-based bypass.It is not a live issue: the Kubernetes apiserver validates Ingress
spec.rules[].host/spec.tls[].hosts[]and Gateway API hostnames as DNS-1123 (sub)domains, which reject any uppercase character (kubernetes/kubernetes#71140). A mixed-case hostname is therefore rejected by built-in validation and can never be persisted, so these policies only ever see already-lowercased hosts.Still, normalizing with
.lowerAscii()before the comparisons is cheap defense-in-depth — robust against any future validation change, and consistent with reviewer expectations. It should be applied uniformly across all three policies rather than just one.Scope
Apply case-insensitive comparison (
.lowerAscii()on both the hostname and the apex / root-host literal), plus a mixed-case test, to:cozystack-ingress-hostname-policy(packages/system/cozystack-basics/templates/ingress-hostname-policy.yaml)cozystack-gateway-hostname-policy(packages/system/cozystack-basics/templates/gateway-hostname-policy.yaml)cozystack-route-hostname-policy(packages/system/cozystack-basics/templates/route-hostname-policy.yaml)Update the matching helm-unittest and
hack/e2e-apps/gateway.batscoverage.Notes