Skip to content

Harden tenant hostname ValidatingAdmissionPolicies with case-insensitive comparison (defense-in-depth) #3205

Description

Summary

The tenant hostname ValidatingAdmissionPolicy objects 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.bats coverage.

Notes

Activity

  1. added
    security/lowLow severity security finding
    priority/backlogGeneral backlog priority. Lower than priority/important-longterm
    kind/cleanupCategorizes issue or PR as related to cleanup of code, process, or technical debt
    area/networkingIssues or PRs related to networking (ingress, gateway, vpn, metallb, kube-ovn)
    on Jul 4, 2026
  2. added
    security/mediumMedium severity security finding
    kind/bugCategorizes issue or PR as related to a bug
    priority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next release
    and removed
    security/lowLow severity security finding
    priority/backlogGeneral backlog priority. Lower than priority/important-longterm
    kind/cleanupCategorizes issue or PR as related to cleanup of code, process, or technical debt
    on Jul 16, 2026
  3. lexfrei commented on Jul 16, 2026

    @lexfrei
    ContributorAuthor

    Re-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/host label value (Kubernetes permits uppercase in a label value) and the templated _cluster.root-host, which is free-form platform config — the platform chart has no values.schema.json, and the value is read verbatim from the cozystack ConfigMap. 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 is alice.example.org is admitted for dashboard.example.org, for another tenant's victim.example.org, and for the bare root apex example.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/medium and kind/cleanup → kind/bug. It stays below high because 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-soon because 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.

  4. added a commit that references this issue on Aug 12, 2026
    516be4a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/networkingIssues or PRs related to networking (ingress, gateway, vpn, metallb, kube-ovn)kind/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 releasesecurity/mediumMedium severity security finding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions