Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions xrspatial/geotiff/tests/test_ssrf_hardening_1664.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,17 @@ def request(self, method, url, **kwargs):


class TestRedirectRevalidation:
# The test_urllib3_* tests exercise the urllib3 transport path: they mock
# urllib3.PoolManager and call read_range(), which internally builds a
# urllib3.Timeout via _urllib3_timeout(). urllib3 is an optional runtime
# dependency (_HTTPSource falls back to stdlib urllib.request when it's
# missing -- see _reader.py:615-617), so each urllib3-using test starts
# with pytest.importorskip("urllib3"). The test_stdlib_* tests below
# exercise the stdlib redirect handler directly and run regardless.
Comment on lines +270 to +276
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I tried that first — an @pytest.fixture(autouse=True) pytest.importorskip("urllib3") at the class level. The trade-off is that an autouse fixture also fires for the three test_stdlib_* methods in the same class (the stdlib redirect handler tests that don't go through _urllib3_timeout), and those should keep running on machines without urllib3 installed.

A separate class-with-autouse-fixture for just the urllib3 subset would work but it requires moving four methods out, which felt heavier than inlining the four calls. I left a class-level comment to nudge future urllib3-path tests toward the same gate.


def test_urllib3_redirect_to_private_rejected(self, monkeypatch):
"""Public host that 302-redirects to loopback must be rejected."""
pytest.importorskip("urllib3")
# Initial validator pass: example.com resolves to a public IP.
monkeypatch.setattr(
socket, 'getaddrinfo', _fake_getaddrinfo('93.184.216.34'))
Expand All @@ -290,6 +299,7 @@ def test_urllib3_redirect_to_private_rejected(self, monkeypatch):

def test_urllib3_redirect_to_public_followed(self, monkeypatch):
"""Public -> public redirect is followed; validator passes each hop."""
pytest.importorskip("urllib3")
monkeypatch.setattr(
socket, 'getaddrinfo', _fake_getaddrinfo('93.184.216.34'))
src = _reader_mod._HTTPSource('https://example.com/cog.tif')
Expand All @@ -305,6 +315,7 @@ def test_urllib3_redirect_to_public_followed(self, monkeypatch):

def test_urllib3_redirect_chain_capped(self, monkeypatch):
"""More than _HTTP_MAX_REDIRECTS hops raises rather than looping."""
pytest.importorskip("urllib3")
monkeypatch.setattr(
socket, 'getaddrinfo', _fake_getaddrinfo('93.184.216.34'))
src = _reader_mod._HTTPSource('https://example.com/cog.tif')
Expand All @@ -322,6 +333,7 @@ def test_urllib3_redirect_chain_capped(self, monkeypatch):

def test_urllib3_relative_location_resolved(self, monkeypatch):
"""Relative Location like ``/other.tif`` resolves against the source."""
pytest.importorskip("urllib3")
monkeypatch.setattr(
socket, 'getaddrinfo', _fake_getaddrinfo('93.184.216.34'))
src = _reader_mod._HTTPSource('https://example.com/dir/cog.tif')
Expand Down
Loading