GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — asyncio: start_tls() loses buffered data from StreamReader · Issue #142352 · python/cpython

asyncio: start_tls() loses buffered data from StreamReader #142352

New issue
Copy link
New issue
Copy link
Closed
#142354
Closed
asyncio: start_tls() loses buffered data from StreamReader#142352
#142354
Copy link
Labels
3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@kasimov-maxim
kasimov-maxim
opened on Dec 6, 2025
Issue body actions

Bug report

Bug description:

Bug description

When using StreamWriter.start_tls() (or loop.start_tls()) to upgrade a connection to TLS mid-stream, any data already buffered in the StreamReader is lost.

This commonly occurs when implementing servers that support the PROXY protocol (e.g., behind HAProxy with send-proxy). In this scenario:

  1. The proxy sends the PROXY protocol header followed immediately by the TLS ClientHello in the same TCP segment
  2. The server reads the PROXY header using reader.readline()
  3. The TLS ClientHello data is now buffered in StreamReader._buffer
  4. When writer.start_tls() is called, a new SSLProtocol is created, but the buffered data is not transferred to it
  5. The TLS handshake hangs waiting for ClientHello data that was already received but lost

Reproducible example

Server (server.py)

import asyncio
import ssl

async def handle_client(reader, writer):
    # Read PROXY protocol header
    proxy_header = await reader.readline()
    print(f"PROXY header: {proxy_header}")

    # Upgrade to TLS - this is where data loss occurs
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain('server.crt', 'server.key')
    
    await writer.start_tls(context)
    print("TLS handshake completed")  # Never reached - hangs here

    data = await reader.read(1024)
    print(f"Received: {data}")
    
    writer.close()
    await writer.wait_closed()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 8000)
    async with server:
        await server.serve_forever()

asyncio.run(main())

HAProxy config (haproxy.cfg)

frontend proxy_frontend
    mode tcp
    bind *:5002
    default_backend proxy_backend

backend proxy_backend
    mode tcp
    server app 127.0.0.1:8000 send-proxy

Client command

echo "Test message" | openssl s_client -connect 127.0.0.1:5002

Expected behavior

TLS handshake completes and server receives "Test message".

Actual behavior

TLS handshake hangs indefinitely because the TLS ClientHello data buffered in StreamReader is lost when start_tls() is called.

Additional context

I have a fix ready with tests and will submit a PR shortly.

The fix transfers buffered data from StreamReader._buffer to SSLProtocol._incoming before the TLS handshake begins.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

  • gh-142352: Fix start_tls() to transfer buffered data from StreamReader #142354
  • [3.14] gh-142352: Fix asyncio start_tls() to transfer buffered data from StreamReader (GH-142354) #145363
  • [3.13] gh-142352: Fix asyncio start_tls() to transfer buffered data from StreamReader (GH-142354) #145364

Activity

  1. kasimov-maxim
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Dec 6, 2025
  2. StanFromIreland
    added
    topic-asyncio
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Dec 6, 2025
  3. github-project-automation
    added this to asyncioon Dec 6, 2025
  4. github-project-automation
    moved this to Todo in asyncioon Dec 6, 2025
  5. fizzi01 commented on Dec 10, 2025

    @fizzi01
    fizzi01
    on Dec 10, 2025
    More actions

    Your solution works perfectly!

    Reacted by Maksym Kasimov
  6. kumaraditya303 commented on Dec 17, 2025

    @kumaraditya303
    kumaraditya303
    on Dec 17, 2025
    Contributor
    More actions

    Does this happens with uvloop as well? ideally asyncio should handle this similar to how it is done in uvloop.

  7. kumaraditya303
    added
    3.13only security fixesonly security fixes
    3.14bugs and security fixesbugs and security fixes
    3.15bugs and security fixesbugs and security fixes
    on Dec 17, 2025
  8. fizzi01 commented on Dec 18, 2025

    @fizzi01
    fizzi01
    on Dec 18, 2025
    More actions

    Does this happens with uvloop as well? ideally asyncio should handle this similar to how it is done in uvloop.

    Yes it does

    Reacted by Maksym Kasimov
  9. kasimov-maxim
    added 3 commits that reference this issue on Jan 21, 2026

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    86d80bf

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    c2cd20b

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    ef4570a
  10. kasimov-maxim
    added 6 commits that reference this issue on Jan 29, 2026

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    73cf3b9

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    9c1bed6

    pythongh-142352: simplify start_tls buffered-data test

    3d61fc9

    pythongh-142352: asyncio.streams: transfer buffered data to SSL layer…

    a3905bd

    pythongh-142352: simplify start_tls buffered-data test

    d3d9940

    pythongh-142352: pause transport before moving buffered data

    f39a5cd
  11. kumaraditya303
    added a commit that references this issue on Feb 28, 2026

    gh-142352: Fix `asyncio` `start_tls()` to transfer buffered data from…

    0598f4a
  12. kumaraditya303
    closed this as completedin #142354on Feb 28, 2026
  13. github-project-automation
    moved this from Todo to Done in asyncioon Feb 28, 2026
  14. miss-islington
    added a commit that references this issue on Feb 28, 2026

    pythongh-142352: Fix `asyncio` `start_tls()` to transfer buffered dat…

    def8286
  15. kumaraditya303
    added 2 commits that reference this issue on Feb 28, 2026

    [3.13] pythongh-142352: Fix `asyncio` `start_tls()` to transfer buffe…

    9b79465

    pythongh-142352: Fix `asyncio` `start_tls()` to transfer buffered dat…

    5fc071b
  16. brijkapadia
    added a commit that references this issue on Feb 28, 2026

    pythongh-142352: Fix `asyncio` `start_tls()` to transfer buffered dat…

    78a274c
  17. kumaraditya303
    added 2 commits that reference this issue on Feb 28, 2026

    [3.14] gh-142352: Fix `asyncio` `start_tls()` to transfer buffered da…

    fc2a6cf

    [3.13] gh-142352: Fix asyncio start_tls() to transfer buffered data f…

    aa0aa31
  18. ljfp
    added a commit that references this issue on Apr 25, 2026

    pythongh-142352: Fix `asyncio` `start_tls()` to transfer buffered dat…

    4332dd0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • asyncio
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.