diff --git a/README.md b/README.md index 028af495..35e87c13 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ These environment variables offer controls for the bootstrap config generation f |`APPMESH_SET_TRACING_DECISION` | |Controls whether Envoy modifies the `x-request-id` header appearing in a request from a client |TRUE | |`ENVOY_NO_EXTENSION_LOOKUP_BY_NAME` | |Controls whether Envoy needs type URL to lookup extensions regardless of the name field. If the type URL is missing it will reject (NACK) the configuration |true | |`ENVOY_ENABLE_TCP_POOL_IDLE_TIMEOUT` | |Controls whether the `idle_timeout` protocol options feature is enabled for TCP upstreams. If not configured the default `idle_timeout` is 10 minutes. Set this environment variable to `false` to disable `idle_timeout` option. |true | +|`ENVOY_SANITIZE_ORIGINAL_PATH` | |Controls whether to sanitize `x-envoy-original-path` coming from an untrusted users. Set this environment variable to `false` to not sanitize `x-envoy-original-path` header coming from untrusted users. |true | |`APPMESH_SDS_SOCKET_PATH` |/path/to/socket |Unix Domain Socket for SDS Based TLS. | | |`APPMESH_PREVIEW` |<0 | 1> |Enables the App Mesh Preview Endpoint | | |`APPMESH_DUALSTACK_ENDPOINT` |<0 | 1> |Enables the App Mesh Dual-Stack Endpoint | | diff --git a/agent/envoy_bootstrap/envoy_bootstrap.go b/agent/envoy_bootstrap/envoy_bootstrap.go index ede8c076..3b90a713 100644 --- a/agent/envoy_bootstrap/envoy_bootstrap.go +++ b/agent/envoy_bootstrap/envoy_bootstrap.go @@ -111,6 +111,14 @@ func getRuntimeConfigLayer0() (map[string]interface{}, error) { } setTcpPoolIdleTimeout, err := env.TruthyOrElse("ENVOY_ENABLE_TCP_POOL_IDLE_TIMEOUT", true) + if err != nil { + return nil, err + } + + setSanitizeOriginalPath, err := env.TruthyOrElse("ENVOY_SANITIZE_ORIGINAL_PATH", true) + if err != nil { + return nil, err + } return map[string]interface{}{ // Allow all deprecated features to be enabled by Envoy. This prevents warnings or hard errors when @@ -137,6 +145,16 @@ func getRuntimeConfigLayer0() (map[string]interface{}, error) { // idle timeout feature for TCP upstream. // See https://www.envoyproxy.io/docs/envoy/v1.25.0/version_history/v1.25/v1.25.0#minor-behavior-changes "envoy.reloadable_features.tcp_pool_idle_timeout": setTcpPoolIdleTimeout, + + // Default is set to true. + // Envoy fixed a bug where `x-envoy-original-path` was not being sanitized when sent from untrusted users. + // This bug fix was done to address a CVE https://nvd.nist.gov/vuln/detail/CVE-2023-27487 + // https://github.com/envoyproxy/envoy/commit/4a8cc2eabaf3d1300f84fe8df333064bfe2fafcd + // See https://www.envoyproxy.io/docs/envoy/v1.25.4/version_history/v1.25/v1.25.4#bug-fixes + // This introduced a behavioral change where `x-envoy-original-path` won't be propagated leading to potential change + // in request path logged in traces and access logs. So in case user wants to keep the original behavior because + // CVE is not applicable in their case then they can set Envoy env variable ENVOY_SANITIZE_ORIGINAL_PATH to `false`. + "envoy.reloadable_features.sanitize_original_path": setSanitizeOriginalPath, }, nil } diff --git a/agent/envoy_bootstrap/envoy_bootstrap_test.go b/agent/envoy_bootstrap/envoy_bootstrap_test.go index 39728add..83b2e3d2 100644 --- a/agent/envoy_bootstrap/envoy_bootstrap_test.go +++ b/agent/envoy_bootstrap/envoy_bootstrap_test.go @@ -607,6 +607,7 @@ layers: envoy.reloadable_features.http_set_tracing_decision_in_request_id: true envoy.reloadable_features.no_extension_lookup_by_name: true envoy.reloadable_features.tcp_pool_idle_timeout: true + envoy.reloadable_features.sanitize_original_path: true re2.max_program_size.error_level: 1000 - name: "admin_layer" adminLayer: {} @@ -629,6 +630,7 @@ layers: envoy.reloadable_features.http_set_tracing_decision_in_request_id: false envoy.reloadable_features.no_extension_lookup_by_name: true envoy.reloadable_features.tcp_pool_idle_timeout: true + envoy.reloadable_features.sanitize_original_path: true re2.max_program_size.error_level: 1000 - name: "admin_layer" adminLayer: {} @@ -651,6 +653,7 @@ layers: envoy.reloadable_features.http_set_tracing_decision_in_request_id: true envoy.reloadable_features.no_extension_lookup_by_name: false envoy.reloadable_features.tcp_pool_idle_timeout: true + envoy.reloadable_features.sanitize_original_path: true re2.max_program_size.error_level: 1000 - name: "admin_layer" adminLayer: {} @@ -673,6 +676,30 @@ layers: envoy.reloadable_features.http_set_tracing_decision_in_request_id: true envoy.reloadable_features.no_extension_lookup_by_name: true envoy.reloadable_features.tcp_pool_idle_timeout: false + envoy.reloadable_features.sanitize_original_path: true + re2.max_program_size.error_level: 1000 + - name: "admin_layer" + adminLayer: {} +`) +} + +func TestBuildLayeredRuntime_DontSanitizeOriginalPath(t *testing.T) { + setup() + os.Setenv("ENVOY_SANITIZE_ORIGINAL_PATH", "false") + defer os.Unsetenv("ENVOY_SANITIZE_ORIGINAL_PATH") + rt, err := buildLayeredRuntime() + if err != nil { + t.Error(err) + } + checkMessage(t, rt, ` +layers: + - name: "static_layer_0" + staticLayer: + envoy.features.enable_all_deprecated_features: true + envoy.reloadable_features.http_set_tracing_decision_in_request_id: true + envoy.reloadable_features.no_extension_lookup_by_name: true + envoy.reloadable_features.tcp_pool_idle_timeout: true + envoy.reloadable_features.sanitize_original_path: false re2.max_program_size.error_level: 1000 - name: "admin_layer" adminLayer: {}