Skip to content

🐛 fix(periodic-update): refuse unverified HTTPS to PyPI by default#3122

Merged
gaborbernat merged 1 commit into
pypa:mainfrom
gaborbernat:security/tls-fallback-env
Apr 14, 2026
Merged

🐛 fix(periodic-update): refuse unverified HTTPS to PyPI by default#3122
gaborbernat merged 1 commit into
pypa:mainfrom
gaborbernat:security/tls-fallback-env

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Security hardening. When the verified HTTPS request to https://pypi.org/pypi/<dist>/json failed, the periodic update retried the request with an unverified SSL context and used whatever came back. The original comment justified this with 'the information we request is not sensitive', but the metadata drives the decision about which wheel version virtualenv considers 'up to date'. 🔒 A network-level attacker that can break the handshake can then pin virtualenv to an older seed wheel and silently suppress security updates.

The fallback is now skipped by default. A failed verified request logs the error and returns None, which the periodic update path already handles gracefully — no wheel bump happens and the run continues. Hosts with genuinely broken trust stores can opt back in by setting VIRTUALENV_PERIODIC_UPDATE_INSECURE=1, which is logged at WARNING so it shows up in CI output. The env var is documented in docs/how-to/usage.rst next to the existing override knobs.

@gaborbernat gaborbernat force-pushed the security/tls-fallback-env branch 3 times, most recently from 53ae5cd to 1b440c9 Compare April 14, 2026 05:07
When the verified HTTPS request to ``https://pypi.org/pypi/<dist>/json``
failed, the periodic update retried with an unverified SSL context and
used whatever it got back. The original reasoning was that the
metadata is not sensitive, but the response drives the "latest wheel"
decision, so a network-level attacker with a TLS handshake in the
middle can quietly pin virtualenv to an older version and suppress
security updates.

Skip the fallback by default and abort the lookup instead. Hosts with
broken trust stores that need the old behaviour can set
``VIRTUALENV_PERIODIC_UPDATE_INSECURE=1`` as an explicit escape hatch,
logged at WARNING so it is visible in CI output.
@gaborbernat gaborbernat force-pushed the security/tls-fallback-env branch from 1b440c9 to e40ca49 Compare April 14, 2026 05:13
@gaborbernat gaborbernat marked this pull request as ready for review April 14, 2026 14:53
@gaborbernat gaborbernat enabled auto-merge (squash) April 14, 2026 15:03
@gaborbernat gaborbernat merged commit 48f6fdc into pypa:main Apr 14, 2026
58 checks passed
@gaborbernat gaborbernat deleted the security/tls-fallback-env branch July 10, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2 participants