You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The desktop (Tauri) bundle ships a Python 3.11 runtime, which bundles OpenSSL 3.0.x.
On some carrier networks, TLS handshakes made with that stack to self-hosted HTTPS endpoints are reset by a middlebox (injected RST); the same endpoints work fine from modern stacks
(browser, curl/OpenSSL 3.5.x). Desktop users cannot change the bundled runtime (frozen stdlib,
no override hook), so the only fix is to bump the desktop build pipeline to Python 3.13
(bundles OpenSSL 3.5.x). Python 3.12 is not an option: Windows Python 3.12 still bundles
OpenSSL 3.0.x — the exact fingerprint being blocked.
Symptom
Desktop app (Windows), selfcheck-reported stack Python 3.11.9 / OpenSSL 3.0.13: TLS handshake
to a self-hosted HTTPS endpoint (cloud VPS + reverse proxy + public CA cert) fails after ~100 ms
with a connection reset (WinError 10054).
Same codebase in the official Docker image (Python 3.11.2 / OpenSSL 3.0.20): ssl.SSLError: TLS/SSL connection has been closed (EOF) (SSLZeroReturnError) — same endpoint, same network.
From the same machine / same network, modern stacks succeed: host curl (OpenSSL 3.5.5) ✅,
a Python 3.13 + OpenSSL 3.5.6 build of this codebase → TLSv1.3 ✅, phone browser ✅.
Root cause: middlebox RST injection, not a server fault
Server-side tcpdump (at the VPS) shows the reset is injected in the path:
The same "peer" sends two RSTs with different sequence numbers (one at the pre-data position,
one at initial-seq + ClientHello length) — a genuine TCP stack cannot own both send positions.
The RSTs carry a TTL 4 hops off the normal packets (55 vs 51) and ToS 0 vs 0x14.
Both RSTs share one IP identification → a single injecting device.
The server access log shows a complete handshake path: certificate selected, ServerHello sent,
then write: connection reset by peer.
Controlled experiments pin down the trigger dimensions:
→ Blocking requires both conditions: SNI in the target domain familyand a legacy
TLS-stack fingerprint (3.0-era ClientHello ≈ 517 B with legacy cipher/protocol declarations,
vs ≈ 1569 B for modern stacks). It is not a weak-cipher issue (forcing strong ciphers did not
help) and it is not a server issue (server side was verified clean end to end).
Scope note: DPI rule sets differ per carrier and per network — on one 5G network we also saw a
modern mobile-app stack (non-browser) blocked, i.e. some rules are stricter than the 3.0-era
fingerprint. The fix below restores connectivity on the networks where the 3.0-era stack is the
distinguishing factor — which is exactly where desktop users stand today, with no workaround.
Why this needs an upstream fix
Unlike a browser, a desktop user has no way to change the TLS stack: the runtime is frozen
into the bundle (PyInstaller onedir; the stdlib lives in the frozen archive, no env/config hook to
redirect to a system Python). Server-side workarounds (other ports, SNI aliases) do not help — the
device fingerprints the client stack, not just the SNI. The fix is a build-time change only.
Why 3.13 specifically (not 3.12)
Windows Python 3.12 still bundles OpenSSL 3.0.x → same blocked fingerprint.
Python 3.13 bundles OpenSSL 3.5.x.
Measured A/B on the same machine, same network, same target: 3.11 + OpenSSL 3.0.20 → RST; 3.13 + OpenSSL 3.5.6 → TLSv1.3 OK (this codebase, rebuilt on a 3.13 base).
Proposed change (desktop pipeline only)
python-version bumps in the desktop workflows — the CI build-machine Python is what scripts/pack-tauri/stage_python_runtime.py follows when selecting the bundled runtime:
File
Lines
Current
.github/workflows/desktop-build.yml
L50, L183
"3.11"
.github/workflows/desktop-release.yml
L77, L140, L182, L320, L469
"3.11"
.github/workflows/desktop-publish.yml
L77
"3.11"
.github/workflows/desktop-promote.yml
L51
"3.11"
.github/workflows/fork-verify-desktop.yml
L56, L130
"3.10" (verify workflow should stage the same runtime as the real pipeline)
Line numbers as of upstream/main @ 3f13a7b2.
No other changes required: stage_python_runtime.py already pins python-build-standalone
release 20260623, which ships cpython-3.13.14 for both x86_64-pc-windows-msvc and aarch64-apple-darwin; the staged runtime version follows the CI python-version automatically.
Compatibility evidence
The upstream CI test matrices already run Python 3.13 alongside 3.11
(tests.yml / full-tests-nightly.yml / release-verify.yml: matrix ["3.11", "3.13"]) —
the codebase is continuously verified on 3.13.
pyproject.toml: requires-python = ">=3.11,<3.14" — 3.13 is inside the supported range.
The desktop bundle builds the same codebase; only the runtime/toolchain version changes.
QwenPaw Version
2.1.0
Description
The desktop (Tauri) bundle ships a Python 3.11 runtime, which bundles OpenSSL 3.0.x.
On some carrier networks, TLS handshakes made with that stack to self-hosted HTTPS endpoints are
reset by a middlebox (injected RST); the same endpoints work fine from modern stacks
(browser, curl/OpenSSL 3.5.x). Desktop users cannot change the bundled runtime (frozen stdlib,
no override hook), so the only fix is to bump the desktop build pipeline to Python 3.13
(bundles OpenSSL 3.5.x). Python 3.12 is not an option: Windows Python 3.12 still bundles
OpenSSL 3.0.x — the exact fingerprint being blocked.
Symptom
to a self-hosted HTTPS endpoint (cloud VPS + reverse proxy + public CA cert) fails after ~100 ms
with a connection reset (
WinError 10054).ssl.SSLError: TLS/SSL connection has been closed (EOF) (SSLZeroReturnError)— same endpoint, same network.a Python 3.13 + OpenSSL 3.5.6 build of this codebase →
TLSv1.3✅, phone browser ✅.Root cause: middlebox RST injection, not a server fault
Server-side
tcpdump(at the VPS) shows the reset is injected in the path:one at initial-seq + ClientHello length) — a genuine TCP stack cannot own both send positions.
then
write: connection reset by peer.Controlled experiments pin down the trigger dimensions:
→ Blocking requires both conditions: SNI in the target domain family and a legacy
TLS-stack fingerprint (3.0-era ClientHello ≈ 517 B with legacy cipher/protocol declarations,
vs ≈ 1569 B for modern stacks). It is not a weak-cipher issue (forcing strong ciphers did not
help) and it is not a server issue (server side was verified clean end to end).
Scope note: DPI rule sets differ per carrier and per network — on one 5G network we also saw a
modern mobile-app stack (non-browser) blocked, i.e. some rules are stricter than the 3.0-era
fingerprint. The fix below restores connectivity on the networks where the 3.0-era stack is the
distinguishing factor — which is exactly where desktop users stand today, with no workaround.
Why this needs an upstream fix
Unlike a browser, a desktop user has no way to change the TLS stack: the runtime is frozen
into the bundle (PyInstaller onedir; the stdlib lives in the frozen archive, no env/config hook to
redirect to a system Python). Server-side workarounds (other ports, SNI aliases) do not help — the
device fingerprints the client stack, not just the SNI. The fix is a build-time change only.
Why 3.13 specifically (not 3.12)
3.13 + OpenSSL 3.5.6 → TLSv1.3 OK (this codebase, rebuilt on a 3.13 base).
Proposed change (desktop pipeline only)
python-versionbumps in the desktop workflows — the CI build-machine Python is whatscripts/pack-tauri/stage_python_runtime.pyfollows when selecting the bundled runtime:.github/workflows/desktop-build.yml"3.11".github/workflows/desktop-release.yml"3.11".github/workflows/desktop-publish.yml"3.11".github/workflows/desktop-promote.yml"3.11".github/workflows/fork-verify-desktop.yml"3.10"(verify workflow should stage the same runtime as the real pipeline)Line numbers as of
upstream/main @ 3f13a7b2.No other changes required:
stage_python_runtime.pyalready pins python-build-standalonerelease
20260623, which shipscpython-3.13.14for bothx86_64-pc-windows-msvcandaarch64-apple-darwin; the staged runtime version follows the CI python-version automatically.Compatibility evidence
(
tests.yml/full-tests-nightly.yml/release-verify.yml: matrix["3.11", "3.13"]) —the codebase is continuously verified on 3.13.
pyproject.toml:requires-python = ">=3.11,<3.14"— 3.13 is inside the supported range.Component(s) Affected
Environment
Steps to Reproduce
Actual vs Expected
Logs / Screenshots
[Paste relevant log output or attach screenshots. Use code blocks for logs.]
Additional Notes
[Optional: workarounds, similar issues, etc.]