@@ -206,6 +206,41 @@ def test_github_authorization_cannot_cross_a_redirect_boundary(
206206 request , None , 302 , "Found" , {}, destination )
207207
208208
209+ @pytest .mark .parametrize (
210+ ("source" , "destination" , "allowed" ),
211+ [
212+ ("https://api.github.com/repos/o/r" ,
213+ "https://api.github.com:443/repos/o/r" , True ),
214+ ("https://api.github.com:443/repos/o/r" ,
215+ "https://api.github.com/repos/o/r" , True ),
216+ ("https://api.github.com/repos/o/r" ,
217+ "https://api.github.com:0/repos/o/r" , False ),
218+ ("https://api.github.com:0/repos/o/r" ,
219+ "https://api.github.com/repos/o/r" , False ),
220+ ("https://api.github.com:8443/repos/o/r" ,
221+ "https://api.github.com:8443/repositories/4242" , True ),
222+ ("https://api.github.com:0/repos/o/r" ,
223+ "https://api.github.com:0/repositories/4242" , True ),
224+ ],
225+ )
226+ def test_redirect_port_identity_is_not_truthiness (
227+ backfill , source , destination , allowed ):
228+ request = urllib .request .Request (
229+ source , headers = {"Authorization" : "Bearer secret" })
230+
231+ if not allowed :
232+ with pytest .raises (
233+ urllib .error .URLError , match = "unsafe GitHub API redirect" ):
234+ backfill ._SameOriginRedirectHandler ().redirect_request (
235+ request , None , 302 , "Found" , {}, destination )
236+ return
237+
238+ redirected = backfill ._SameOriginRedirectHandler ().redirect_request (
239+ request , None , 302 , "Found" , {}, destination )
240+ assert redirected .full_url == destination
241+ assert redirected .get_header ("Authorization" ) == "Bearer secret"
242+
243+
209244def test_same_origin_https_redirect_remains_usable (backfill ):
210245 request = urllib .request .Request (
211246 "https://api.github.com/repos/octo/demo" ,
0 commit comments