kubernetesIngressNGINX: location ^~ modifier silently fails to match paths in server-snippet
Welcome!
- Yes, I've searched similar issues on GitHub and didn't find any.
- Yes, I've searched similar issues on the Traefik community forum and didn't find any.
What did you do?
Used kubernetesIngressNGINX provider with an Ingress containing an NGINX server-snippet using the standard ^~ (best prefix match) location modifier to block internal paths:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
location ^~ /internal {
return 404;
}
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-service
port:
number: 80
Sent an HTTP request to GET /internal.
What did you see instead?
The request to /internal was not blocked and fell through to the catch-all path: / backend. No error or warning was produced during Ingress parsing or at runtime.
Root Cause in Source Code:
In pkg/middlewares/ingressnginx/snippet/collector.go:
createLocationCollectable()handles 2 parameters when a modifier is present:pathPattern := params[0].String() if len(params) == 2 { pathPattern += params[1].String() }For
location ^~ /internal,params[0]is"^~"andparams[1]is"/internal", makingpathPattern = "^~/internal".buildLocationMatcher(pathPattern)checks for~*,~, and=, but omits^~:func buildLocationMatcher(pathPattern string) (locationMatcher, error) { if pattern, ok := strings.CutPrefix(pathPattern, "~*"); ok { ... } if pattern, ok := strings.CutPrefix(pathPattern, "~"); ok { ... } if exact, ok := strings.CutPrefix(pathPattern, "="); ok { ... } // Fallback: Prefix match return func(req *http.Request) bool { return strings.HasPrefix(req.URL.Path, pathPattern) }, nil }Because
"^~/internal"does not start with~or=, it falls into the prefix match fallback:strings.HasPrefix(req.URL.Path, "^~/internal").Since request paths never start with
"^~",matcher(req)silently evaluates tofalsefor every request, causing the block to never execute.
What version of Traefik are you using?
v3.7.5
What is your environment & configuration?
- Kubernetes with
kubernetesIngressNGINXprovider enabled (--providers.kubernetesingressnginx=true,--providers.kubernetesingressnginx.allowSnippetAnnotations=true). - Standard
networking.k8s.io/v1Ingress withnginx.ingress.kubernetes.io/server-snippet.
Source: traefik/traefik