Skip to content

Block HTTPS-to-HTTP redirects to untrusted origins - #14259

Draft
jacobbabula wants to merge 2 commits into
pypa:mainfrom
jacobbabula:codex/block-https-http-redirects
Draft

Block HTTPS-to-HTTP redirects to untrusted origins#14259
jacobbabula wants to merge 2 commits into
pypa:mainfrom
jacobbabula:codex/block-https-http-redirects

Conversation

@jacobbabula

Copy link
Copy Markdown

What does this PR do?

Refuse redirects from HTTPS to HTTP unless pip already considers the destination a secure origin.

PipSession.get_redirect_target() previously rejected non-HTTP(S) schemes but returned HTTP targets regardless of the source scheme. This adds the downgrade check at the shared redirect boundary and reuses is_secure_origin() so localhost and --trusted-host behavior stay unchanged.

Fixes #3174.

Tests cover HTTPS and relative redirects, HTTP-to-HTTP redirects, trusted HTTP origins, and the blocked downgrade.

Validation

  • PYTHONPATH=src python -m pytest tests/unit/test_network_session.py -q (51 passed, 1 skipped)
  • Black and Ruff pre-commit hooks

PR Checklist:

  • I agree to follow the PSF Code of Conduct.
  • I have read and have followed the CONTRIBUTING.md file.
  • I have added a news file fragment (or this PR does not need one).
  • I have read and followed the AI_POLICY.md file, and if any AI tools were used, I have disclosed it below.

Assisted-by: OpenAI Codex

Comment thread src/pip/_internal/network/session.py Outdated
Comment on lines +533 to +538
if (
source_scheme == "https"
and scheme.lower() == "http"
and not self.is_secure_origin(Link(redirect_url))
):
return None

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.

This is unfortunately not enough because the secure HTTP redirect target may redirect again to another non-secure HTTP location. For example: https://index.example → http://127.0.0.1/bounce → http://untrusted.example/package.whl .

Fixing this requires tracking the scheme of the entire request chain, probably on the request object although I'm not sure how to do that.

Comment on lines +533 to +538
if (
source_scheme == "https"
and scheme.lower() == "http"
and not self.is_secure_origin(Link(redirect_url))
):
return None

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.

This method name is misleading, while it does indeed check whether the URL is from secure origin, the warning it presents is specialised to package indexes. It'd be better to refactor is_secure_origin() to only return a boolean (and accept a string URL instead) and raise the appropriate warnings at its call sites.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pip should not follow redirects from a https:// index url to http:// at any point because doing so dangers users

2 participants