Skip to main content
security · kubernetes

Ingress resources serving without a TLS block

resource types
1
rule IDs covered
3
severity
high

What does ZopNight detect here?

An Ingress with no `tls` section serves plaintext HTTP, exposing cookies and tokens on the wire. Adding 1 `tls` block plus a matching `kubernetes.io/tls` Secret fixes it, and cert-manager issues and renews those free from Let's Encrypt. ZopNight skips `cm-acme-http-solver-*` ingresses, which are HTTP-only by protocol design.

Signal and threshold

How ZopNight evaluates Ingress resources serving without a TLS block.
Field Value
Rule IDsRC-1720 · RC-1820 · RC-1920
Categorysecurity
Severityhigh
Metricnone — pure configuration read
Sourceinternal/rules/k8s/ingress_no_tls.go

Plaintext at the edge, not just in transit

An Ingress is usually the first thing outside the cluster touches. Without a tls block, the controller serves the route over HTTP, and everything on the wire (session cookies, bearer tokens, form posts) is readable by anything between the client and the load balancer.

The part worth being precise about: a cloud load balancer sitting in front of the Ingress may already be terminating TLS. In that case the exposure is hop-by-hop rather than end-to-end, and the finding is about the leg from the load balancer to the cluster, not about the browser connection. Check which is true before deciding urgency.

The ACME solver exception

Ingresses named cm-acme-http-solver-* are excluded. cert-manager creates these temporarily to answer an HTTP-01 challenge, which by protocol definition must be served over plain HTTP. Let’s Encrypt fetches a token from /.well-known/acme-challenge/ before any certificate exists.

Flagging them would mean flagging the mechanism that fixes the finding.

Why this rarely stays unfixed once someone looks

Certificates are the reason people assume this is hard, and they have not been hard for some years. cert-manager watches Ingress resources, requests a certificate from Let’s Encrypt, writes the Secret, and renews it before expiry with no human involved. The cost is zero.

Most untagged Ingresses in this state are not a decision. They are a manifest written before cert-manager was installed and never revisited.

TLS present is not redirect present

Adding the tls block makes HTTPS work. It does not stop HTTP working. A client that types the bare hostname still gets plaintext unless the controller is told to redirect, which on ingress-nginx is the ssl-redirect annotation and on other controllers is its own equivalent.

Half-finished remediation here is common and looks complete from a certificate check.

When the rule stays silent

If the discoverer captured no tlsEnabled key for the Ingress, nothing is emitted. Missing metadata is not read as “no TLS”.

Listing Ingresses with an empty spec.tls

Terminal window
kubectl get ingress -A -o json | jq -r '
.items[] | select((.spec.tls | length) == 0)
| select(.metadata.name | startswith("cm-acme-http-solver-") | not)
| "\(.metadata.namespace)/\(.metadata.name)\t\(.spec.rules[]?.host // "-")"'

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·