Repository: envoyproxy/gateway
Pull request #5566 (2025-03-21 04:19:43)

[release/v1.2.8] cherry pick

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/5566?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
Attention: Patch coverage is `81.95489%` with `24 lines` in your changes missing coverage. Please review.
> Project coverage is 65.72%. Comparing base [(`4eb7745`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/4eb774504fd4f2ff35483a939397d3fe417115f6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`5214652`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/521465263aeefbe1ddb39045f7095e2e50be841a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

| [Files with missing lines](https://app.codecov.io/gh/envoyproxy/gateway/pull/5566?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) | Patch % | Lines |
|---|---|---|
| [internal/gatewayapi/filters.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/5566?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Ffilters.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9maWx0ZXJzLmdv) | 81.95% | [24 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/5566?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |

<details><summary>Additional details and impacted files</summary>


```diff
@@               Coverage Diff                @@
##           release/v1.2    #5566      +/-   ##
================================================
+ Coverage         65.68%   65.72%   +0.03%     
================================================
  Files               211      211              
  Lines             32183    32026     -157     
================================================
- Hits              21141    21049      -92     
+ Misses             9787     9726      -61     
+ Partials           1255     1251       -4     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/5566?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/VERSION b/VERSION
index 503f4b129..d1f79a941 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-v1.2.7
+v1.2.8
diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go
index 1e57786d0..9ef305acb 100644
--- a/api/v1alpha1/shared_types.go
+++ b/api/v1alpha1/shared_types.go
@@ -22,7 +22,7 @@ const (
 	// DefaultDeploymentMemoryResourceRequests for deployment memory resource
 	DefaultDeploymentMemoryResourceRequests = "512Mi"
 	// DefaultEnvoyProxyImage is the default image used by envoyproxy
-	DefaultEnvoyProxyImage = "docker.io/envoyproxy/envoy:distroless-v1.32.3"
+	DefaultEnvoyProxyImage = "docker.io/envoyproxy/envoy:distroless-v1.32.4"
 	// DefaultShutdownManagerCPUResourceRequests for shutdown manager cpu resource
 	DefaultShutdownManagerCPUResourceRequests = "10m"
 	// DefaultShutdownManagerMemoryResourceRequests for shutdown manager memory resource
@@ -30,7 +30,7 @@ const (
 	// DefaultShutdownManagerImage is the default image used for the shutdown manager.
 	DefaultShutdownManagerImage = "docker.io/envoyproxy/gateway-dev:latest"
 	// DefaultRateLimitImage is the default image used by ratelimit.
-	DefaultRateLimitImage = "docker.io/envoyproxy/ratelimit:ae4cee11"
+	DefaultRateLimitImage = "docker.io/envoyproxy/ratelimit:0141a24f"
 	// HTTPProtocol is the common-used http protocol.
 	HTTPProtocol = "http"
 	// GRPCProtocol is the common-used grpc protocol.
diff --git a/charts/gateway-helm/README.md b/charts/gateway-helm/README.md
index b49a6ba7e..11ed2a80a 100644
--- a/charts/gateway-helm/README.md
+++ b/charts/gateway-helm/README.md
@@ -102,7 +102,7 @@ To uninstall the chart:
 | global.images.envoyGateway.image | string | `nil` |  |
 | global.images.envoyGateway.pullPolicy | string | `nil` |  |
 | global.images.envoyGateway.pullSecrets | list | `[]` |  |
-| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:ae4cee11"` |  |
+| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:0141a24f"` |  |
 | global.images.ratelimit.pullPolicy | string | `"IfNotPresent"` |  |
 | global.images.ratelimit.pullSecrets | list | `[]` |  |
 | kubernetesClusterDomain | string | `"cluster.local"` |  |
diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml
index a9d3c88df..896c711e5 100644
--- a/charts/gateway-helm/values.tmpl.yaml
+++ b/charts/gateway-helm/values.tmpl.yaml
@@ -12,7 +12,7 @@ global:
       pullSecrets: []
     ratelimit:
       # This is the full image name including the hub, repo, and tag.
-      image: "docker.io/envoyproxy/ratelimit:ae4cee11"
+      image: "docker.io/envoyproxy/ratelimit:0141a24f"
       # Specify image pull policy if default behavior isn't desired.
       # Default behavior: latest images will be Always else IfNotPresent.
       pullPolicy: IfNotPresent
diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod
index 2ae1badd0..b0a14dfcb 100644
--- a/examples/extension-server/go.mod
+++ b/examples/extension-server/go.mod
@@ -16,7 +16,7 @@ require (
 require (
 	cel.dev/expr v0.16.0 // indirect
 	github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
-	github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 // indirect
+	github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
 	github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
diff --git a/examples/extension-server/go.sum b/examples/extension-server/go.sum
index 960a9ee8a..0895c8038 100644
--- a/examples/extension-server/go.sum
+++ b/examples/extension-server/go.sum
@@ -2,8 +2,8 @@ cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y=
 cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
 github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
 github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg=
-github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
+github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
+github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
 github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
 github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
diff --git a/go.mod b/go.mod
index 103a5e7ff..5914bb1ef 100644
--- a/go.mod
+++ b/go.mod
@@ -7,8 +7,10 @@ replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
 require (
 	fortio.org/fortio v1.67.1
 	fortio.org/log v1.17.1
-	github.com/Masterminds/semver/v3 v3.3.0
-	github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20
+	github.com/Masterminds/semver/v3 v3.3.1
+	github.com/avast/retry-go v3.0.0+incompatible
+	github.com/cenkalti/backoff/v4 v4.3.0
+	github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
 	github.com/docker/cli v27.3.1+incompatible
 	github.com/dominikbraun/graph v0.23.0
@@ -223,7 +225,6 @@ require (
 	github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
 	github.com/MakeNowJust/heredoc v1.0.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/cenkalti/backoff/v4 v4.3.0
 	github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/chai2010/gettext-go v1.0.3 // indirect
diff --git a/go.sum b/go.sum
index 12cc6d685..fce2b5e01 100644
--- a/go.sum
+++ b/go.sum
@@ -62,8 +62,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ
 github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
 github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
 github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
-github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
+github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
 github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
 github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
 github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
@@ -97,6 +97,8 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
+github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -123,8 +125,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
 github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg=
-github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
+github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
+github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
 github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go
index 68bf84b33..f8a8c4cd9 100644
--- a/internal/gatewayapi/filters.go
+++ b/internal/gatewayapi/filters.go
@@ -188,15 +188,9 @@ func (t *Translator) processURLRewriteFilter(
 	if filterContext.URLRewrite != nil {
 		if hasMultipleCoreRewrites(rewrite, filterContext.URLRewrite) ||
 			hasConflictingCoreAndExtensionRewrites(rewrite, filterContext.URLRewrite) {
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				"Cannot configure multiple urlRewrite filters for a single HTTPRouteRule",
-			)
+			updateRouteStatusForFilter(
+				filterContext,
+				"Cannot configure multiple urlRewrite filters for a single HTTPRouteRule")
 			return
 		}
 	}
@@ -209,15 +203,7 @@ func (t *Translator) processURLRewriteFilter(
 
 	if rewrite.Hostname != nil {
 		if err := t.validateHostname(string(*rewrite.Hostname)); err != nil {
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				err.Error(),
-			)
+			updateRouteStatusForFilter(filterContext, err.Error())
 			return
 		}
 		redirectHost := string(*rewrite.Hostname)
@@ -230,29 +216,15 @@ func (t *Translator) processURLRewriteFilter(
 		switch rewrite.Path.Type {
 		case gwapiv1.FullPathHTTPPathModifier:
 			if rewrite.Path.ReplacePrefixMatch != nil {
-				errMsg := "ReplacePrefixMatch cannot be set when rewrite path type is \"ReplaceFullPath\""
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					errMsg,
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ReplacePrefixMatch cannot be set when rewrite path type is \"ReplaceFullPath\"")
 				return
 			}
 			if rewrite.Path.ReplaceFullPath == nil {
-				errMsg := "ReplaceFullPath must be set when rewrite path type is \"ReplaceFullPath\""
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					errMsg,
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ReplaceFullPath must be set when rewrite path type is \"ReplaceFullPath\"")
 				return
 			}
 			if rewrite.Path.ReplaceFullPath != nil {
@@ -264,29 +236,15 @@ func (t *Translator) processURLRewriteFilter(
 			}
 		case gwapiv1.PrefixMatchHTTPPathModifier:
 			if rewrite.Path.ReplaceFullPath != nil {
-				errMsg := "ReplaceFullPath cannot be set when rewrite path type is \"ReplacePrefixMatch\""
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					errMsg,
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ReplaceFullPath cannot be set when rewrite path type is \"ReplacePrefixMatch\"")
 				return
 			}
 			if rewrite.Path.ReplacePrefixMatch == nil {
-				errMsg := "ReplacePrefixMatch must be set when rewrite path type is \"ReplacePrefixMatch\""
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					errMsg,
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ReplacePrefixMatch must be set when rewrite path type is \"ReplacePrefixMatch\"")
 				return
 			}
 			if rewrite.Path.ReplacePrefixMatch != nil {
@@ -297,16 +255,11 @@ func (t *Translator) processURLRewriteFilter(
 				}
 			}
 		default:
-			errMsg := fmt.Sprintf("Rewrite path type: %s is invalid, only \"ReplaceFullPath\" and \"ReplacePrefixMatch\" are supported", rewrite.Path.Type)
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				errMsg,
-			)
+			updateRouteStatusForFilter(
+				filterContext,
+				fmt.Sprintf(
+					"Rewrite path type: %s is invalid, only \"ReplaceFullPath\" and \"ReplacePrefixMatch\" are supported",
+					rewrite.Path.Type))
 			return
 		}
 	}
@@ -320,15 +273,9 @@ func (t *Translator) processRedirectFilter(
 ) {
 	// Can't have two redirects for the same route
 	if filterContext.RedirectResponse != nil {
-		routeStatus := GetRouteStatus(filterContext.Route)
-		status.SetRouteStatusCondition(routeStatus,
-			filterContext.ParentRef.routeParentStatusIdx,
-			filterContext.Route.GetGeneration(),
-			gwapiv1.RouteConditionAccepted,
-			metav1.ConditionFalse,
-			gwapiv1.RouteReasonUnsupportedValue,
-			"Cannot configure multiple requestRedirect filters for a single HTTPRouteRule",
-		)
+		updateRouteStatusForFilter(
+			filterContext,
+			"Cannot configure multiple requestRedirect filters for a single HTTPRouteRule")
 		return
 	}
 
@@ -343,31 +290,16 @@ func (t *Translator) processRedirectFilter(
 		if *redirect.Scheme == "http" || *redirect.Scheme == "https" {
 			redir.Scheme = redirect.Scheme
 		} else {
-			errMsg := fmt.Sprintf("Scheme: %s is unsupported, only 'https' and 'http' are supported", *redirect.Scheme)
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				errMsg,
-			)
+			updateRouteStatusForFilter(
+				filterContext,
+				fmt.Sprintf("Scheme: %s is unsupported, only 'https' and 'http' are supported", *redirect.Scheme))
 			return
 		}
 	}
 
 	if redirect.Hostname != nil {
 		if err := t.validateHostname(string(*redirect.Hostname)); err != nil {
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				err.Error(),
-			)
+			updateRouteStatusForFilter(filterContext, err.Error())
 		} else {
 			redirectHost := string(*redirect.Hostname)
 			redir.Hostname = &redirectHost
@@ -389,16 +321,11 @@ func (t *Translator) processRedirectFilter(
 				}
 			}
 		default:
-			errMsg := fmt.Sprintf("Redirect path type: %s is invalid, only \"ReplaceFullPath\" and \"ReplacePrefixMatch\" are supported", redirect.Path.Type)
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				errMsg,
-			)
+			updateRouteStatusForFilter(
+				filterContext,
+				fmt.Sprintf(
+					"Redirect path type: %s is invalid, only \"ReplaceFullPath\" and \"ReplacePrefixMatch\" are supported",
+					redirect.Path.Type))
 			return
 		}
 	}
@@ -410,15 +337,7 @@ func (t *Translator) processRedirectFilter(
 			redir.StatusCode = &redirectCode
 		} else {
 			errMsg := fmt.Sprintf("Status code %d is invalid, only 302 and 301 are supported", redirectCode)
-			routeStatus := GetRouteStatus(filterContext.Route)
-			status.SetRouteStatusCondition(routeStatus,
-				filterContext.ParentRef.routeParentStatusIdx,
-				filterContext.Route.GetGeneration(),
-				gwapiv1.RouteConditionAccepted,
-				metav1.ConditionFalse,
-				gwapiv1.RouteReasonUnsupportedValue,
-				errMsg,
-			)
+			updateRouteStatusForFilter(filterContext, errMsg)
 			return
 		}
 	}
@@ -449,28 +368,19 @@ func (t *Translator) processRequestHeaderModifierFilter(
 		for _, addHeader := range headersToAdd {
 			emptyFilterConfig = false
 			if addHeader.Name == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"RequestHeaderModifier Filter cannot add a header with an empty name",
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"RequestHeaderModifier Filter cannot add a header with an empty name")
 				// try to process the rest of the headers and produce a valid config.
 				continue
 			}
-			// Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names
-			if strings.Contains(string(addHeader.Name), "/") || strings.Contains(string(addHeader.Name), ":") {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					fmt.Sprintf("RequestHeaderModifier Filter cannot set headers with a '/' or ':' character in them. Header: %q", string(addHeader.Name)),
+			if !isModifiableHeader(string(addHeader.Name)) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The RequestHeaderModifier filter cannot set the Host header or headers with a '/' "+
+							"or ':' character in them. To modify the Host header use the URLRewrite or the HTTPRouteFilter filter.",
+						string(addHeader.Name)),
 				)
 				continue
 			}
@@ -506,27 +416,19 @@ func (t *Translator) processRequestHeaderModifierFilter(
 		for _, setHeader := range headersToSet {
 
 			if setHeader.Name == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"RequestHeaderModifier Filter cannot set a header with an empty name",
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"RequestHeaderModifier Filter cannot set a header with an empty name")
 				continue
 			}
-			// Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names
-			if strings.Contains(string(setHeader.Name), "/") || strings.Contains(string(setHeader.Name), ":") {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					fmt.Sprintf("RequestHeaderModifier Filter cannot set headers with a '/' or ':' character in them. Header: '%s'", string(setHeader.Name)),
+
+			if !isModifiableHeader(string(setHeader.Name)) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The RequestHeaderModifier filter cannot set the Host header or headers with a '/' "+
+							"or ':' character in them. To modify the Host header use the URLRewrite or the HTTPRouteFilter filter.",
+						string(setHeader.Name)),
 				)
 				continue
 			}
@@ -562,14 +464,19 @@ func (t *Translator) processRequestHeaderModifierFilter(
 		}
 		for _, removedHeader := range headersToRemove {
 			if removedHeader == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"RequestHeaderModifier Filter cannot remove a header with an empty name",
+				updateRouteStatusForFilter(
+					filterContext,
+					"RequestHeaderModifier Filter cannot remove a header with an empty name")
+				continue
+			}
+
+			if !isModifiableHeader(removedHeader) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The RequestHeaderModifier filter cannot remove the Host header or headers with a '/' "+
+							"or ':' character in them.",
+						removedHeader),
 				)
 				continue
 			}
@@ -591,18 +498,30 @@ func (t *Translator) processRequestHeaderModifierFilter(
 
 	// Update the status if the filter failed to configure any valid headers to add/remove
 	if len(filterContext.AddRequestHeaders) == 0 && len(filterContext.RemoveRequestHeaders) == 0 && !emptyFilterConfig {
-		routeStatus := GetRouteStatus(filterContext.Route)
-		status.SetRouteStatusCondition(routeStatus,
-			filterContext.ParentRef.routeParentStatusIdx,
-			filterContext.Route.GetGeneration(),
-			gwapiv1.RouteConditionAccepted,
-			metav1.ConditionFalse,
-			gwapiv1.RouteReasonUnsupportedValue,
-			"RequestHeaderModifier Filter did not provide valid configuration to add/set/remove any headers",
-		)
+		updateRouteStatusForFilter(
+			filterContext,
+			"RequestHeaderModifier Filter did not provide valid configuration to add/set/remove any headers")
 	}
 }
 
+func updateRouteStatusForFilter(filterContext *HTTPFiltersContext, message string) {
+	routeStatus := GetRouteStatus(filterContext.Route)
+	status.SetRouteStatusCondition(routeStatus,
+		filterContext.ParentRef.routeParentStatusIdx,
+		filterContext.Route.GetGeneration(),
+		gwapiv1.RouteConditionAccepted,
+		metav1.ConditionFalse,
+		gwapiv1.RouteReasonUnsupportedValue,
+		message,
+	)
+}
+
+func isModifiableHeader(headerName string) bool {
+	// Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names
+	// And Envoy does not allow modification the pseudo headers and the host header
+	return !strings.Contains(headerName, "/") && !strings.Contains(headerName, ":") && !strings.EqualFold(headerName, "host")
+}
+
 func (t *Translator) processResponseHeaderModifierFilter(
 	headerModifier *gwapiv1.HTTPHeaderFilter,
 	filterContext *HTTPFiltersContext,
@@ -621,29 +540,19 @@ func (t *Translator) processResponseHeaderModifierFilter(
 		for _, addHeader := range headersToAdd {
 			emptyFilterConfig = false
 			if addHeader.Name == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"ResponseHeaderModifier Filter cannot add a header with an empty name",
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ResponseHeaderModifier Filter cannot add a header with an empty name")
 				// try to process the rest of the headers and produce a valid config.
 				continue
 			}
-			// Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names
-			if strings.Contains(string(addHeader.Name), "/") || strings.Contains(string(addHeader.Name), ":") {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					fmt.Sprintf("ResponseHeaderModifier Filter cannot set headers with a '/' or ':' character in them. Header: %q", string(addHeader.Name)),
-				)
+			if !isModifiableHeader(string(addHeader.Name)) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The ResponseHeaderModifier filter cannot set the Host header or headers with a '/' "+
+							"or ':' character in them.",
+						string(addHeader.Name)))
 				continue
 			}
 			// Check if the header is a duplicate
@@ -678,28 +587,19 @@ func (t *Translator) processResponseHeaderModifierFilter(
 		for _, setHeader := range headersToSet {
 
 			if setHeader.Name == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"ResponseHeaderModifier Filter cannot set a header with an empty name",
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ResponseHeaderModifier Filter cannot set a header with an empty name")
 				continue
 			}
-			// Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names
-			if strings.Contains(string(setHeader.Name), "/") || strings.Contains(string(setHeader.Name), ":") {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					fmt.Sprintf("ResponseHeaderModifier Filter cannot set headers with a '/' or ':' character in them. Header: '%s'", string(setHeader.Name)),
-				)
+
+			if !isModifiableHeader(string(setHeader.Name)) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The ResponseHeaderModifier filter cannot set the Host header or headers with a '/' "+
+							"or ':' character in them.",
+						string(setHeader.Name)))
 				continue
 			}
 
@@ -734,15 +634,18 @@ func (t *Translator) processResponseHeaderModifierFilter(
 		}
 		for _, removedHeader := range headersToRemove {
 			if removedHeader == "" {
-				routeStatus := GetRouteStatus(filterContext.Route)
-				status.SetRouteStatusCondition(routeStatus,
-					filterContext.ParentRef.routeParentStatusIdx,
-					filterContext.Route.GetGeneration(),
-					gwapiv1.RouteConditionAccepted,
-					metav1.ConditionFalse,
-					gwapiv1.RouteReasonUnsupportedValue,
-					"ResponseHeaderModifier Filter cannot remove a header with an empty name",
-				)
+				updateRouteStatusForFilter(
+					filterContext,
+					"ResponseHeaderModifier Filter cannot remove a header with an empty name")
+				continue
+			}
+			if !isModifiableHeader(removedHeader) {
+				updateRouteStatusForFilter(
+					filterContext,
+					fmt.Sprintf(
+						"Header: %q. The ResponseHeaderModifier filter cannot remove the Host header or headers with a '/' "+
+							"or ':' character in them.",
+						removedHeader))
 				continue
 			}
 
@@ -764,15 +667,9 @@ func (t *Translator) processResponseHeaderModifierFilter(
 
 	// Update the status if the filter failed to configure any valid headers to add/remove
 	if len(filterContext.AddResponseHeaders) == 0 && len(filterContext.RemoveResponseHeaders) == 0 && !emptyFilterConfig {
-		routeStatus := GetRouteStatus(filterContext.Route)
-		status.SetRouteStatusCondition(routeStatus,
-			filterContext.ParentRef.routeParentStatusIdx,
-			filterContext.Route.GetGeneration(),
-			gwapiv1.RouteConditionAccepted,
-			metav1.ConditionFalse,
-			gwapiv1.RouteReasonUnsupportedValue,
-			"ResponseHeaderModifier Filter did not provide valid configuration to add/set/remove any headers",
-		)
+		updateRouteStatusForFilter(
+			filterContext,
+			"ResponseHeaderModifier Filter did not provide valid configuration to add/set/remove any headers")
 	}
 }
 
@@ -794,15 +691,9 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 					if filterContext.URLRewrite != nil {
 						if hasMultipleExtensionRewrites(hrf.Spec.URLRewrite, filterContext.URLRewrite) ||
 							hasConflictingExtensionAndCoreRewrites(hrf.Spec.URLRewrite, filterContext.URLRewrite) {
-							routeStatus := GetRouteStatus(filterContext.Route)
-							status.SetRouteStatusCondition(routeStatus,
-								filterContext.ParentRef.routeParentStatusIdx,
-								filterContext.Route.GetGeneration(),
-								gwapiv1.RouteConditionAccepted,
-								metav1.ConditionFalse,
-								gwapiv1.RouteReasonUnsupportedValue,
-								"Cannot configure multiple urlRewrite filters for a single HTTPRouteRule",
-							)
+							updateRouteStatusForFilter(
+								filterContext,
+								"Cannot configure multiple urlRewrite filters for a single HTTPRouteRule")
 							return
 						}
 					}
@@ -811,30 +702,16 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 						if hrf.Spec.URLRewrite.Path.Type == egv1a1.RegexHTTPPathModifier {
 							if hrf.Spec.URLRewrite.Path.ReplaceRegexMatch == nil ||
 								hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Pattern == "" {
-								errMsg := "ReplaceRegexMatch Pattern must be set when rewrite path type is \"ReplaceRegexMatch\""
-								routeStatus := GetRouteStatus(filterContext.Route)
-								status.SetRouteStatusCondition(routeStatus,
-									filterContext.ParentRef.routeParentStatusIdx,
-									filterContext.Route.GetGeneration(),
-									gwapiv1.RouteConditionAccepted,
-									metav1.ConditionFalse,
-									gwapiv1.RouteReasonUnsupportedValue,
-									errMsg,
-								)
+								updateRouteStatusForFilter(
+									filterContext,
+									"ReplaceRegexMatch Pattern must be set when rewrite path type is \"ReplaceRegexMatch\"")
 								return
 							} else if _, err := regexp.Compile(hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Pattern); err != nil {
 								// Avoid envoy NACKs due to invalid regex.
 								// Golang's regexp is almost identical to RE2: https://pkg.go.dev/regexp/syntax
-								errMsg := "ReplaceRegexMatch must be a valid RE2 regular expression"
-								routeStatus := GetRouteStatus(filterContext.Route)
-								status.SetRouteStatusCondition(routeStatus,
-									filterContext.ParentRef.routeParentStatusIdx,
-									filterContext.Route.GetGeneration(),
-									gwapiv1.RouteConditionAccepted,
-									metav1.ConditionFalse,
-									gwapiv1.RouteReasonUnsupportedValue,
-									errMsg,
-								)
+								updateRouteStatusForFilter(
+									filterContext,
+									"ReplaceRegexMatch must be a valid RE2 regular expression")
 								return
 							}
 
@@ -863,16 +740,9 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 						var hm *ir.HTTPHostModifier
 						if hrf.Spec.URLRewrite.Hostname.Type == egv1a1.HeaderHTTPHostnameModifier {
 							if hrf.Spec.URLRewrite.Hostname.Header == nil {
-								errMsg := "Header must be set when rewrite path type is \"Header\""
-								routeStatus := GetRouteStatus(filterContext.Route)
-								status.SetRouteStatusCondition(routeStatus,
-									filterContext.ParentRef.routeParentStatusIdx,
-									filterContext.Route.GetGeneration(),
-									gwapiv1.RouteConditionAccepted,
-									metav1.ConditionFalse,
-									gwapiv1.RouteReasonUnsupportedValue,
-									errMsg,
-								)
+								updateRouteStatusForFilter(
+									filterContext,
+									"Header must be set when rewrite path type is \"Header\"")
 								return
 							}
 							hm = &ir.HTTPHostModifier{
@@ -1012,14 +882,7 @@ func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *H
 		gwapiv1.RouteReasonBackendNotFound,
 		errMsg,
 	)
-	status.SetRouteStatusCondition(routeStatus,
-		filterContext.ParentRef.routeParentStatusIdx,
-		filterContext.Route.GetGeneration(),
-		gwapiv1.RouteConditionAccepted,
-		metav1.ConditionFalse,
-		gwapiv1.RouteReasonUnsupportedValue,
-		errMsg,
-	)
+	updateRouteStatusForFilter(filterContext, errMsg)
 	filterContext.DirectResponse = &ir.CustomResponse{
 		StatusCode: ptr.To(uint32(500)),
 	}
@@ -1027,31 +890,16 @@ func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *H
 
 func (t *Translator) processUnsupportedHTTPFilter(filterType string, filterContext *HTTPFiltersContext) {
 	errMsg := fmt.Sprintf("Unsupported filter type: %s", filterType)
-	routeStatus := GetRouteStatus(filterContext.Route)
-	status.SetRouteStatusCondition(routeStatus,
-		filterContext.ParentRef.routeParentStatusIdx,
-		filterContext.Route.GetGeneration(),
-		gwapiv1.RouteConditionAccepted,
-		metav1.ConditionFalse,
-		gwapiv1.RouteReasonUnsupportedValue,
-		errMsg,
-	)
+	updateRouteStatusForFilter(filterContext, errMsg)
 	filterContext.DirectResponse = &ir.CustomResponse{
 		StatusCode: ptr.To(uint32(500)),
 	}
 }
 
 func (t *Translator) processInvalidHTTPFilter(filterType string, filterContext *HTTPFiltersContext, err error) {
-	errMsg := fmt.Sprintf("Invalid filter %s: %v", filterType, err)
-	routeStatus := GetRouteStatus(filterContext.Route)
-	status.SetRouteStatusCondition(routeStatus,
-		filterContext.ParentRef.routeParentStatusIdx,
-		filterContext.Route.GetGeneration(),
-		gwapiv1.RouteConditionAccepted,
-		metav1.ConditionFalse,
-		gwapiv1.RouteReasonUnsupportedValue,
-		errMsg,
-	)
+	updateRouteStatusForFilter(
+		filterContext,
+		fmt.Sprintf("Invalid filter %s: %v", filterType, err))
 	filterContext.DirectResponse = &ir.CustomResponse{
 		StatusCode: ptr.To(uint32(500)),
 	}
diff --git a/internal/gatewayapi/resource/load.go b/internal/gatewayapi/resource/load.go
index 78f84d16d..755c17edb 100644
--- a/internal/gatewayapi/resource/load.go
+++ b/internal/gatewayapi/resource/load.go
@@ -20,6 +20,7 @@ import (
 	utilyaml "k8s.io/apimachinery/pkg/util/yaml"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
+	gwapiv1a3 "sigs.k8s.io/gateway-api/apis/v1alpha3"
 	"sigs.k8s.io/yaml"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
@@ -44,10 +45,7 @@ func LoadResourcesFromYAMLBytes(yamlBytes []byte, addMissingResources bool) (*Re
 
 // loadKubernetesYAMLToResources converts a Kubernetes YAML string into GatewayAPI Resources.
 // TODO: add support for kind:
-//   - EnvoyExtensionPolicy (gateway.envoyproxy.io/v1alpha1)
-//   - HTTPRouteFilter (gateway.envoyproxy.io/v1alpha1)
 //   - BackendLPPolicy (gateway.networking.k8s.io/v1alpha2)
-//   - BackendTLSPolicy (gateway.networking.k8s.io/v1alpha3)
 //   - ReferenceGrant (gateway.networking.k8s.io/v1alpha2)
 //   - TLSRoute (gateway.networking.k8s.io/v1alpha2)
 func loadKubernetesYAMLToResources(input []byte, addMissingResources bool) (*Resources, error) {
@@ -337,6 +335,32 @@ func loadKubernetesYAMLToResources(input []byte, addMissingResources bool) (*Res
 				Data: typedData.(map[string]string),
 			}
 			resources.ConfigMaps = append(resources.ConfigMaps, configMap)
+		case KindBackendTLSPolicy:
+			typedSpec := spec.Interface()
+			backendTLSPolicy := &gwapiv1a3.BackendTLSPolicy{
+				TypeMeta: metav1.TypeMeta{
+					Kind: KindBackendTLSPolicy,
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      name,
+					Namespace: namespace,
+				},
+				Spec: typedSpec.(gwapiv1a3.BackendTLSPolicySpec),
+			}
+			resources.BackendTLSPolicies = append(resources.BackendTLSPolicies, backendTLSPolicy)
+		case KindEnvoyExtensionPolicy:
+			typedSpec := spec.Interface()
+			envoyExtensionPolicy := &egv1a1.EnvoyExtensionPolicy{
+				TypeMeta: metav1.TypeMeta{
+					Kind: KindEnvoyExtensionPolicy,
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      name,
+					Namespace: namespace,
+				},
+				Spec: typedSpec.(egv1a1.EnvoyExtensionPolicySpec),
+			}
+			resources.EnvoyExtensionPolicies = append(resources.EnvoyExtensionPolicies, envoyExtensionPolicy)
 		}
 
 		return nil
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index 4259823c0..611fe1245 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -215,8 +215,7 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques
 					string(gwapiv1.GatewayClassReasonInvalidParameters),
 					msg)
 				r.resources.GatewayClassStatuses.Store(utils.NamespacedName(gc), &gc.Status)
-				r.log.Error(err, "failed to process parametersRef for gatewayclass", "name", managedGC.Name)
-				return reconcile.Result{}, err
+				return reconcile.Result{}, nil
 			}
 		}
 
diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go
index 7626ea32d..4a8d44395 100644
--- a/internal/provider/kubernetes/indexers.go
+++ b/internal/provider/kubernetes/indexers.go
@@ -120,6 +120,22 @@ func backendHTTPRouteIndexFunc(rawObj client.Object) []string {
 				)
 			}
 		}
+
+		// Check for a RequestMirror filter to also include the backendRef from that filter
+		for _, filter := range rule.Filters {
+			if filter.Type != gwapiv1.HTTPRouteFilterRequestMirror {
+				continue
+			}
+
+			mirrorBackendRef := filter.RequestMirror.BackendRef
+
+			backendRefs = append(backendRefs,
+				types.NamespacedName{
+					Namespace: gatewayapi.NamespaceDerefOr(mirrorBackendRef.Namespace, httproute.Namespace),
+					Name:      string(mirrorBackendRef.Name),
+				}.String(),
+			)
+		}
 	}
 	return backendRefs
 }
diff --git a/internal/wasm/cache.go b/internal/wasm/cache.go
index 785d8d370..7a045038f 100644
--- a/internal/wasm/cache.go
+++ b/internal/wasm/cache.go
@@ -67,11 +67,16 @@ type localFileCache struct {
 	// option sets for configuring the cache.
 	CacheOptions
 
+	// permissionCheckCache is the cache for permission check for private OCI images.
+	// The permission check is run periodically by a background goroutine and the result is cached.
+	permissionCheckCache *permissionCache
+
 	// logger
 	logger logging.Logger
 }
 
 func (c *localFileCache) Start(ctx context.Context) {
+	c.permissionCheckCache.Start(ctx)
 	go c.purge(ctx)
 }
 
@@ -131,9 +136,12 @@ type cacheEntry struct {
 func newLocalFileCache(options CacheOptions, logger logging.Logger) *localFileCache {
 	options = options.sanitize()
 	cache := &localFileCache{
-		httpFetcher:  NewHTTPFetcher(options.HTTPRequestTimeout, options.HTTPRequestMaxRetries, logger),
-		modules:      make(map[moduleKey]*cacheEntry),
-		checksums:    make(map[string]*checksumEntry),
+		httpFetcher: NewHTTPFetcher(options.HTTPRequestTimeout, options.HTTPRequestMaxRetries, logger),
+		modules:     make(map[moduleKey]*cacheEntry),
+		checksums:   make(map[string]*checksumEntry),
+		permissionCheckCache: newPermissionCache(
+			permissionCacheOptions{},
+			logger),
 		CacheOptions: options,
 		logger:       logger,
 	}
@@ -220,7 +228,7 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 	if ce != nil {
 		// We still need to check if the pull secret is correct if it is a private OCI image.
 		if u.Scheme == "oci" && ce.isPrivate {
-			if err = c.checkPermission(ctx, u, insecure, opts); err != nil {
+			if _, err := c.permissionCheckCache.IsAllowed(ctx, u, opts.PullSecret, insecure); err != nil {
 				return nil, err
 			}
 		}
@@ -250,7 +258,24 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 		if len(opts.PullSecret) > 0 {
 			isPrivate = true
 		}
-		if imageBinaryFetcher, dChecksum, err = c.prepareFetch(ctx, u, insecure, opts); err != nil {
+
+		imageBinaryFetcher, dChecksum, err = c.prepareFetch(ctx, u, insecure, opts.PullSecret)
+
+		if isPrivate {
+			e := &permissionCacheEntry{
+				image: u,
+				fetcherOption: &ImageFetcherOption{
+					Insecure:   insecure,
+					PullSecret: opts.PullSecret,
+				},
+				lastCheck:  time.Now(),
+				lastAccess: time.Now(),
+				checkError: err,
+			}
+			c.permissionCheckCache.Put(e)
+		}
+
+		if err != nil {
 			wasmRemoteFetchTotal.WithFailure(reasonManifestError).Increment()
 			return nil, fmt.Errorf("could not fetch Wasm OCI image: %w", err)
 		}
@@ -287,24 +312,16 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry,
 	return c.addEntry(key, b, isPrivate)
 }
 
-func (c *localFileCache) checkPermission(ctx context.Context, u *url.URL, insecure bool, opts GetOptions) error {
-	// Try to get the image metadata to check if the pull secret is correct.
-	if _, _, err := c.prepareFetch(ctx, u, insecure, opts); err != nil {
-		return fmt.Errorf("failed to login to private registry: %w", err)
-	}
-	return nil
-}
-
 // prepareFetch won't fetch the binary, but it will prepare the binaryFetcher and actualDigest.
 func (c *localFileCache) prepareFetch(
-	ctx context.Context, url *url.URL, insecure bool, opts GetOptions) (
+	ctx context.Context, url *url.URL, insecure bool, pullSecret []byte) (
 	binaryFetcher func() ([]byte, error), actualDigest string, err error,
 ) {
 	imgFetcherOps := ImageFetcherOption{
 		Insecure: insecure,
 	}
-	if len(opts.PullSecret) > 0 {
-		imgFetcherOps.PullSecret = opts.PullSecret
+	if len(pullSecret) > 0 {
+		imgFetcherOps.PullSecret = pullSecret
 	}
 	fetcher := NewImageFetcher(ctx, imgFetcherOps, c.logger)
 	if binaryFetcher, actualDigest, err = fetcher.PrepareFetch(url.Host + url.Path); err != nil {
diff --git a/internal/wasm/premissioncache.go b/internal/wasm/premissioncache.go
new file mode 100644
index 000000000..e680574ad
--- /dev/null
+++ b/internal/wasm/premissioncache.go
@@ -0,0 +1,266 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+// Copyright Istio Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wasm
+
+import (
+	"context"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"sync"
+	"time"
+
+	"github.com/avast/retry-go"
+	"github.com/google/go-containerregistry/pkg/v1/remote/transport"
+
+	"github.com/envoyproxy/gateway/internal/logging"
+)
+
+type permissionCacheOptions struct {
+	// checkInterval is the interval to recheck the permission for the cached permission entries.
+	checkInterval time.Duration
+
+	// permissionExpiry is the expiry time for permission cache entry.
+	// The permission cache entry will be updated by rechecking the OCI image permission against the pull secret.
+	permissionExpiry time.Duration
+
+	// cacheExpiry is the expiry time for the permission cache.
+	// The permission cache will be removed if it is not accessed for the specified expiry time.
+	// This is used to purge the cache.
+	cacheExpiry time.Duration
+}
+
+// sanitize validates and sets the default values for the permission cache options.
+func (o *permissionCacheOptions) sanitize() {
+	if o.checkInterval == 0 {
+		o.checkInterval = 5 * time.Minute
+	}
+	if o.permissionExpiry == 0 {
+		o.permissionExpiry = 1 * time.Hour
+	}
+	if o.cacheExpiry == 0 {
+		o.cacheExpiry = 24 * time.Hour
+	}
+}
+
+// permissionCache is a cache for permission check for private OCI images.
+// After a new permission is put into the cache, it will be checked periodically by a background goroutine.
+// It is used to avoid blocking the translator due to the permission check.
+type permissionCache struct {
+	sync.Mutex
+	permissionCacheOptions
+
+	cache  map[string]*permissionCacheEntry
+	logger logging.Logger
+}
+
+// permissionCacheEntry is an entry in the permission cache.
+type permissionCacheEntry struct {
+	// The oci image URL.
+	image *url.URL
+	// fetcherOption contains the pull secret for the image.
+	fetcherOption *ImageFetcherOption
+	// The last time the pull secret is checked against the image.
+	lastCheck time.Time
+	// The error returned by the OCI registry when checking the permission.
+	// If error is not nil, the permission is not allowed.
+	// If it's a permission error, it's represented by a transport.Error with 401 or 403 HTTP status code.
+	// But it's not necessarily a permission error, it could be other errors like network error, non-exist image, etc.
+	// In this case, the permission is also not allowed.
+	checkError error
+	// The last time the cache entry is accessed.
+	lastAccess time.Time
+}
+
+func (e *permissionCacheEntry) key() string {
+	return permissionCacheKey(e.image, e.fetcherOption.PullSecret)
+}
+
+// isPermissionExpired returns true if the permission check is older
+// than the specified expiry duration. If this is true, the entry
+// should be rechecked.
+func (e *permissionCacheEntry) isPermissionExpired(expiry time.Duration) bool {
+	return time.Now().After(e.lastCheck.Add(expiry))
+}
+
+// isCacheExpired returns true if the cache entry has not been accessed
+// for the specified expiry duration. If this is true, the entry
+// should be removed.
+func (e *permissionCacheEntry) isCacheExpired(expiry time.Duration) bool {
+	return time.Now().After(e.lastAccess.Add(expiry))
+}
+
+// permissionCacheKey generates a key for a permission cache entry.
+// The key is the hex encoded of concatenation of the image URL and the pull secret.
+func permissionCacheKey(image *url.URL, pullSecret []byte) string {
+	b := make([]byte, len(image.String())+len(pullSecret))
+	copy(b, image.String())
+	copy(b[len(image.String()):], pullSecret)
+	return hex.EncodeToString(b)
+}
+
+// newPermissionCache creates a new permission cache with a given TTL.
+func newPermissionCache(options permissionCacheOptions, logger logging.Logger) *permissionCache {
+	options.sanitize()
+	return &permissionCache{
+		cache:                  make(map[string]*permissionCacheEntry),
+		permissionCacheOptions: options,
+		logger:                 logger,
+	}
+}
+
+// checkAndUpdatePermission checks the permission of the image against the pull secret and updates the cache entry.
+func (p *permissionCache) checkAndUpdatePermission(ctx context.Context, e *permissionCacheEntry) error {
+	fetcher := NewImageFetcher(ctx, *e.fetcherOption, p.logger)
+	_, _, err := fetcher.PrepareFetch(e.image.Host + e.image.Path)
+	e.checkError = err
+	e.lastCheck = time.Now()
+	return err
+}
+
+// start starts a background goroutine to periodically check the permission for the cached permission entries.
+func (p *permissionCache) Start(ctx context.Context) {
+	go func() {
+		ticker := time.NewTicker(p.checkInterval)
+		defer ticker.Stop()
+		for {
+			select {
+			case <-ticker.C:
+				func() {
+					p.Lock()
+					defer p.Unlock()
+					for _, e := range p.cache {
+						if e.isCacheExpired(p.cacheExpiry) {
+							p.logger.Info("removing permission cache entry", "image", e.image.String())
+							delete(p.cache, e.key())
+							continue
+						}
+						if e.isPermissionExpired(p.permissionExpiry) {
+							const retryAttempts = 3
+							const retryDelay = 1 * time.Second
+							p.logger.Info("rechecking permission for image", "image", e.image.String())
+							err := retry.Do(
+								func() error {
+									err := p.checkAndUpdatePermission(ctx, e)
+									if err != nil && isRetriableError(err) {
+										p.logger.Error(
+											err,
+											"failed to check permission for image, will retry again",
+											"image",
+											e.image.String())
+										return err
+									}
+									return nil
+								},
+								retry.Attempts(retryAttempts),
+								retry.DelayType(retry.BackOffDelay),
+								retry.Delay(retryDelay),
+								retry.Context(ctx),
+							)
+							if err != nil {
+								p.logger.Error(
+									err,
+									fmt.Sprintf("failed to recheck permission for image after %d attempts", retryAttempts),
+									"image",
+									e.image.String())
+							}
+						}
+					}
+				}()
+			case <-ctx.Done():
+				return
+			}
+		}
+	}()
+}
+
+// isRetriableError checks if the error is retriable.
+// If the error is a permission error, it's not retriable. For example, 401 and 403 HTTP status code.
+func isRetriableError(err error) bool {
+	var terr *transport.Error
+	if errors.As(err, &terr) {
+		if terr.StatusCode == http.StatusUnauthorized || terr.StatusCode == http.StatusForbidden {
+			return false
+		}
+	}
+	return true
+}
+
+// put puts a new permission cache entry into the cache.
+func (p *permissionCache) Put(e *permissionCacheEntry) {
+	p.Lock()
+	defer p.Unlock()
+	e.lastAccess = time.Now()
+	e.lastCheck = time.Now()
+	p.cache[e.key()] = e
+}
+
+// IsAllowed checks if the given image is allowed to be accessed with the provided pull secret.
+// If the permission is not found in the cache, this method will block until the permission is checked and cached.
+// This blocking won't be too long as it's only for the first time permission check and won't retry. Subsequent
+// permission checks will be done in a background goroutine by the permission cache.
+//
+// If any error occurs, the permission is considered not allowed.
+// The error can be a permission error or other errors like network error, non-exist image, etc.
+func (p *permissionCache) IsAllowed(ctx context.Context, image *url.URL, pullSecret []byte, insecure bool) (bool, error) {
+	p.Lock()
+	defer p.Unlock()
+	key := permissionCacheKey(image, pullSecret)
+	if e, ok := p.cache[key]; ok {
+		e.lastAccess = time.Now()
+		return e.checkError == nil, e.checkError
+	}
+
+	e := &permissionCacheEntry{
+		image: image,
+		fetcherOption: &ImageFetcherOption{
+			Insecure:   insecure,
+			PullSecret: pullSecret,
+		},
+	}
+	// Do not retry if the permission check fails because we don't want to block the translator for too long.
+	// The permission check will be retried in the background goroutine by the permission cache.
+	if err := p.checkAndUpdatePermission(ctx, e); err != nil {
+		p.logger.Error(err, "failed to check permission for image", "image", e.image.String())
+	}
+	e.lastAccess = time.Now()
+	p.cache[key] = e
+	return e.checkError == nil, e.checkError
+}
+
+// getForTest is a test helper to get a permission cache entry from the cache.
+func (p *permissionCache) getForTest(key string) (permissionCacheEntry, bool) {
+	p.Lock()
+	defer p.Unlock()
+	entry, ok := p.cache[key]
+	if !ok {
+		return permissionCacheEntry{}, false
+	}
+	return *entry, true
+}
+
+// deleteForTest is a test helper to delete a permission cache entry from the cache.
+func (p *permissionCache) deleteForTest(key string) {
+	p.Lock()
+	defer p.Unlock()
+	delete(p.cache, key)
+}
diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go
index 991c8e342..304f22da4 100644
--- a/internal/xds/translator/accesslog.go
+++ b/internal/xds/translator/accesslog.go
@@ -336,10 +336,10 @@ func buildXdsAccessLog(al *ir.AccessLog, accessLogType ir.ProxyAccessLogType) ([
 			ResourceAttributes: convertToKeyValueList(otel.Resources, false),
 		}
 
-		if otel.Text == nil {
-			return nil, errors.New("otel.Text is nil")
+		var format string
+		if otel.Text != nil && *otel.Text != "" {
+			format = *otel.Text
 		}
-		format := *otel.Text
 
 		if format != "" {
 			al.Body = &otlpcommonv1.AnyValue{
@@ -349,9 +349,17 @@ func buildXdsAccessLog(al *ir.AccessLog, accessLogType ir.ProxyAccessLogType) ([
 			}
 		}
 
-		al.Attributes = convertToKeyValueList(otel.Attributes, true)
+		var attrs map[string]string
+		if len(otel.Attributes) != 0 {
+			attrs = otel.Attributes
+		} else if len(otel.Attributes) == 0 && format == "" {
+			// if there are no attributes and text format is unset, use the default EnvoyJSONLogFields
+			attrs = EnvoyJSONLogFields
+		}
+
+		al.Attributes = convertToKeyValueList(attrs, true)
+		formatters := accessLogOpenTelemetryFormatters(format, attrs)
 
-		formatters := accessLogOpenTelemetryFormatters(format, otel.Attributes)
 		if len(formatters) != 0 {
 			al.Formatters = formatters
 		}
diff --git a/release-notes/current.yaml b/release-notes/current.yaml
index 5f6cb7da7..3271a4f90 100644
--- a/release-notes/current.yaml
+++ b/release-notes/current.yaml
@@ -2,7 +2,6 @@ date: Pending
 
 # Changes that are expected to cause an incompatibility with previous versions, such as deletions or modifications to existing APIs.
 breaking changes: |
-  Add a breaking change here
 
 # Updates addressing vulnerabilities, security flaws, or compliance requirements.
 security updates: |
@@ -14,11 +13,9 @@ bug fixes: |
 
 # Enhancements that improve performance.
 performance improvements: |
-  Add a performance improvement here
 
 # Deprecated features or APIs.
 deprecations: |
-  Add a deprecation here
 
 # Other notable changes not covered by the above sections.
 Other changes: |
diff --git a/release-notes/v1.2.8.yaml b/release-notes/v1.2.8.yaml
new file mode 100644
index 000000000..e5a070f20
--- /dev/null
+++ b/release-notes/v1.2.8.yaml
@@ -0,0 +1,21 @@
+date: March 25, 2025
+
+security updates: |
+  Fixed vulnerability CVE-2025-30157, where local replies were incorrectly sent to the ext_proc server.
+  Included ratelimit security fixes related to the golang net/http package.
+
+bug fixes: |
+  Added support for BackendTLSPolicy and EnvoyExtensionPolicy parsing in Standalone mode.
+  Fixed endpoint updates when mirrored backend Pod IPs change.
+  Fix not logging an error and returning it in the K8s Reconcile method when a GatewayClass is not accepted.
+  Fixed validation of host header in RequestHeaderModifier filter.
+  Fixed an OpenTelemetry access log sink failure caused by an 'otel.Text is nil' error.
+# Enhancements that improve performance.
+performance improvements: |
+  Added a cache for the Wasm OCI image permission checks and check the pullSecrets against the OCI image registry in
+  a background goroutine.
+
+# Other notable changes not covered by the above sections.
+Other changes: |
+  Bumped envoy to v1.32.4.
+  Bumped ratelimit to 0141a24f.
diff --git a/site/content/en/news/releases/notes/v1.2.8.md b/site/content/en/news/releases/notes/v1.2.8.md
new file mode 100644
index 000000000..9301613d4
--- /dev/null
+++ b/site/content/en/news/releases/notes/v1.2.8.md
@@ -0,0 +1,26 @@
+---
+title: "v1.2.8"
+publishdate: 2025-03-25
+---
+
+Date: March 25, 2025
+
+## Security updates
+- Fixed vulnerability CVE-2025-30157, where local replies were incorrectly sent to the ext_proc server.
+- Included ratelimit security fixes related to the golang net/http package.
+
+## Bug fixes
+- Added support for BackendTLSPolicy and EnvoyExtensionPolicy parsing in Standalone mode.
+- Fixed endpoint updates when mirrored backend Pod IPs change.
+- Fix not logging an error and returning it in the K8s Reconcile method when a GatewayClass is not accepted.
+- Fixed validation of host header in RequestHeaderModifier filter.
+- Fixed an OpenTelemetry access log sink failure caused by an 'otel.Text is nil' error.
+
+## Performance improvements
+- Added a cache for the Wasm OCI image permission checks and check the pullSecrets against the OCI image registry in
+- a background goroutine.
+
+## Other changes
+- Bumped envoy to v1.32.4.
+- Bumped ratelimit to 0141a24f.
+


Test patch:
diff --git a/internal/cmd/egctl/testdata/translate/in/backend-endpoint.yaml b/internal/cmd/egctl/testdata/translate/in/backend-endpoint.yaml
index d2aa0f78f..f845c0941 100644
--- a/internal/cmd/egctl/testdata/translate/in/backend-endpoint.yaml
+++ b/internal/cmd/egctl/testdata/translate/in/backend-endpoint.yaml
@@ -44,3 +44,34 @@ spec:
     - ip:
         address: 0.0.0.0
         port: 3000
+---
+apiVersion: gateway.networking.k8s.io/v1alpha3
+kind: BackendTLSPolicy
+metadata:
+  name: example-com-tls-policy
+spec:
+  targetRefs:
+    - group: 'gateway.envoyproxy.io'
+      kind: Backend
+      name: backend
+  validation:
+    wellKnownCACertificates: "System"
+    hostname: www.example.com
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyExtensionPolicy
+metadata:
+  name: ext-proc-example
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: backend
+  extProc:
+    - backendRefs:
+        - name: grpc-ext-proc
+          port: 9002
+      processingMode:
+        request: {}
+        response:
+          body: Streamed
diff --git a/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml b/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml
index d3f3ed2c7..4ced5040f 100644
--- a/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml
@@ -1,3 +1,28 @@
+backendTLSPolicies:
+- kind: BackendTLSPolicy
+  metadata:
+    creationTimestamp: null
+    name: example-com-tls-policy
+    namespace: envoy-gateway-system
+  spec:
+    targetRefs:
+    - group: gateway.envoyproxy.io
+      kind: Backend
+      name: backend
+    validation:
+      hostname: www.example.com
+      wellKnownCACertificates: System
+  status:
+    ancestors:
+    - ancestorRef:
+        name: eg
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 backends:
 - kind: Backend
   metadata:
@@ -16,6 +41,41 @@ backends:
       reason: Accepted
       status: "True"
       type: Accepted
+envoyExtensionPolicies:
+- kind: EnvoyExtensionPolicy
+  metadata:
+    creationTimestamp: null
+    name: ext-proc-example
+    namespace: envoy-gateway-system
+  spec:
+    extProc:
+    - backendRefs:
+      - name: grpc-ext-proc
+        port: 9002
+      processingMode:
+        request: {}
+        response:
+          body: Streamed
+    targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: backend
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: eg
+        namespace: envoy-gateway-system
+      conditions:
+      - lastTransitionTime: null
+        message: |-
+          Wasm: wasm cache is not initialized
+          ExtProc: service envoy-gateway-system/grpc-ext-proc not found.
+        reason: Invalid
+        status: "False"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 gatewayClass:
   kind: GatewayClass
   metadata:
diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.in.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.in.yaml
index aaf5bad87..869f9122c 100644
--- a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.in.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.in.yaml
@@ -30,7 +30,7 @@ httpRoutes:
     rules:
     - matches:
       - path:
-          value: "/"
+          value: "/foo"
       backendRefs:
       - name: service-1
         port: 8080
@@ -42,7 +42,57 @@ httpRoutes:
             value: "some-value"
           - name: "good-header"
             value: "some-value"
-          add:
-          - name: "example/2"
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-2
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/bar"
+      backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - type: RequestHeaderModifier
+        requestHeaderModifier:
+          remove:
+          - "example/2"
+          set:
+          - name: "good-header"
+            value: "some-value"
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/baz"
+      backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - type: RequestHeaderModifier
+        requestHeaderModifier:
+          set:
+          - name: "host"
+            value: "example.com"
+          - name: "good-header"
             value: "some-value"
-
diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml
index 339e6a1f4..b1428fee3 100644
--- a/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-header-filter-invalid-headers.out.yaml
@@ -17,7 +17,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 1
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -60,9 +60,6 @@ httpRoutes:
         port: 8080
       filters:
       - requestHeaderModifier:
-          add:
-          - name: example/2
-            value: some-value
           set:
           - name: example:1
             value: some-value
@@ -71,13 +68,109 @@ httpRoutes:
         type: RequestHeaderModifier
       matches:
       - path:
-          value: /
+          value: /foo
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: 'Header: "example:1". The RequestHeaderModifier filter cannot set
+          the Host header or headers with a ''/'' or '':'' character in them. To modify
+          the Host header use the URLRewrite or the HTTPRouteFilter filter.'
+        reason: UnsupportedValue
+        status: "False"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-2
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - requestHeaderModifier:
+          remove:
+          - example/2
+          set:
+          - name: good-header
+            value: some-value
+        type: RequestHeaderModifier
+      matches:
+      - path:
+          value: /bar
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: 'Header: "example/2". The RequestHeaderModifier filter cannot remove
+          the Host header or headers with a ''/'' or '':'' character in them.'
+        reason: UnsupportedValue
+        status: "False"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - requestHeaderModifier:
+          set:
+          - name: host
+            value: example.com
+          - name: good-header
+            value: some-value
+        type: RequestHeaderModifier
+      matches:
+      - path:
+          value: /baz
   status:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: 'RequestHeaderModifier Filter cannot set headers with a ''/'' or
-          '':'' character in them. Header: ''example:1'''
+        message: 'Header: "host". The RequestHeaderModifier filter cannot set the
+          Host header or headers with a ''/'' or '':'' character in them. To modify
+          the Host header use the URLRewrite or the HTTPRouteFilter filter.'
         reason: UnsupportedValue
         status: "False"
         type: Accepted
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.in.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.in.yaml
index 6e1e57425..95da71440 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.in.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.in.yaml
@@ -30,7 +30,7 @@ httpRoutes:
     rules:
     - matches:
       - path:
-          value: "/"
+          value: "/foo"
       backendRefs:
       - name: service-1
         port: 8080
@@ -42,7 +42,57 @@ httpRoutes:
             value: "some-value"
           - name: "good-header"
             value: "some-value"
-          add:
-          - name: "example/2"
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-2
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/bar"
+      backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - type: ResponseHeaderModifier
+        responseHeaderModifier:
+          remove:
+          - "example/2"
+          set:
+          - name: "good-header"
+            value: "some-value"
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/baz"
+      backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - type: ResponseHeaderModifier
+        responseHeaderModifier:
+          set:
+          - name: "host"
+            value: "example.com"
+          - name: "good-header"
             value: "some-value"
-
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml
index 077e6e866..3fee996d4 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-invalid-headers.out.yaml
@@ -17,7 +17,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 1
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -60,9 +60,6 @@ httpRoutes:
         port: 8080
       filters:
       - responseHeaderModifier:
-          add:
-          - name: example/2
-            value: some-value
           set:
           - name: example:1
             value: some-value
@@ -71,13 +68,107 @@ httpRoutes:
         type: ResponseHeaderModifier
       matches:
       - path:
-          value: /
+          value: /foo
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: 'Header: "example:1". The ResponseHeaderModifier filter cannot set
+          the Host header or headers with a ''/'' or '':'' character in them.'
+        reason: UnsupportedValue
+        status: "False"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-2
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - responseHeaderModifier:
+          remove:
+          - example/2
+          set:
+          - name: good-header
+            value: some-value
+        type: ResponseHeaderModifier
+      matches:
+      - path:
+          value: /bar
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: 'Header: "example/2". The ResponseHeaderModifier filter cannot remove
+          the Host header or headers with a ''/'' or '':'' character in them.'
+        reason: UnsupportedValue
+        status: "False"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      filters:
+      - responseHeaderModifier:
+          set:
+          - name: host
+            value: example.com
+          - name: good-header
+            value: some-value
+        type: ResponseHeaderModifier
+      matches:
+      - path:
+          value: /baz
   status:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: 'ResponseHeaderModifier Filter cannot set headers with a ''/'' or
-          '':'' character in them. Header: ''example:1'''
+        message: 'Header: "host". The ResponseHeaderModifier filter cannot set the
+          Host header or headers with a ''/'' or '':'' character in them.'
         reason: UnsupportedValue
         status: "False"
         type: Accepted
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
index 33f61c29a..8d7a0f29f 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
@@ -56,7 +56,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
index aa3d4d2de..dca73a69b 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
index 27f1cfc34..efe53616a 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
@@ -198,7 +198,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
index b9dfe81c4..582c9b100 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
@@ -236,7 +236,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
index 31c087d6b..c197762b9 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
index 7cd8c3672..06027c7d6 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
index 64fdb9cd7..a2140535c 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
@@ -232,7 +232,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
index aa832e193..f89a85ecb 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
@@ -56,7 +56,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
index 0e7438971..3a8a914dd 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
@@ -229,7 +229,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
index 59a396661..a4d5e375d 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
index c6c2e95bc..9e1eea608 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
index f571a656e..e9b362a24 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
index 6669ca1c2..981c708ae 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
@@ -227,7 +227,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
index 8a48e1633..02ebacb53 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
@@ -59,7 +59,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
index 9080ce0b8..4b53d5ad4 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
@@ -60,7 +60,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
index 534424253..2cb26dd6d 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
index 41ec060e1..13b681fe9 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
@@ -202,7 +202,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml
index 172348b98..1b5babaab 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml
@@ -232,7 +232,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml
index a819b7f59..b6acb282d 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml
@@ -232,7 +232,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
index 9016b8e26..f6dea0d39 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
@@ -240,7 +240,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
index 5a2e6b3e2..55b2f4ead 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
index 659dcbb60..8f8ebcd8a 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
index d54be4c52..ba8a9747a 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
@@ -236,7 +236,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
index 946f572e9..441533d25 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
@@ -60,7 +60,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
index 44d76b56d..73c365cff 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
index c48ce3a76..2fd6becd6 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
@@ -233,7 +233,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
index db91ba2dc..ec8e1ead8 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
index 493dcf36d..29f90e0b5 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
index 2e590d605..7829bba90 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
index c2bb6a1bb..d11da975d 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
@@ -231,7 +231,7 @@ spec:
             fieldRef:
               apiVersion: v1
               fieldPath: metadata.name
-        image: docker.io/envoyproxy/envoy:distroless-v1.32.3
+        image: docker.io/envoyproxy/envoy:distroless-v1.32.4
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
index 84af681d9..6af6849e3 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
@@ -86,7 +86,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
index de4c83da5..017b8154e 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
@@ -76,7 +76,7 @@ spec:
           value: tcp
         - name: REDIS_URL
           value: redis.redis.svc:6379
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
index 6971dc186..b901fc37f 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
@@ -101,7 +101,7 @@ spec:
           value: "0.6"
         - name: OTEL_EXPORTER_OTLP_ENDPOINT
           value: http://trace-collector.envoy-gateway-system.svc.cluster.local:4317
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
index b78ec434d..386b108a3 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
@@ -101,7 +101,7 @@ spec:
           value: "1.0"
         - name: OTEL_EXPORTER_OTLP_ENDPOINT
           value: http://trace-collector.envoy-gateway-system.svc.cluster.local:4318
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-annotations.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-annotations.yaml
index 945e60e67..97ceb278f 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-annotations.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-annotations.yaml
@@ -88,7 +88,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-labels.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-labels.yaml
index 9cd149a10..69a0153b6 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-labels.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/merge-labels.yaml
@@ -88,7 +88,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
index 21b6e9fbf..c93d833bd 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
@@ -86,7 +86,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
index 4700c613c..8d979a863 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
@@ -86,7 +86,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
index c784904d2..530bedf02 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
@@ -86,7 +86,7 @@ spec:
           value: :19001
         - name: PROMETHEUS_MAPPER_YAML
           value: /etc/statsd-exporter/conf.yaml
-        image: docker.io/envoyproxy/ratelimit:ae4cee11
+        image: docker.io/envoyproxy/ratelimit:0141a24f
         imagePullPolicy: IfNotPresent
         name: envoy-ratelimit
         ports:
diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go
index 8ff155f46..073de5a58 100644
--- a/internal/provider/kubernetes/predicates_test.go
+++ b/internal/provider/kubernetes/predicates_test.go
@@ -418,6 +418,52 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) {
 			endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "service"),
 			expect:        true,
 		},
+		{
+			name: "mirrored backend route exists",
+			configs: []client.Object{
+				test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil),
+				sampleGateway,
+				&gwapiv1.HTTPRoute{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "httproute-test",
+					},
+					Spec: gwapiv1.HTTPRouteSpec{
+						CommonRouteSpec: gwapiv1.CommonRouteSpec{
+							ParentRefs: []gwapiv1.ParentReference{
+								{Name: gwapiv1.ObjectName("scheduled-status-test")},
+							},
+						},
+						Rules: []gwapiv1.HTTPRouteRule{
+							{
+								BackendRefs: []gwapiv1.HTTPBackendRef{
+									{
+										BackendRef: gwapiv1.BackendRef{
+											BackendObjectReference: gwapiv1.BackendObjectReference{
+												Name: gwapiv1.ObjectName("service"),
+												Port: ptr.To(gwapiv1.PortNumber(80)),
+											},
+										},
+									},
+								},
+								Filters: []gwapiv1.HTTPRouteFilter{
+									{
+										Type: gwapiv1.HTTPRouteFilterRequestMirror,
+										RequestMirror: &gwapiv1.HTTPRequestMirrorFilter{
+											BackendRef: gwapiv1.BackendObjectReference{
+												Name: "mirror-service",
+												Port: ptr.To(gwapiv1.PortNumber(80)),
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "mirror-service"),
+			expect:        true,
+		},
 	}
 
 	// Create the reconciler.
diff --git a/internal/wasm/premissioncache_test.go b/internal/wasm/premissioncache_test.go
new file mode 100644
index 000000000..2fdb95ff1
--- /dev/null
+++ b/internal/wasm/premissioncache_test.go
@@ -0,0 +1,282 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+// Copyright Istio Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wasm
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"sync"
+	"testing"
+	"time"
+
+	"github.com/google/go-containerregistry/pkg/registry"
+	"github.com/stretchr/testify/require"
+
+	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
+	"github.com/envoyproxy/gateway/internal/logging"
+)
+
+func TestPermissionCache(t *testing.T) {
+	lock := sync.Mutex{}
+	// Flag to control whether the permission check should fail.
+	failPermissionCheck := false
+
+	// Set up a fake registry for OCI images.
+	reg := registry.New()
+	tos := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		lock.Lock()
+		defer lock.Unlock()
+		if failPermissionCheck {
+			http.Error(w, "permission denied", http.StatusUnauthorized)
+			return
+		}
+		reg.ServeHTTP(w, r)
+	}))
+	defer tos.Close()
+	ou, err := url.Parse(tos.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, _ = setupOCIRegistry(t, ou.Host)
+	ociURLWithTag := fmt.Sprintf("oci://%s/test/valid/docker:v0.1.0", ou.Host)
+	ociURLWithLatestTag := fmt.Sprintf("oci://%s/test/valid/docker:latest", ou.Host)
+	image, _ := url.Parse(ociURLWithTag)
+	latestImage, _ := url.Parse(ociURLWithLatestTag)
+	secret := []byte("")
+
+	t.Run("Cached permission should be updated", func(t *testing.T) {
+		lock.Lock()
+		failPermissionCheck = false
+		lock.Unlock()
+
+		ctx := context.Background()
+		defer ctx.Done()
+		cache, entry := setupTestPermissionCache(
+			permissionCacheOptions{
+				checkInterval:    10 * time.Nanosecond,
+				permissionExpiry: 10 * time.Nanosecond,
+			},
+			image,
+			latestImage,
+			secret)
+		cache.Start(ctx)
+
+		lastAccessTime := entry.lastAccess
+		lastCheckTime := entry.lastCheck
+
+		time.Sleep(1 * time.Millisecond)
+		allowed, err := cache.IsAllowed(context.Background(), image, secret, true)
+		require.True(
+			t,
+			allowed,
+			"permission should be rechecked and allowed after permission expired")
+		require.NoError(
+			t,
+			err,
+			"permission should be rechecked and allowed after permission expired")
+
+		entry, ok := cache.getForTest(entry.key())
+		require.True(t, ok, "cache entry should exist")
+		require.True(t, entry.lastAccess.After(lastAccessTime), "last access time should be updated")
+		require.True(t, entry.lastCheck.After(lastCheckTime), "last check time should be updated")
+	})
+
+	t.Run("Cached permission failed after recheck", func(t *testing.T) {
+		lock.Lock()
+		failPermissionCheck = true
+		lock.Unlock()
+
+		ctx := context.Background()
+		defer ctx.Done()
+		cache, entry := setupTestPermissionCache(
+			permissionCacheOptions{
+				checkInterval:    10 * time.Nanosecond,
+				permissionExpiry: 10 * time.Nanosecond,
+			},
+			image,
+			latestImage,
+			secret)
+		cache.Start(ctx)
+
+		lastAccessTime := entry.lastAccess
+		lastCheckTime := entry.lastCheck
+
+		time.Sleep(1 * time.Millisecond)
+		allowed, err := cache.IsAllowed(context.Background(), image, secret, true)
+		require.False(t, isRetriableError(err), "permission check error should not be retriable")
+		require.False(
+			t,
+			allowed,
+			"permission should be rechecked and denied after permission expired and secret is invalid")
+		require.Error(
+			t,
+			err,
+			"permission should be rechecked and denied after permission expired and secret is invalid")
+
+		entry, ok := cache.getForTest(entry.key())
+		require.True(t, ok, "cache entry should exist")
+		require.True(t, entry.lastAccess.After(lastAccessTime), "last access time should be updated")
+		require.True(t, entry.lastCheck.After(lastCheckTime), "last check time should be updated")
+	})
+
+	t.Run("Cached permission should be removed after expiry", func(t *testing.T) {
+		lock.Lock()
+		failPermissionCheck = false
+		lock.Unlock()
+
+		ctx := context.Background()
+		defer ctx.Done()
+		cache, entry := setupTestPermissionCache(
+			permissionCacheOptions{
+				checkInterval: 10 * time.Nanosecond,
+				cacheExpiry:   10 * time.Nanosecond,
+			},
+			image,
+			latestImage,
+			secret)
+		cache.Start(ctx)
+
+		lastAccessTime := entry.lastAccess
+		lastCheckTime := entry.lastCheck
+
+		time.Sleep(1 * time.Millisecond)
+		key := entry.key()
+		entry, ok := cache.getForTest(key)
+		require.False(t, ok, "cache entry should be removed after expiry")
+		allowed, err := cache.IsAllowed(context.Background(), image, secret, true)
+		require.True(t,
+			allowed,
+			"permission should be rechecked and allowed after cache removed")
+		require.NoError(t,
+			err,
+			"permission should be rechecked and allowed after cache removed")
+		entry, ok = cache.getForTest(key)
+		require.True(t, ok, "expired entry should be added after recheck")
+		require.True(t, entry.lastAccess.After(lastAccessTime), "last access time should be updated")
+		require.True(t, entry.lastCheck.After(lastCheckTime), "last check time should be updated")
+	})
+
+	t.Run("Non-exist permission should be checked and cached after first access for allowed permission", func(t *testing.T) {
+		lock.Lock()
+		failPermissionCheck = false
+		lock.Unlock()
+
+		ctx := context.Background()
+		defer ctx.Done()
+		cache, entry := setupTestPermissionCache(
+			permissionCacheOptions{
+				checkInterval: 10 * time.Nanosecond,
+			},
+			image,
+			latestImage,
+			secret)
+		key := entry.key()
+		// remove the cache entry
+		cache.deleteForTest(key)
+		cache.Start(ctx)
+
+		_, ok := cache.getForTest(key)
+		require.False(t, ok, "cache entry should not exist before access")
+
+		now := time.Now()
+		allowed, err := cache.IsAllowed(context.Background(), image, secret, true)
+		require.True(t,
+			allowed,
+			"non-exist permission should be checked and allowed at first access")
+		require.NoError(t,
+			err,
+			"non-exist permission should be checked and allowed at first access")
+
+		entry, ok = cache.getForTest(key)
+		require.True(t, ok, "non-exist permission should be added to the cache after first access ")
+		require.True(t, entry.lastAccess.After(now), "last access time should be updated after first access")
+		require.True(t, entry.lastCheck.After(now), "last check time should be updated after first access")
+	})
+
+	t.Run("Non-exist permission should be checked and cached after first access for denied permission", func(t *testing.T) {
+		lock.Lock()
+		failPermissionCheck = true
+		lock.Unlock()
+
+		ctx := context.Background()
+		defer ctx.Done()
+		cache, entry := setupTestPermissionCache(
+			permissionCacheOptions{
+				checkInterval: 10 * time.Nanosecond,
+			},
+			image,
+			latestImage,
+			secret)
+		key := entry.key()
+		// remove the cache entry
+		cache.deleteForTest(key)
+		cache.Start(ctx)
+
+		_, ok := cache.getForTest(key)
+		require.False(t, ok, "cache entry should not exist before access")
+
+		now := time.Now()
+		allowed, err := cache.IsAllowed(context.Background(), image, secret, true)
+		require.False(t,
+			allowed,
+			"non-exist permission should be checked and denied at first access if secret is invalid")
+		require.Error(t,
+			err,
+			"non-exist permission should be checked and denied at first access if secret is invalid")
+
+		entry, ok = cache.getForTest(key)
+		require.True(t, ok, "non-exist permission should be added to the cache after first access ")
+		require.True(t, entry.lastAccess.After(now), "last access time should be updated after first access")
+		require.True(t, entry.lastCheck.After(now), "last check time should be updated after first access")
+	})
+}
+
+// setupTestPermissionCache sets up a permission cache for testing.
+func setupTestPermissionCache(options permissionCacheOptions, image, latestImage *url.URL, secret []byte) (*permissionCache, permissionCacheEntry) {
+	// Setup the permission cache.
+	cache := newPermissionCache(
+		options,
+		logging.DefaultLogger(egv1a1.LogLevelInfo))
+
+	entry := &permissionCacheEntry{
+		image: image,
+		fetcherOption: &ImageFetcherOption{
+			PullSecret: secret,
+			Insecure:   true,
+		},
+		lastCheck: time.Now(),
+	}
+	cache.Put(entry)
+
+	// Add one more entry for the latest image to test the cache can handle multiple entries correctly.
+	cache.Put(&permissionCacheEntry{
+		image: latestImage,
+		fetcherOption: &ImageFetcherOption{
+			PullSecret: secret,
+			Insecure:   true,
+		},
+		lastCheck: time.Now(),
+	})
+
+	return cache, *entry
+}
diff --git a/site/content/en/latest/install/gateway-helm-api.md b/site/content/en/latest/install/gateway-helm-api.md
index 1035fdea5..b32bcda77 100644
--- a/site/content/en/latest/install/gateway-helm-api.md
+++ b/site/content/en/latest/install/gateway-helm-api.md
@@ -66,7 +66,7 @@ The Helm chart for Envoy Gateway
 | global.images.envoyGateway.image | string | `nil` |  |
 | global.images.envoyGateway.pullPolicy | string | `nil` |  |
 | global.images.envoyGateway.pullSecrets | list | `[]` |  |
-| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:ae4cee11"` |  |
+| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:0141a24f"` |  |
 | global.images.ratelimit.pullPolicy | string | `"IfNotPresent"` |  |
 | global.images.ratelimit.pullSecrets | list | `[]` |  |
 | kubernetesClusterDomain | string | `"cluster.local"` |  |
diff --git a/site/content/zh/latest/install/gateway-helm-api.md b/site/content/zh/latest/install/gateway-helm-api.md
index 1035fdea5..b32bcda77 100644
--- a/site/content/zh/latest/install/gateway-helm-api.md
+++ b/site/content/zh/latest/install/gateway-helm-api.md
@@ -66,7 +66,7 @@ The Helm chart for Envoy Gateway
 | global.images.envoyGateway.image | string | `nil` |  |
 | global.images.envoyGateway.pullPolicy | string | `nil` |  |
 | global.images.envoyGateway.pullSecrets | list | `[]` |  |
-| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:ae4cee11"` |  |
+| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:0141a24f"` |  |
 | global.images.ratelimit.pullPolicy | string | `"IfNotPresent"` |  |
 | global.images.ratelimit.pullSecrets | list | `[]` |  |
 | kubernetesClusterDomain | string | `"cluster.local"` |  |
diff --git a/test/e2e/testdata/accesslog-otel-default.yaml b/test/e2e/testdata/accesslog-otel-default.yaml
new file mode 100644
index 000000000..764e8e02e
--- /dev/null
+++ b/test/e2e/testdata/accesslog-otel-default.yaml
@@ -0,0 +1,61 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: Gateway
+metadata:
+  name: accesslog-gtw
+  namespace: gateway-conformance-infra
+spec:
+  gatewayClassName: {GATEWAY_CLASS_NAME}
+  listeners:
+    - name: http
+      port: 80
+      protocol: HTTP
+      allowedRoutes:
+        namespaces:
+          from: Same
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: accesslog-otel
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: accesslog-otel
+  namespace: gateway-conformance-infra
+spec:
+  ipFamily: IPv4
+  telemetry:
+    accessLog:
+      settings:
+        - matches:
+            - "'x-envoy-logged' in request.headers"
+          sinks:
+            - type: OpenTelemetry
+              openTelemetry:
+                backendRefs:
+                  - name: otel-collector
+                    namespace: monitoring
+                    port: 4317
+                resources:
+                  k8s.cluster.name: "envoy-gateway"
+  shutdown:
+    drainTimeout: 5s
+    minDrainDuration: 1s
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: accesslog-otel
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: accesslog-gtw
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /otel
+      backendRefs:
+        - name: infra-backend-v2
+          port: 8080
diff --git a/test/e2e/testdata/accesslog-otel-json.yaml b/test/e2e/testdata/accesslog-otel-json.yaml
new file mode 100644
index 000000000..219315112
--- /dev/null
+++ b/test/e2e/testdata/accesslog-otel-json.yaml
@@ -0,0 +1,79 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: Gateway
+metadata:
+  name: accesslog-gtw
+  namespace: gateway-conformance-infra
+spec:
+  gatewayClassName: {GATEWAY_CLASS_NAME}
+  listeners:
+    - name: http
+      port: 80
+      protocol: HTTP
+      allowedRoutes:
+        namespaces:
+          from: Same
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: accesslog-otel
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: accesslog-otel
+  namespace: gateway-conformance-infra
+spec:
+  ipFamily: IPv4
+  telemetry:
+    accessLog:
+      settings:
+        - format:
+            type: JSON
+            json:
+              time: "%START_TIME%"
+              method: "%REQ(:METHOD)%"
+              metadata: "%METADATA(ROUTE:envoy-gateway:resources)%"
+              x-envoy-original-path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
+              protocol: "%PROTOCOL%"
+              responseCode: "%RESPONSE_CODE%"
+              responseFlags: "%RESPONSE_FLAGS%"
+              bytesReceived: "%BYTES_RECEIVED%"
+              bytesSent: "%BYTES_SENT%"
+              duration: "%DURATION%"
+              x-forwarded-for: "%REQ(X-FORWARDED-FOR)%"
+              user-agent: "%REQ(USER-AGENT)%"
+              x-request-id: "%REQ(X-REQUEST-ID)%"
+              authority: "%REQ(:AUTHORITY)%"
+              upstreamHost: "%UPSTREAM_HOST%"
+          matches:
+            - "'x-envoy-logged' in request.headers"
+          sinks:
+            - type: OpenTelemetry
+              openTelemetry:
+                backendRefs:
+                  - name: otel-collector
+                    namespace: monitoring
+                    port: 4317
+                resources:
+                  k8s.cluster.name: "envoy-gateway"
+  shutdown:
+    drainTimeout: 5s
+    minDrainDuration: 1s
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: accesslog-otel
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: accesslog-gtw
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /otel
+      backendRefs:
+        - name: infra-backend-v2
+          port: 8080
diff --git a/test/e2e/tests/accesslog.go b/test/e2e/tests/accesslog.go
index 4edc12f7c..a9a7ca26a 100644
--- a/test/e2e/tests/accesslog.go
+++ b/test/e2e/tests/accesslog.go
@@ -21,7 +21,7 @@ import (
 )
 
 func init() {
-	ConformanceTests = append(ConformanceTests, FileAccessLogTest, OpenTelemetryTest, ALSTest)
+	ConformanceTests = append(ConformanceTests, FileAccessLogTest, OpenTelemetryTestText, OpenTelemetryTestJSON, ALSTest, OpenTelemetryTestJSONAsDefault)
 }
 
 var FileAccessLogTest = suite.ConformanceTest{
@@ -116,9 +116,9 @@ var FileAccessLogTest = suite.ConformanceTest{
 	},
 }
 
-var OpenTelemetryTest = suite.ConformanceTest{
-	ShortName:   "OpenTelemetryAccessLog",
-	Description: "Make sure OpenTelemetry access log is working",
+var OpenTelemetryTestText = suite.ConformanceTest{
+	ShortName:   "OpenTelemetryTextAccessLog",
+	Description: "Make sure OpenTelemetry text access log is working",
 	Manifests:   []string{"testdata/accesslog-otel.yaml"},
 	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
 		labels := map[string]string{
@@ -174,6 +174,112 @@ var OpenTelemetryTest = suite.ConformanceTest{
 	},
 }
 
+var OpenTelemetryTestJSONAsDefault = suite.ConformanceTest{
+	ShortName:   "OpenTelemetryAccessLogJSONAsDefault",
+	Description: "Make sure OpenTelemetry JSON access log is working as default when no format or type is specified",
+	Manifests:   []string{"testdata/accesslog-otel-default.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		labels := map[string]string{
+			"k8s_namespace_name": "envoy-gateway-system",
+			"exporter":           "OTLP",
+		}
+
+		ns := "gateway-conformance-infra"
+		routeNN := types.NamespacedName{Name: "accesslog-otel", Namespace: ns}
+		gwNN := types.NamespacedName{Name: "accesslog-gtw", Namespace: ns}
+		gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+		t.Run("Positive", func(t *testing.T) {
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/otel",
+					Headers: map[string]string{
+						"x-envoy-logged": "1",
+					},
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			runLogTest(t, suite, gwAddr, expectedResponse, labels, "", 1)
+		})
+
+		t.Run("Negative", func(t *testing.T) {
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/otel",
+					// envoy will not log this request without the header x-envoy-logged
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			runLogTest(t, suite, gwAddr, expectedResponse, labels, "", 0)
+		})
+	},
+}
+
+var OpenTelemetryTestJSON = suite.ConformanceTest{
+	ShortName:   "OpenTelemetryAccessLogJSON",
+	Description: "Make sure OpenTelemetry JSON access log is working with custom JSON attributes",
+	Manifests:   []string{"testdata/accesslog-otel-json.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		labels := map[string]string{
+			"k8s_namespace_name": "envoy-gateway-system",
+			"exporter":           "OTLP",
+		}
+
+		ns := "gateway-conformance-infra"
+		routeNN := types.NamespacedName{Name: "accesslog-otel", Namespace: ns}
+		gwNN := types.NamespacedName{Name: "accesslog-gtw", Namespace: ns}
+		gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+		t.Run("Positive", func(t *testing.T) {
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/otel",
+					Headers: map[string]string{
+						"x-envoy-logged": "1",
+					},
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			runLogTest(t, suite, gwAddr, expectedResponse, labels, "", 1)
+		})
+
+		t.Run("Negative", func(t *testing.T) {
+			expectedResponse := httputils.ExpectedResponse{
+				Request: httputils.Request{
+					Path: "/otel",
+					// envoy will not log this request without the header x-envoy-logged
+				},
+				Response: httputils.Response{
+					StatusCode: 200,
+				},
+				Namespace: ns,
+			}
+			// make sure listener is ready
+			httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+
+			runLogTest(t, suite, gwAddr, expectedResponse, labels, "", 0)
+		})
+	},
+}
+
 var ALSTest = suite.ConformanceTest{
 	ShortName:   "ALS",
 	Description: "Make sure ALS access log is working",
diff --git a/test/e2e/tests/wasm_oci.go b/test/e2e/tests/wasm_oci.go
index 514ab9373..f9f74cec2 100644
--- a/test/e2e/tests/wasm_oci.go
+++ b/test/e2e/tests/wasm_oci.go
@@ -197,7 +197,7 @@ var OCIWasmTest = suite.ConformanceTest{
 				t, suite.Client,
 				types.NamespacedName{Name: testEEP, Namespace: testNS},
 				suite.ControllerName,
-				ancestorRef, "failed to login to private registry")
+				ancestorRef, "UNAUTHORIZED: authentication required")
 		})
 
 		// Verify that the wasm module can't be loaded if the password is incorrect
@@ -232,7 +232,7 @@ var OCIWasmTest = suite.ConformanceTest{
 				t, suite.Client,
 				types.NamespacedName{Name: testEEP, Namespace: testNS},
 				suite.ControllerName,
-				ancestorRef, "failed to login to private registry")
+				ancestorRef, "UNAUTHORIZED: authentication required")
 		})
 	},
 }
diff --git a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml
index e4541b8cd..4bba4e1f5 100644
--- a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml
+++ b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml
index 210af77b5..243833482 100644
--- a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml
+++ b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml
@@ -52,7 +52,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/default-config.out.yaml b/test/helm/gateway-helm/default-config.out.yaml
index ebd8d9db5..dffdc90ac 100644
--- a/test/helm/gateway-helm/default-config.out.yaml
+++ b/test/helm/gateway-helm/default-config.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/deployment-custom-topology.out.yaml b/test/helm/gateway-helm/deployment-custom-topology.out.yaml
index c78eb3d24..7d580d91f 100644
--- a/test/helm/gateway-helm/deployment-custom-topology.out.yaml
+++ b/test/helm/gateway-helm/deployment-custom-topology.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/deployment-images-config.out.yaml b/test/helm/gateway-helm/deployment-images-config.out.yaml
index f09e89d19..c7d4d18e2 100644
--- a/test/helm/gateway-helm/deployment-images-config.out.yaml
+++ b/test/helm/gateway-helm/deployment-images-config.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/deployment-priorityclass.out.yaml b/test/helm/gateway-helm/deployment-priorityclass.out.yaml
index 9063afac9..7d3ed99c6 100644
--- a/test/helm/gateway-helm/deployment-priorityclass.out.yaml
+++ b/test/helm/gateway-helm/deployment-priorityclass.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/deployment-securitycontext.out.yaml b/test/helm/gateway-helm/deployment-securitycontext.out.yaml
index cf23490af..f0a5dff52 100644
--- a/test/helm/gateway-helm/deployment-securitycontext.out.yaml
+++ b/test/helm/gateway-helm/deployment-securitycontext.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value:
diff --git a/test/helm/gateway-helm/service-annotations.out.yaml b/test/helm/gateway-helm/service-annotations.out.yaml
index 83ea20ab6..e15f84270 100644
--- a/test/helm/gateway-helm/service-annotations.out.yaml
+++ b/test/helm/gateway-helm/service-annotations.out.yaml
@@ -37,7 +37,7 @@ data:
       kubernetes:
         rateLimitDeployment:
           container:
-            image: docker.io/envoyproxy/ratelimit:ae4cee11
+            image: docker.io/envoyproxy/ratelimit:0141a24f
           patch:
             type: StrategicMerge
             value: