Block HTTPS-to-HTTP redirects to untrusted origins - #14259
Conversation
| if ( | ||
| source_scheme == "https" | ||
| and scheme.lower() == "http" | ||
| and not self.is_secure_origin(Link(redirect_url)) | ||
| ): | ||
| return None |
There was a problem hiding this comment.
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.
| if ( | ||
| source_scheme == "https" | ||
| and scheme.lower() == "http" | ||
| and not self.is_secure_origin(Link(redirect_url)) | ||
| ): | ||
| return None |
There was a problem hiding this comment.
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.
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 reusesis_secure_origin()so localhost and--trusted-hostbehavior 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)PR Checklist:
Assisted-by: OpenAI Codex