[9.5] [HTTP/2] Fix KibanaSocket to use session-level socket for HTTP/2 requests (#285344) - #287792
Merged
Merged
Conversation
…ests (elastic#285344) ## Summary Fixes the root cause of elastic#258232 — PKI sessions being invalidated after upgrading to Kibana 9.x, where `server.protocol` silently defaults to `http2` when `ssl.enabled: true`. This is the companion to elastic#285153, which fixes the symptom in `pki.ts`. This PR fixes the underlying socket resolution in Core HTTP. ## Problem For HTTP/2 requests, `Http2ServerRequest.socket` returns a `Proxy` over the **stream**, not the session's `TLSSocket`. The load-bearing traps branch on `stream[kSession]`: ```js // Node.js lib/internal/http2/compat.js getPrototypeOf(stream) { if (stream.session !== undefined) return ReflectGetPrototypeOf(stream.session[kSocket]); return ReflectGetPrototypeOf(stream); // <-- Http2Stream, NOT TLSSocket } ``` Node clears `stream[kSession]` whenever the stream is destroyed — RST_STREAM, GOAWAY, client abort, timeout. After that point the proxy resolves against the `Http2Stream` itself, so every `instanceof TLSSocket` check in `KibanaSocket` fails and the accessors degrade: | accessor | value after stream destruction | |---|---| | `authorized` | `undefined` | | `authorizationError` | `undefined` | | `getPeerCertificate(true)` | `null` | | `getProtocol()` | `null` | | `remoteAddress` | `undefined` | This happens on **live, authorized connections** — the TLS handshake succeeded and the client certificate is valid, but the stream-level proxy can no longer report it. Kibana's own frontend aborts in-flight requests constantly via `AbortController` (search sessions, unified search, autocomplete). On HTTP/1.1 an abort closes a dedicated socket; on HTTP/2 it emits RST_STREAM on a **shared** session mid-flight, so one cancelled stream degrades the socket view for concurrent requests. ## Fix Resolve the **session-level** socket (`req.stream.session.socket`) at `KibanaSocket` construction time instead of using the stream-level proxy. The session socket resolves against `session[kSocket]`, is a real `TLSSocket`, and remains stable for the lifetime of the TCP connection. This is semantically correct: in HTTP/2 the client certificate is a property of the **connection**, not of an individual stream. Falls back to `req.socket` when the session socket is unavailable — either an HTTP/1.1 request (no `stream` property) or a fully destroyed session (`session.socket` throws `ERR_HTTP2_SOCKET_UNBOUND`). ## Secondary fix `audit_service.ts` reads `request.socket.remoteAddress` for audit log client IP enrichment. On destroyed HTTP/2 streams this silently yielded `undefined`, losing the client IP in audit records for **all** auth providers. This patch fixes that too, since the session socket carries a stable `remoteAddress`. ## Testing Four new unit tests in `socket.test.ts` covering `resolveRawSocket`: - HTTP/1.1 request (no `stream` property) → returns `req.socket` - HTTP/2 request → returns the session-level socket - `stream.session` undefined → falls back to `req.socket` - `session.socket` throws `ERR_HTTP2_SOCKET_UNBOUND` → falls back to `req.socket` ``` node scripts/jest src/core/packages/http/router-server-internal/src/socket.test.ts # 20 passed, 20 total ``` ## Relationship to elastic#285153 - **elastic#285153** (`pki.ts`) — defensive guard so an unknowable socket state (`authorized === undefined`) is not treated as an explicit cert rejection. Narrow, safe to backport. - **This PR** (Core HTTP) — removes the condition that produces the unknowable state in the first place. Both are worth having. The `pki.ts` guard remains correct defense-in-depth for the fully-destroyed-session case, where even the session socket is unavailable. ## Risk Touches socket resolution for all Core HTTP requests, not just PKI. Mitigations: - HTTP/1.1 requests are unaffected — no `stream` property means the original `req.socket` is returned unchanged. - The HTTP/2 path only changes *which* socket object is wrapped; `KibanaSocket`'s own logic is untouched. - Fallback preserves today's behaviour whenever the session socket cannot be resolved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- ## Release note Fixes an issue where audit log records could omit the client IP address for requests made over HTTP/2. --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: kibanamachine <[email protected]> (cherry picked from commit d433465) # Conflicts: # x-pack/platform/plugins/shared/security/test/scout_pki_stress/.meta/api/standard.json
jeramysoucy
enabled auto-merge (squash)
August 28, 2026 10:01
kibanamachine
requested review from
elena-shostak
and removed request for
kibanamachine
August 28, 2026 10:02
Contributor
💚 Build Succeeded
Metrics [docs]
|
elena-shostak
approved these changes
Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport
This will backport the following commits from
mainto9.5:Questions ?
Please refer to the Backport tool documentation