Skip to content

test(client-certificates): do not reuse a renegotiated connection - #42878

Merged
Yury Semikhatsky (yury-s) merged 1 commit into
microsoft:mainfrom
csaavedra:fix-cc-renegotiation-reuse
Sep 24, 2026
Merged

Yury Semikhatsky (yury-s) merged 1 commit into
microsoft:mainfrom
csaavedra:fix-cc-renegotiation-reuse

Conversation

@csaavedra

Copy link
Copy Markdown
Contributor

Node counts server-initiated renegotiations against tls.CLIENT_RENEG_LIMIT, and the accounting is such that the second renegotiation on one socket already exceeds the default of 3: the socket is destroyed with "TLS session renegotiation attack detected" while the response is still being produced.

This test renegotiates for both /from-fetch-api and /style.css, so it only survived when the two requests landed on different connections. That was up to the browser's connection pool. WebKit usually reuses the fetch connection for the following navigation, which retires it, and serves the stylesheet on a fresh socket; roughly once in fifteen runs the navigation opened a new connection instead, the stylesheet reused the renegotiated one, and the server killed it mid-request. The browser reported "The network connection was lost.", the stylesheet never arrived, and the button kept its default color.

Close the connection after each response that renegotiates, so every renegotiation gets a socket of its own. This also makes the coverage deterministic: before, whether the stylesheet was fetched over a renegotiated connection depended on pooling; now both steps always renegotiate exactly once. The response is still chunked and gzip encoded, as the browser sees it.

Node counts server-initiated renegotiations against tls.CLIENT_RENEG_LIMIT, and
the accounting is such that the second renegotiation on one socket already
exceeds the default of 3: the socket is destroyed with "TLS session
renegotiation attack detected" while the response is still being produced.

This test renegotiates for both /from-fetch-api and /style.css, so it only
survived when the two requests landed on different connections. That was up to
the browser's connection pool. WebKit usually reuses the fetch connection for
the following navigation, which retires it, and serves the stylesheet on a fresh
socket; roughly once in fifteen runs the navigation opened a new connection
instead, the stylesheet reused the renegotiated one, and the server killed it
mid-request. The browser reported "The network connection was lost.", the
stylesheet never arrived, and the button kept its default color.

Close the connection after each response that renegotiates, so every
renegotiation gets a socket of its own. This also makes the coverage
deterministic: before, whether the stylesheet was fetched over a renegotiated
connection depended on pooling; now both steps always renegotiate exactly once.
The response is still chunked and gzip encoded, as the browser sees it.
@github-actions

Copy link
Copy Markdown
Contributor

Test results for "tests 1"

6 flaky ⚠️ [chromium-library] › library/video.spec.ts:762 › screencast › should work with video+trace `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/chromium/chromium.spec.ts:301 › should report intercepted service worker requests in HAR `@realtime-time-library-chromium-linux`
⚠️ [chromium-library] › library/video.spec.ts:725 › screencast › should capture full viewport on hidpi `@realtime-time-library-chromium-linux`
⚠️ [firefox-library] › library/browsercontext-cookies-third-party.spec.ts:257 › third party 'Partitioned;' cookies `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/browsercontext-cookies-third-party.spec.ts:470 › top level 'Partitioned;' cookie and same origin iframe `@firefox-ubuntu-22.04-node20`
⚠️ [playwright-test] › ui-mode-trace.spec.ts:827 › should update state on subsequent run `@ubuntu-latest-node24`

52074 passed, 1241 skipped


Merge workflow run.

@github-actions

Copy link
Copy Markdown
Contributor

Test results for "MCP"

6 failed
❌ [firefox] › mcp/annotate.spec.ts:316 › should annotate via direct browser_annotate MCP call @mcp-windows-latest-firefox
❌ [firefox] › mcp/annotate.spec.ts:349 › should annotate when context has no fixed viewport @mcp-windows-latest-firefox
❌ [firefox] › mcp/cli-core.spec.ts:140 › uncheck @mcp-windows-latest-firefox
❌ [firefox] › mcp/cli-drag.spec.ts:19 › drag between elements @mcp-windows-latest-firefox
❌ [firefox] › mcp/cli-mouse.spec.ts:38 › mousewheel @mcp-windows-latest-firefox
❌ [firefox] › mcp/cli-save-as.spec.ts:26 › screenshot @mcp-windows-latest-firefox

8699 passed, 1474 skipped


Merge workflow run.

@csaavedra

Copy link
Copy Markdown
Contributor Author

ping Yury Semikhatsky (@yury-s)

'Transfer-Encoding': 'chunked'
'Transfer-Encoding': 'chunked',
// A renegotiated connection must not be reused: a second renegotiation on
// the same socket trips Node's tls.CLIENT_RENEG_LIMIT and destroys it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brave new world!

@yury-s
Yury Semikhatsky (yury-s) merged commit 0d3f1b4 into microsoft:main Sep 24, 2026
44 of 45 checks passed
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.

2 participants