Skip to content

upstream_rbac: use stats_prefix string to scope filter stats#32

Closed
fl0Lec wants to merge 750 commits into
masterfrom
fl/upstream-rbac-stats-prefix
Closed

upstream_rbac: use stats_prefix string to scope filter stats#32
fl0Lec wants to merge 750 commits into
masterfrom
fl/upstream-rbac-stats-prefix

Conversation

@fl0Lec

@fl0Lec fl0Lec commented Jul 6, 2026

Copy link
Copy Markdown

Commit Message:
upstream_rbac: use stats_prefix string to scope filter stats

Risk Level:
Low

Testing:
Existing unit tests. Integration test coverage TBD.

Docs Changes:
N/A

Release Notes:
Included

Platform Specific Features:
N/A

API Considerations:
N/A — no API changes.


Context

As noted in the review of envoyproxy#45666, the correct pattern for HTTP filter stats scoping is:

  • The FactoryContext::scope() carries an empty prefix
  • The stats_prefix string passed to createFilterFactoryFromProto carries the parent's namespace (e.g. http.ingress. for connection manager filters, cluster.X. for cluster upstream filters)
  • Filters concatenate stats_prefix with their own metric names to produce fully-qualified stat paths

Problem

Two inconsistencies existed:

  1. Router upstream filter chain (router.cc): passed context.scope().prefix() (empty, since the filter-chain scope has no prefix of its own) to FilterChainHelper, so upstream filters received an empty stats_prefix — no context prefix at all.

  2. Cluster upstream filter chain (upstream_impl.cc): passed the cluster scope's prefix string (e.g. cluster.X.) as stats_prefix, while simultaneously passing a scope that already carried the same cluster.X. prefix. Any filter following the standard pattern would produce cluster.X.cluster.X.my_stat — a double-prefixed name. The upstream RBAC filter worked around this by ignoring stats_prefix entirely (EMPTY_STRING), relying solely on the scope prefix.

Fix

  • router.cc: pass stat_prefix (converted to string, e.g. http.ingress.) as the stats_prefix to FilterChainHelper. Scope is unchanged.
  • upstream_impl.cc: pass an empty string as stats_prefix since the upstream context scope already carries cluster.<name>.. Filters that emit stats relative to the scope get the right prefix without the string.
  • upstream_rbac/config.cc: use the received stats_prefix instead of EMPTY_STRING.

Result

Context Scope prefix stats_prefix string RBAC stat
Router upstream "" http.ingress. http.ingress.rbac.allowed
Cluster upstream cluster.X. "" cluster.X.rbac.allowed

zmiklank and others added 30 commits June 10, 2026 06:57
…returning success.

This is backport of
envoyproxy/envoy-openssl#527.

Returning 1 (always succeed) is safe because OpenSSL's FIPS provider
already performs pairwise consistency tests and key validation
internally during key generation and import. By the time Envoy calls
these functions, OpenSSL has already validated the key through
FIPS-compliant code paths. These BoringSSL-specific FIPS self-test
functions are redundant in an OpenSSL context and were causing a
measurable performance decrease.

Signed-off-by: Zuzana Miklankova <zmiklank@redhat.com>
Signed-off-by: Jonh Wendell <jwendell@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com>
Limit number of PRIORITY frames based on active_streams rather than the
currently bypassable limit based on the cumulative number of streams
ever opened on a connection (`open_streams`).

Add a test that prevents regression.

Signed-off-by: Ethan Truong <ethantruong@google.com>
Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com>
…ermark (envoyproxy#45387)

## Description

`recreateStream()` sets `response_encoder_ = nullptr` before moving the
buffered request body. If the buffer was above the high watermark,
`move()` drains it past the low watermark and synchronously fires
`onDecoderFilterBelowWriteBufferLowWatermark()`, which dereferences the
now-null `response_encoder_`. Crash.

Fix: move the null assignment to after `move()`. The watermark callback
sees a valid pointer during drain. The null still happens before
`doEndStream()`, so the invariant that prevents codec stream reset is
preserved.

## How to trigger

1. `custom_response` filter with `RedirectPolicy` configured
2. Request body exceeds `per_request_buffer_limit_bytes` (~1MB default)
3. 413 local reply in non-streaming mode
4. `RedirectPolicy::encodeHeaders` calls `recreateStream()`
5. Buffer drain → watermark callback → null deref

## Risk level

Low. One assignment moved, no behavioral change outside the brief
watermark callback window.

## Testing

Added `RecreateStreamWithWatermarkedBufferDoesNotCrash` — buffers data
above high watermark, calls `recreateStream()`, expects
`readDisable(false)` without crashing.

Signed-off-by: jingze <daijingze.djz@alibaba-inc.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…xy#45238)

Three changes:
1. renamed the `recreateOnHostChange` to
`recreateOnHostChangeDeprecated`.
2. removed the default implementation to force custom LB implementations
to make an explicit choice during the migration.
3. fixed OverrideHost LB's recreation logic to ensure the sub lb could
be recreated correctly if necessary.

Risk Level: low.
Testing: n/a.
Docs Changes: n/a.
Release Notes: n/a.
Platform Specific Features: n/a.

---------

Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
…proxy#45245)

Fuzz tests for `envoy.filters.http.ext_proc` depend on
`EXT_PROC_GRPC_FUZZ_TEST_DEPS`, some of which are implemented as
`envoy_extension_cc_test_library`. This breaks when the extensions are
turned off via extension build config.

Signed-off-by: Filip Cacky <filip.cacky@cdn77.com>
On systems where libc++ is not available (e.g. RHEL/UBI), the LLVM
toolchain defaults to builtin-libc++ which fails to find C++ standard
library headers. This adds a BAZEL_USE_LIBSTDCPP repo env variable
that configures the LLVM toolchain to use libstdc++ instead.

This allows building with clang and libstdc++ by using bazel flags
`--config=libstdc++ --config=clang-common`.

Signed-off-by: Jonh Wendell <jwendell@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
With stdlib=stdc++, toolchains_llvm v1.7.0 places -l:libstdc++.a in
link_flags (before object files), causing duplicate symbol errors with
tcmalloc which overrides operator new/delete. Move it to link_libs
(after object files) so tcmalloc's definitions take precedence.

This is already fixed upstream in toolchains_llvm master; the patch
can be removed when upgrading to v1.8.0+.

Signed-off-by: Jonh Wendell <jwendell@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Commit Message: dym: add local filename dym support to all extensions
Additional Description:

Now all dynamic modules could use the module.local.filename to specific
the module's patch and to avoid put all modules in same path and
reference it with name.

Risk Level: low.
Testing: unit.
Docs Changes: n/a.
Release Notes: n/a.
Platform Specific Features: n/a.

---------

Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
Commit Message: http: new filter chain filter
Additional Description:

- New filter to configured multiple sub filter chains and allow the
route to select one or provide a inline sub filter chain.

This PR gives the actual per route level filter chain support. We only
need to ensure most filters could support the
`createFilterFactoryFromProtoWithServerContext`.

This filter is a little similar to composite, but with following
difference:
- provides full feature sub filter chain support.
- not as flexible as composite filter, only the initial route could be
used to help to select the sub filter chain, but more easier to use and
more robust for lots scenarios.

Risk Level: low. new filter.
Testing: unit/integration.
Docs Changes: added.
Release Notes: added.
Platform Specific Features: n/a.

---------

Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
Signed-off-by: wbpcode <wbphub@gmail.com>
Signed-off-by: code <wbphub@gmail.com>
Co-authored-by: phlax <phlax@users.noreply.github.com>
<!--
!!!ATTENTION!!!

If you are fixing *any* crash or *any* potential security issue, *do
not*
open a pull request in this repo. Please report the issue via emailing
envoy-security@googlegroups.com where the issue will be triaged
appropriately.
Thank you in advance for helping to keep Envoy secure.

!!!ATTENTION!!!

For an explanation of how to fill out the fields, please see the
relevant section
in
[PULL_REQUESTS.md](https://github.com/envoyproxy/envoy/blob/main/PULL_REQUESTS.md)

!!!ATTENTION!!!

Please check the [use of generative AI
policy](https://github.com/envoyproxy/envoy/blob/main/CONTRIBUTING.md?plain=1#L41).

You may use generative AI only if you fully understand the code. You
need to disclose
this usage in the PR description to ensure transparency.
-->

Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
Fixes: envoyproxy#42434
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional [API
Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):]

---------

Signed-off-by: Ethan Truong <ethantruong@google.com>
Commit Message: fix: skip null pointer in EDS validation
Additional Description: Skips gap in LocalityLbEndpoints priorities that
caused nullprt dereference and Envoy crashed with SEGFAULT. Affected
when RING_HASH or MAGLEV loadbalancer policy is used.
Risk Level: Low
Testing: https://github.com/dajas22/envoy-playground
Docs Changes:
Release Notes:

Affects releases since 1.36.0.

cc @botengyao

---------

Signed-off-by: June Kim <junekim@users.noreply.github.com>
Signed-off-by: June Kim <kimjune01@gmail.com>
Co-authored-by: June Kim <kimjune01@gmail.com>
…nvoyproxy#44664)

<!--
!!!ATTENTION!!!

If you are fixing *any* crash or *any* potential security issue, *do
not*
open a pull request in this repo. Please report the issue via emailing
envoy-security@googlegroups.com where the issue will be triaged
appropriately.
Thank you in advance for helping to keep Envoy secure.

!!!ATTENTION!!!

For an explanation of how to fill out the fields, please see the
relevant section
in
[PULL_REQUESTS.md](https://github.com/envoyproxy/envoy/blob/main/PULL_REQUESTS.md)

!!!ATTENTION!!!

Please check the [use of generative AI
policy](https://github.com/envoyproxy/envoy/blob/main/CONTRIBUTING.md?plain=1#L41).

You may use generative AI only if you fully understand the code. You
need to disclose
this usage in the PR description to ensure transparency.
-->

Commit Message: xds: log per-resource rejection details for
LDS/CDS/RDS/EDS/SDS/SRDS

Additional Description: When an xDS update is rejected, the error detail
(e.g. "route: unknown cluster '...'") was only visible via the admin
`/config_dump` API or buried in an aggregated subscription-layer NACK
log using an opaque proto type URL.
This made diagnosing readiness failures like "lds updates: 0 successful,
N rejected" require manual config dump inspection. This PR adds a
per-resource `warn` log at the point of rejection in each xDS resource
handler, naming the specific resource and the exact reason:

[warn] lds: listener 'foo' config rejected: route: unknown cluster 'bar'
  [warn] cds: cluster 'foo' config rejected: <detail>
  [warn] rds: route config 'foo' rejected: <detail>
  [warn] eds: cluster 'foo' config rejected: <detail>
  [warn] sds: secret 'foo' config rejected: <detail>
  [warn] srds: scoped route config 'foo' rejected: <detail>

The log level matches the three existing rejection log sites in the
subscription layer (subscription_state.h, delta_subscription_state.cc,
grpc_subscription_impl.cc) which all use `warn` for the same class of
event.

Risk Level: Low, additive logging only, no behavioral changes.
Testing: Existing unit tests for each xDS handler cover the error paths
that now emit the new log lines. No new behavior was introduced that
requires additional test coverage. Manual testing performed using a
filesystem-based LDS subscription with a listener referencing a
non-existent cluster (validate_clusters: true) to confirm the new log
line appears.
Docs Changes: None
Release Notes: Added per-resource warn-level log lines when xDS config
updates are rejected for LDS, CDS, RDS, EDS, SDS, and SRDS. Previously
these errors were only surfaced via the admin config_dump API or as an
aggregated
message in the subscription-layer NACK log.
Platform Specific Features: None
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional [API
Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):]

---------

Signed-off-by: Prashanth Josyula <prashanth.16@gmail.com>
…roxy#44282)

When Envoy sits behind an external load balancer, the internal
:authority and :scheme headers don't match the externally-visible
hostname. The redirect_uri can already be templated with formatters to
handle this, but the URL encoded in the OAuth2 state parameter is always
derived from the request's :authority/:scheme — causing a mismatch that
breaks the post-login redirect.

This PR adds two new config fields:

- `original_request_uri`: an optional formatter-supported base URI
(scheme + host)
used to build the original request URL encoded into the OAuth2 state
parameter.
Operators can template it from `x-forwarded-host`/`x-forwarded-proto` so
the
post-auth redirect uses the public host rather than Envoy's internal
`:authority`.
- `allowed_redirect_domains`: a case-insensitive allowlist (exact or
`*.` wildcard)
  applied to the host of the formatted `redirect_uri`, the formatted
`original_request_uri`, and the URL decoded from the `state` parameter
on callback.
Mitigates open-redirect attacks via injected `x-forwarded-host` headers
or forged
`state` values. Empty list (default) disables the check for backward
compatibility.

Risk Level: Low
Testing: Unit tests added for the allowlist (exact, wildcard, empty-list
no-op), forwarded-header-driven redirect and state, and rejection on
mismatch and on unparseable URLs.
Docs Changes: Proto field documentation added inline.
Release Notes: Added `original_request_uri` and
`allowed_redirect_domains` options to the OAuth2 filter to support
deployments behind external load balancers and prevent open redirects
via the state parameter.
Platform Specific Features: N/A
[Optional Fixes envoyproxy#41034]
[Optional API Considerations: Two new fields added to OAuth2Config
(field numbers 28 and 29). No breaking changes to existing configs.]

Signed-off-by: Mohammed Shetaya <mohammed.shetaya@procore.com>
<!--
!!!ATTENTION!!!

If you are fixing **any** crash or **any** potential security issue,
**do not
open a pull request**.

Instead, please
[open a GitHub Security
Advisory](https://github.com/envoyproxy/envoy/security/advisories/new)
(preferred). Alternatively, you may email
envoy-security@googlegroups.com.

Thank you in advance for helping to keep Envoy secure.

!!!ATTENTION!!!

For an explanation of how to fill out the fields, please see the
relevant section
in
[PULL_REQUESTS.md](https://github.com/envoyproxy/envoy/blob/main/PULL_REQUESTS.md)

!!!ATTENTION!!!

Please check the [use of generative AI
policy](https://github.com/envoyproxy/envoy/blob/main/CONTRIBUTING.md?plain=1#L41).

You may use generative AI only if you fully understand the code. You
need to disclose
this usage in the PR description to ensure transparency.
-->

Commit Message: feat: `path_rewrite` redirect action
Additional Description: Implement support for a new `path_rewrite`
redirect action that supports substitution and CEL formatting to set the
new URI for redirect.
Risk Level: Low (new feature)
Testing: Unit testing
Docs Changes: N/A
Release Notes: Yes
Fixes: envoyproxy#44844

---------

Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com>
…cross-instance compatibility (envoyproxy#44981)

## Summary

Stateful session cookies created by one Envoy instance could appear
expired when validated by another because `monotonicTime()` is
process-specific. Different instances have different monotonic clock
baselines, causing premature cookie expiry behind a load balancer.

Switches from `monotonicTime()` to `systemTime()` in both cookie
creation and validation so all instances share a consistent time
reference.

## Test plan
- [ ] Deploy multiple Envoy instances behind a load balancer with
stateful session cookies
- [ ] Verify cookies created by one instance are accepted by another
- [ ] Verify cookie expiry works correctly with wall-clock time

Fixes envoyproxy#44111

---------

Signed-off-by: June Kim <kimjune01@gmail.com>
…ger downstream reconnections (envoyproxy#45101)

**Commit Message:**
http: add connection-duration jitter and drain-timeout jitter to stagger
downstream reconnections

**Additional Description:**
Mitigates the thundering-herd reconnect problem when many downstream
long-lived HTTP/2 or gRPC connections share the same
`max_connection_duration` and all reach the limit (and therefore drain)
at the same instant. Two opt-in knobs:

1. `HttpProtocolOptions.max_connection_duration_jitter`
(`type.v3.Percent`):
extends each connection's duration timer by `random(0, base * pct/100)`.
Mirrors the existing TCP-proxy field
`max_downstream_connection_duration_jitter_percentage` (from
envoyproxy#40999).
1. `HttpConnectionManager.drain_timeout_jitter` (`type.v3.Percent`):
extends
the drain grace period between the shutdown-notice GOAWAY and the final
  GOAWAY by `random(0, drain_timeout * pct/100)`.

Both fields are individually opt-in.

**Risk Level:**
Low.
- Defaults preserve current behavior on both fields:
  - jitter fields default to unset → no jitter
- No existing config paths or stats are altered.

**Testing:**
Unit tests and config-parsing tests

**Docs Changes:**
Proto field comments document semantics, defaults, and interaction with
`max_connection_duration` / `drain_timeout`.

**Release Notes:**
Updated change log.

**Platform Specific Features:**
None.

**Runtime guard:**
None.

**Fixes #Issue:**
- envoyproxy#35391
- envoyproxy#42410

**API Considerations:**
- `max_connection_duration_jitter` placed on `HttpProtocolOptions` (next
to
`max_connection_duration`) following the TCP proxy precedent. Note: the
field is currently honored only by the downstream HCM runtime; upstream
  clusters read the same proto but do not apply the jitter today.
- `drain_timeout_jitter` placed on
  `HttpConnectionManager` because the drain sequence they gate is
  downstream-HCM-only; placing it on `HttpProtocolOptions` would
  incorrectly imply upstream applicability.
- Both use `type.v3.Percent`, which carries `[0, 100]` PGV validation;
  no additional runtime bounds checking is needed.

---------

Signed-off-by: Winbobob <zhewei.hu33@gmail.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
…nvoyproxy#45372)

Replace constructors that can throw with a factory method that returns
StatusOr<> for SystemTimeFormatter and derived classes. There should be
no functional changes, as there is still a throw present when a factory
method fails.

Test changes are all conversions from direct construction to a factory
method.

In the subsequent PRs I will generalize the makeTimeFormatter so it can
be used with generic types.

There are boilerplate checkConstructPreconditions method in the derived
classes that just call the base class. They are not strictly needed, and
I have left them, just to so I can use this as pattern for agents that
will work on implementing this pattern for other types where derived
classes have their own preconditions.


Risk Level: low
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

---------

Signed-off-by: Yan Avlasov <yavlasov@google.com>
Signed-off-by: publish-envoy[bot]
Commit Message: upstream: support SDS in HCS-built clusters
Additional Description:

ProdClusterInfoFactory constructed TransportSocketFactoryContextImpl
with the 3-arg ctor, leaving init_manager_ null. The SDS branch of
getTlsCertificateConfigProviders (context_config_impl.cc:74) calls
factory_context.initManager() unconditionally, so any HCS carrying
tls_certificate_sds_secret_configs aborts the proxy in HdsCluster
construction. Passing the server's init manager would also assert at
runtime because HCS arrives long after the server has transitioned to
Initialized.

Mirror the per-cluster pattern used by ClusterImplBase for CDS clusters
(upstream_impl.cc:1622): construct a fresh Init::ManagerImpl for each
HCS-built cluster, set it on the factory_context, build the transport
socket factory and matcher, then drive initialize() with a no-op watcher
so the registered SDS subscriptions kick off their file watchers
immediately.

Risk Level: mid (touches core)
Testing: done
Docs Changes: n/a
Release Notes: n/a
Platform Specific Features: n/a

Signed-off-by: Takeshi Yoneda <tyoneda@netflix.com>
…data

Extension metadata (status, security_posture) is now declared in
extensions_metadata.yaml files rather than in envoy_cc_extension BUILD
rules. Update the documentation to point to the correct files and
document the status_upstream field for extensions usable in both
downstream and upstream contexts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonh Wendell <jwendell@redhat.com>
**Commit Message:**  dynamic_modules: add cluster_get_name ABI callback

**Additional Description:**

Adds envoy_dynamic_module_callback_cluster_get_name, a cluster-side ABI
callback that returns the cluster's CDS name from any context holding a 
cluster_envoy_ptr.

Previously the cluster name was only reachable from the load-balancer
side via
cluster_lb_get_cluster_name. Modules that key per-cluster state by the
unique
CDS name had no way to read it from the cluster lifecycle callbacks, and
had to
capture it late from the LB. This callback closes that gap and matches
the
existing LB-side accessor.

Risk Level: Low
Testing: Unit Tests added
Docs Changes: N.A
Release Notes: N.A
Platform Specific Features: N.A

---------

Signed-off-by: Basundhara Chakrabarty <basundhara17061996@gmail.com>
https://github.com/google/quiche/compare/6b6a9b743..0abb446b2

```
$ git log 6b6a9b743..0abb446b2 --date=short --no-merges --format="%ad %al %s"

2026-06-11 asedeno Bump anonymous-tokens dependency in QUICHE.
2026-06-10 ericorth QBONE Server Simulator: Minor shutdown crash fix
2026-06-10 ericorth QBONE Server Simulator: Add generic logic to handle control messages
2026-06-09 ericorth QBONE Server Simulator: Implement open-source BasicQuicServer
2026-06-09 dschinazi Allow expecting multiple errors in OHTTP test client
2026-06-09 asedeno Conditionalize testing of QUIC server padding.
2026-06-09 asedeno Remove protobuf WKT doppleganglers from QUICHE.
2026-06-06 quiche-dev Log request header count in GFE. We will use this for potential log analysis in the context of Sonic Marmot (omg/98169).
2026-06-05 quiche-dev Fix 5 ClangTidyReadability findings: * function 'QuicConnectionIdHasher' has inline specifier but is implicitly inlined. For more info, see go/clang_tidy/checks/readability-redundant-inline-specifier (2 times) * function 'ReviseFirstByteByVersion' has inline specifier but is implicitly inlined. For more info, see go/clang_tidy/checks/readability-redundant-inline-specifier (2 times) * function 'Hash' has inline specifier but is implicitly inlined. For more info, see go/clang_tidy/checks/readability-redundant-inline-specifier
2026-06-05 vasilvv Support the "has first object in the subgroup" bit in the subgroup header.
```

Risk Level: Low
Testing: CI

Signed-off-by: Alejandro R. Sedeño <asedeno@google.com>
…tension (envoyproxy#44326)

**Commit Message:** add access logging support for the reverse tunnel
initiator bootstrap extension

  **Additional Description:**

  **Problem:**

The reverse tunnel initiator (downstream side) has no access logging
support. Operators have no
structured visibility into when reverse tunnel connections are
established, when handshakes fail,
or when connections are closed. The only observability available is
stats counters and debug-level
ENVOY_LOG traces, which are not suitable for production monitoring or
auditing.

  **Solution:**

Add a configurable `access_log` field to the
`DownstreamReverseConnectionSocketInterface` bootstrap
extension proto. Access loggers are instantiated from config in
`ReverseTunnelInitiatorExtension` and
  invoked at three lifecycle points in `ReverseConnectionIOHandle`:

- `handshake_success` — reverse tunnel handshake completed successfully
- `handshake_failure` — reverse tunnel handshake failed (with error
details)
- `connection_closed` — an established reverse tunnel connection was
torn down

Each log entry carries reverse tunnel metadata as dynamic metadata under
the
`envoy.reverse_tunnel.initiator` namespace, accessible via standard
`%DYNAMIC_METADATA(...)%`
  format strings:

  | Field | Description |
  |---|---|
| `event` | Lifecycle event: `handshake_success`, `handshake_failure`,
`connection_closed` |
  | `node_id` | The `src_node_id` of this initiator Envoy instance |
| `cluster_id` | The `src_cluster_id` of this initiator Envoy instance |
  | `tenant_id` | The `src_tenant_id` of this initiator Envoy instance |
| `upstream_cluster` | Name of the upstream cluster this tunnel connects
to |
  | `host_address` | Resolved address of the specific upstream host |
| `connection_key` | Unique identifier for this connection (correlates
handshake and close events) |
| `error` | Failure reason (only present on `handshake_failure` events)
|

Any access log type supported by Envoy (file, stdout, gRPC, etc.) can be
used. The implementation
follows the same pattern as TCP proxy access logging — creating an
ephemeral `StreamInfoImpl` per
log entry and populating dynamic metadata before calling each configured
logger.

  Risk Level: Low
Testing: Existing unit tests pass. Access log creation and lifecycle
callsites are additive.
Docs Changes: Added access logging section to
`docs/root/configuration/other_features/reverse_tunnel.rst`
  Release Notes: N/A
  Platform Specific Features: N/A

Signed-off-by: Krishna Sharma <krishna@krishna.com>
Signed-off-by: Krishna Sharma <krishnagpl2001@gmail.com>
Commit Message: Disable DLB due to breakage of contrib build.
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes: included
Fixes envoyproxy#45491

Signed-off-by: Kevin Baichoo <envoy@kevinbaichoo.com>
…cks (envoyproxy#45585)

## Description

Return early from the clear route cache and add custom flag callbacks
when decoder callbacks are absent, and skip clearing when the downstream
callbacks optional is empty, matching the guarded sibling callbacks.

---

**Commit Message:** dynamic_modules: guard http filter route cache and
custom flag callbacks
**Risk Level:** Low
**Testing:** Added
**Docs Changes:** Added
**Release Notes:** N/A

Signed-off-by: Rohit Agrawal <rohit.agrawal@databricks.com>
…voyproxy#45586)

## Description

This PR allocates and seeds the worker slot in the cluster constructor
so that the worker threads always observe an initialized slot instead of
relying on the lazy allocation.

---

**Commit Message:** dynamic_modules: allocate cluster worker slot during
construction
**Risk Level:** Low
**Testing:** Added
**Docs Changes:** Added
**Release Notes:** N/A

Signed-off-by: Rohit Agrawal <rohit.agrawal@databricks.com>
…oyproxy#45587)

## Description

This PR retains the host metadata shared pointer on the filter so that
the pointer returned to the module stays valid for the entire duration
of the call.

---

**Commit Message:** dynamic_modules: hold host metadata snapshot for
stable lifetime
**Risk Level:** Low
**Testing:** Added
**Docs Changes:** Added
**Release Notes:** N/A

Signed-off-by: Rohit Agrawal <rohit.agrawal@databricks.com>
yanavlasov and others added 29 commits July 1, 2026 10:17
…xy#45918)

Risk Level: none
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
Risk Level: none
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
expose the qcache_max_ttl setting and share DNSResolver if cares config
is the same so the qcache can be shared. runtime guard
"envoy.restart_features.shared_cares_dns_resolver" is set to true by
default to enable sharing DNSResolver if cares config of the clusters
are the same. Set to false to disable this behavior.

AI is used to generate the tests and write some of the comment but I did
review and tune/modify all the tests added. All other code are hand
written.

Risk Level: Low
Testing: unit test and manual test using tcpdump to verify multiple
clusters with the same host (different port) only generate 1 dns lookup
most of the time.
Docs Changes: None
Release Notes: Added qcache_max_ttl field to CaresDnsResolverConfig
Platform Specific Features: None
[Optional Runtime guard:]
"envoy.restart_features.shared_cares_dns_resolver" is set to true by
default to enable sharing DNSResolver if cares config of the clusters
are the same. Set to false to disable this behavior.

---------

Signed-off-by: Andy Fong <andy.fong@solo.io>
Fixes envoyproxy#40127

Commit Message: oauth2: add `private_key_jwt` client authentication
support
Additional Description: Adds `PRIVATE_KEY_JWT` as a new `auth_type` for
the OAuth2 filter. Instead of sending a `client_secret` in the token
request, the filter creates a signed JWT assertion.

**Changes in this PR**
- New proto message `PrivateKeyJwt` with configurable
`signing_algorithm` (default RS256)
    and `assertion_lifetime` (default 60s).
- New `ClientAssertion` class handles JWT creation: builds
header/payload with required
claims (iss, sub, aud, exp, iat, jti), signs with the PEM private key
provided via
    the existing `token_secret` SDS config.
  - Supported algorithms: RS256, RS384, RS512, ES256, ES384, ES512.
  - Works for both initial token exchange and refresh token flows.
  - JSON claim values are sanitized to prevent injection.

Risk Level: Low
Testing: Unit tests added. Validated on a oauth flow.
Docs Changes: Proto changes included.
Release Notes: Added
Platform Specific Features: NA

---------

Signed-off-by: Anurag Aggarwal <kanurag94@gmail.com>
This benchmark demonstrates how the cost of `EdsResourcesCacheImpl`
operations scales with increasingly complex `ClusterLoadAssignment`
messages.

I used the Gemini AI model to generate the benchmark. The file itself
looks reasonable to me.

Here are the results from an example run on my workstation:
```
Run on (12 X 4500 MHz CPU s)
CPU Caches:
  L1 Data 32 KiB (x6)
  L1 Instruction 32 KiB (x6)
  L2 Unified 1024 KiB (x6)
  L3 Unified 8448 KiB (x1)
Load Average: 8.13, 5.26, 3.11
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
----------------------------------------------------------------
Benchmark                      Time             CPU   Iterations
----------------------------------------------------------------
bmSetResource/1/1            800 ns          800 ns       978841
bmSetResource/1/10          6635 ns         6634 ns       105646
bmSetResource/10/10        66568 ns        66565 ns         9212
bmSetResource/10/100      668162 ns       668139 ns          927
bmSetResource/100/100   11704205 ns     11703982 ns           66
bmGetResource/1/1           11.1 ns         11.1 ns     64584407
bmGetResource/1/10          11.1 ns         11.1 ns     64811719
bmGetResource/10/10         12.3 ns         12.3 ns     61295787
bmGetResource/10/100        11.7 ns         11.7 ns     65544985
bmGetResource/100/100       11.1 ns         11.1 ns     63082759
```

Commit Message:
Additional Description:
Risk Level: none
Testing: ran the benchmark locally
Docs Changes:
Release Notes:
Platform Specific Features:

Signed-off-by: Biren Roy <birenroy@google.com>
…xy#45923)

### Description

The cross-thread degrade path in outlier detection dereferences a null
host monitor when a host is removed from the cluster before a deferred
degrade callback runs.

`DetectorImpl::setHostDegraded()` posts to the main thread via
`dispatcher_.post(...)`. Before the posted callback
(`setHostDegradedMainThread`) runs, a cluster update can deliver
`hosts_removed` and execute `host_monitors_.erase(host)`. When the
deferred callback then runs, `host_monitors_[host]` (an
`absl::flat_hash_map::operator[]`) **default-inserts a null
`DetectorHostMonitorImpl`**, and the subsequent `->degrade(...)`
dereferences null, crashing the process.

The eject path already guards exactly this case in
`onConsecutiveErrorWorker`:

```cpp
// Ejections come in cross thread. There is a chance that the host has already been removed from
// the set. If so, just ignore it.
if (host_monitors_.count(host) == 0) {
  return;
}
```

The degrade path had no such guard.

This is reachable under ordinary, non-adversarial churn — autoscaling,
rolling deploys, and health-check-driven host removal — whenever a
degraded host is removed in the window between the worker thread posting
the degrade event and the main thread running it. No attacker or
deliberate control-plane timing is required to hit it by chance.

### Fix

Add the removed-host guard at the top of `setHostDegradedMainThread`,
mirroring the eject path, so `host_monitors_[host]` cannot
default-insert a null monitor that is then dereferenced.

### Test

Adds a deterministic regression test,
`OutlierDetectorImplTest.CrossThreadDegradeRemoveRace`, that reproduces
the interleaving without real threads: it intercepts the degrade
`dispatcher_.post`, removes the host (`runCallbacks({}, old_hosts)` ->
`host_monitors_.erase`), then fires the captured callback. Pre-fix this
dereferences a null monitor and crashes; post-fix the removed host is
skipped and the test passes cleanly. This mirrors the existing
`CrossThreadRemoveRace` / `CrossThreadDestroyRace` tests.

Adds a `bug_fixes` changelog fragment.

### Notes

Reported privately as GHSA-rf7j-pmr2-gf7r; opening per @yanavlasov's
go-ahead to fix in the open.

---------

Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
Co-authored-by: Omkhar Arasaratnam <omkhar@linkedin.com>
Broken due to bad merge.

Risk Level: none
Testing: unit test
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
…#45933)

The change is safe and should result in a better error message during
config ingestion. There is already a defense-in-depth check for nullptr
formatter, which is converted to a generic error status.

Risk Level: low
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
## Description

The install documentation at `docs/root/start/install.rst` includes an
apt-based install path for Ubuntu 24.04 (`noble`), but
`https://apt.envoyproxy.io` does not currently publish a `noble`
release.
Users following the documented commands hit a 404 on `apt-get update`:

```
Err:5 https://apt.envoyproxy.io noble Release
  404  Not Found
```

This change removes the broken `Ubuntu noble` `code-tab` block and
replaces it with a `.. note::` block that:

- Tells Ubuntu 24.04 users that no apt repository is currently
published.
- Points them at the pre-built Docker images (existing
  `:ref:` link to `install_binaries`).
- Points them at the GitHub release page for the static binary.
- Links back to issue envoyproxy#44405 for the tracking discussion.

This matches the maintainer's stated preference in the issue thread:

> this is currently not working im afraid - it requires some
> rearchitecting - possibly we should remove from docs until its fixed

---

**Commit Message:** docs: remove broken Ubuntu noble install
instructions

**Additional Description:** Replaced the non-functional `Ubuntu noble`
apt install code-tab with a note pointing affected users to the working
Docker / GitHub-release install paths, and linking the tracking issue.

**Risk Level:** Low

**Testing:** Documentation-only change; no code changes, no tests added
or modified. Visually verified the resulting RST renders as a `..
note::`
admonition immediately after the existing Debian-based tabs.

**Docs Changes:** This *is* the docs change.
`docs/root/start/install.rst`
updated.

**Release Notes:** None — documentation-only fix to existing
instructions
that were broken at publication time.

Fixes envoyproxy#44405

---

*Note on AI assistance:* This change was prepared with AI assistance per
the [generative AI
policy](https://github.com/envoyproxy/envoy/blob/main/CONTRIBUTING.md#use-of-generative-ai-policy).
The submitter understands the change, has reviewed the resulting RST,
and
will respond to review feedback directly.

---------

Signed-off-by: gaurav0107 <gauravdubey0107@gmail.com>
)

The oauth2 private_key_jwt feature (envoyproxy#44005) uses BoringSSL functions
that were missing from the OpenSSL compatibility layer, breaking the
OpenSSL CI build.

- d2i_ECDSA_SIG: standard function, auto-generated forwarding suffices.
- BN_bn2bin_padded: BoringSSL-specific, handwritten to adapt to
OpenSSL's BN_bn2binpad (different parameter order and return value).

Signed-off-by: Jonh Wendell <jwendell@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
docs build imports top level .bazelrc and does not need to be changed.

Risk Level: none
Testing: build
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
…5875)

On a reverse tunnel the downstream is the HTTP/2 server. When the peer
upstream drains it sends GOAWAY, but HCM ignores GOAWAY by default, so
the tunnel lingers until the socket closes and the agent does not
proactively restore capacity.

This makes the drain-aware HCM react to a peer GOAWAY by re-dialing a
replacement tunnel, so capacity is restored before the draining tunnel
closes while its in-flight streams finish. Opt-in via
``enable_drain_with_goaway`` on the drain-aware HCM config; default off,
so unupgraded or disabled downstreams are unaffected (a received GOAWAY
stays a no-op) -- a safe migration path.

Companion to envoyproxy#45874 (the upstream emits the drain GOAWAY); the two are
independent and each is harmless alone.

**Commit Message:** reverse_tunnel: drain-aware HCM re-dials on peer
GOAWAY
**Additional Description:** See above.
**Risk Level:** Low -- config-gated, default off; unchanged behavior
when off.
**Testing:** unit tests (drain_aware_config_test,
drain_aware_server_connection_test); manual end-to-end + mixed-version
safety (an old downstream safely ignores the GOAWAY without crashing).
**Docs Changes:** drain_aware_hcm config field docs.
**Release Notes:** changelog fragment included.
**Platform Specific Features:** n/a
**Optional Runtime guard:** n/a (config-gated)
**Optional API Considerations:** adds ``enable_drain_with_goaway`` to
``DrainAwareHttpConnectionManager``.

---------

Signed-off-by: Prasad I V <prasad.iv@databricks.com>
Co-authored-by: Prasad I V <prasad.iv@databricks.com>
…roxy#45969)

Test file got too big and times out under TSAN or ASAN. Also takes
forever to compile. Split the `HttpFilterTest` test suite into its own
file.

Risk Level: none
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yavlasov@google.com>
…nvoyproxy#45967)

Replace const std::string& arguments with absl::string_view in methods
that don't need an owned string or that already perform a copy
internally. This doesn't change performance characteristics on its own
but it allows custom extensions that can cheaply produce a string_view
but not a const std::string& to avoid an unnecessary allocation just to
fit method signatures.

This was generated with AI but is a mechanical change. No behavior
changes are expected.

Risk Level: low
Testing: built all targets
Docs Changes: n/a
Release Notes: n/a
Platform Specific Features: n/a

Towards envoyproxy#11693

---------

Signed-off-by: Alex Bakon <abakon@netflix.com>
like envoyproxy#45871, but
for wasm.

---------

Signed-off-by: zirain <zirain2009@gmail.com>
…proxy#45970)

Fix a typo where "callback" was misspelled as "callabck" in a local
variable name in the dynamic_modules HTTP filter, in a member variable
name in the generic_proxy network filter integration test and docs.
No functional change; purely a rename for readability.

Generative AI (Claude Code) was used to check for remaining occurrences
of the typo across the repository and to assist with code review of the
changes.

Risk Level: low
Testing: Ran the affected targets locally:
- //test/extensions/dynamic_modules/http:filter_test
- //test/extensions/filters/network/generic_proxy:integration_test


Docs Changes: Fix typo
Release Notes:N/A
Platform Specific Features:N/A

Signed-off-by: u-kai <76635578+u-kai@users.noreply.github.com>
… field allocation (envoyproxy#45893)

_Commit Message:_
fix memory exhaustion via unbounded tagged field allocation in
flexible-version request headers.

_Additional Description:_
the Envoy contrib Kafka network filter was vulnerable to a memory
exhaustion attack through the flexible-version request header parser.
Kafka's flexible version protocol extends request headers with optional
tagged fields, each encoded as a VarUInt32 count followed by per-field
VarUInt32 tag, VarUInt32 data-length, and data bytes.
added MAX_TAGGED_FIELD_COUNT = 64 and MAX_TAGGED_FIELD_DATA_SIZE = 64 kb
guard here to mitigate the issue.

_Risk Level:_
low

_Testing:_
will update test cases soon

Fixes envoyproxy#45859

---------

Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
…xy#45972)

Move agrawroh and botengyao into the senior-maintainers group to match
OWNERS.md, and refresh the header expiration/last-updated/last-reviewed
dates.

Commit Message:
Additional Description:
Risk Level: low
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:

Signed-off-by: Boteng Yao <botengyao@gmail.com>
…#45951)

For Number token, there are two cases
(1) Huge Number token that arrive complete with their terminator in the
same chunk: This is not subject to attack vector here, hence the limit
in this PR here is not applicable, as it is bounded by the
max_body_bytes limit in the upper layer

(2) Huge Number token is split and sent via many small data chunks by
attacker, when NUMBER token straddles a chunk boundary, it will cause
Wuffs to rewind its ead cursor and the cursor to save the unread bytes
in pending_bytes_. Thus we need to cap the pending_bytes here.

Tests have been added.

Signed-off-by: tyxia <tyxia@google.com>
**Commit Message:** Add a dynamic module health checker

**Additional Description:**

This adds a new dynamic-module extension type, a custom health checker
registered as 'envoy.health_checkers.dynamic_modules'. It lets users
define a custom health-check mechanism in a dynamic module, and/or run
the health check inside the module on its own thread (off Envoy's main
thread) and report the result back to the main thread. The C++
DynamicModuleHealthChecker subclasses Upstream::HealthCheckerImplBase,
so Envoy continues to drive the standard per-host interval/timeout
timers, healthy/unhealthy thresholds, jitter, and event logging; on each
interval it calls into the module, which performs the actual check and
reports status back to Envoy's main dispatcher.

Risk Level: Low
Testing: Unit + Integration Tests added
Docs Changes: Docs added
Release Notes: N.A
Platform Specific Features: N.A

Signed-off-by: Basundhara Chakrabarty <basundhara17061996@gmail.com>
…eam recreates (envoyproxy#45888)

**Commit Message:** persist module-owned filter state objects across
stream recreates
**Additional Description:**

This adds a dynamic-modules HTTP-filter ABI that lets a module store an
opaque, module-owned, non-serializable object in StreamInfo::FilterState
at a lifespan that survives recreate_stream, with a module-supplied
destructor. It is purely additive to the dynamic-modules extension.

**Motivation:** A dynamic-module HTTP filter sometimes needs to keep a
live, per-stream object graph (channel handles, task handles for an
in-flight async exchange) alive across an Envoy recreate_stream().
recreate_stream() destroys the current filter instance and builds a
fresh one, so any state the instance held in native memory dies with it.
The existing filter-state ABI can't carry it: it's byte-oriented (no way
to serialize live handles) and hardcoded to FilterChain lifespan.

This adds two HTTP-filter ABI callbacks plus Rust SDK wrappers:

- set_filter_state_object(key, obj, destructor, life_span): store an
opaque, module-owned void* with a lifespan and a module destructor.
- get_filter_state_object(key): borrow it back on any later hook,
including the rebuilt instance after a recreate.

Objects stored at Request/Connection lifespan are carried into the new
stream by the connection manager; FilterChain objects are not.

The module keys the object under a fixed, well-known name. On a fresh
request the key is absent, so the filter creates the object and stores
it; after recreate_stream the same key is present on the rebuilt
instance, which is the signal to re-attach to the surviving object
instead of starting over. The per-stream filter state is the entire
handoff ; no request header, random id, or external registry needed.

Risk Level: Low
Testing: Unit and Integration Tests
Docs Changes: N.A
Release Notes: N.A
Platform Specific Features: N.A

---------

Signed-off-by: Basundhara Chakrabarty <basundhara17061996@gmail.com>
…#45922)

Test cleanup was racing with request completion, occasionally crashing.

Risk Level: no
Testing: unit test
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yavlasov@google.com>
…45952)

Status error validation is present at all callsites of the `parse`
method.

Risk Level: low
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yavlasov@google.com>
## Description

This PR adds the Stat Sink reference to the Dynamic Module docs main
page.

---

**Commit Message**: docs: add entry for stat sink DM
**Risk Level:** Low
**Testing:** CI
**Docs Changes**: Added
**Release Notes**: N/A

Signed-off-by: Rohit Agrawal <rohit.agrawal@databricks.com>
…st (envoyproxy#45963)

CDS update synchronization in these tests were invalid. The
`cluster_manager.active_clusters` was already 3 causing test to proceed
without waiting for CDS update to applied. It was more likely to fail
under slower tests like ASAN.

Risk Level: none
Testing: unit test (asan 1000 times)
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yavlasov@google.com>
…oxy#45977)

Two disabled tests trigger UB (div by zero and nullptr assignment) in
WASM VM and can never succeed under UBSAN.

Risk Level: none
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yavlasov@google.com>
Reduce number of files pulled through //envoy/stats:stats_interface

Risk Level: none
Testing: unit tests
Docs Changes: no
Release Notes: no
Platform Specific Features: no

Signed-off-by: Yan Avlasov <yan_avlasov@hotmail.com>
The stats_prefix string passed to createFilterFactoryFromProto carries
the parent's namespace (e.g. "http.ingress." for router upstream filters).
Upstream filters should use this string to qualify their own stats rather
than relying on the scope's prefix, which follows the same convention used
by downstream HTTP filters.

Changes:
- router.cc: pass stat_prefix (converted to string) to FilterChainHelper
  instead of the scope's empty prefix, so router upstream filters receive a
  non-empty stats_prefix matching the connection manager's stat prefix.
- upstream_impl.cc: pass an empty stats_prefix to FilterChainHelper since
  the upstream_context_ scope already carries the "cluster.<name>." prefix;
  passing the same prefix as both a scope prefix and the stats_prefix string
  would cause filters to emit double-prefixed names.
- upstream_rbac/config.cc: use the received stats_prefix instead of
  EMPTY_STRING so RBAC counters land under the parent's namespace.

Signed-off-by: Florent Lecoultre <florent.lecoultre@datadoghq.com>
@fl0Lec fl0Lec closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.