Description
The geotiff reader routes URLs to one of three sources using a case-sensitive prefix match. URL schemes are case-insensitive per RFC 3986, so an uppercase HTTP:// or HTTPS:// URL slips past _HTTPSource (which carries the SSRF allow-list and pinned DNS from #1664 / #1846) and ends up on the fsspec branch via _is_fsspec_uri.
Affected call sites
The case-sensitive check appears in:
xrspatial/geotiff/_reader.py:145 (eager read_to_array dispatcher)
xrspatial/geotiff/_backends/dask.py:197-200 (dask backend HTTP/fsspec branch)
xrspatial/geotiff/_sources.py:1454-1460 (_is_fsspec_uri)
xrspatial/geotiff/_sources.py:1639 (_open_source)
xrspatial/geotiff/_sidecar.py:46 (_is_http_url)
xrspatial/geotiff/_writer.py:1244 (writer _is_fsspec_uri)
xrspatial/geotiff/_backends/gpu.py:350, 1056 (GPU backend HTTP routing)
_is_fsspec_uri only rejects lowercase http:// / https://, so HTTP://127.0.0.1/foo.tif matches :// and routes to _CloudSource (fsspec). The SSRF validator, private-host check, and pinned-DNS connection are all skipped.
Reproducer
from xrspatial.geotiff._sources import _is_fsspec_uri
assert _is_fsspec_uri("HTTP://127.0.0.1/foo.tif") is False # currently True
Fix direction
Parse the URL once with urlparse(source).scheme.lower() and use the lower-cased scheme at every dispatch site. _is_fsspec_uri should reject HTTP(S) case-insensitively. Add regression tests for HTTP://127.0.0.1/... and HTTPS://....
Versions
- xarray-spatial: main (current)
Description
The geotiff reader routes URLs to one of three sources using a case-sensitive prefix match. URL schemes are case-insensitive per RFC 3986, so an uppercase
HTTP://orHTTPS://URL slips past_HTTPSource(which carries the SSRF allow-list and pinned DNS from #1664 / #1846) and ends up on the fsspec branch via_is_fsspec_uri.Affected call sites
The case-sensitive check appears in:
xrspatial/geotiff/_reader.py:145(eagerread_to_arraydispatcher)xrspatial/geotiff/_backends/dask.py:197-200(dask backend HTTP/fsspec branch)xrspatial/geotiff/_sources.py:1454-1460(_is_fsspec_uri)xrspatial/geotiff/_sources.py:1639(_open_source)xrspatial/geotiff/_sidecar.py:46(_is_http_url)xrspatial/geotiff/_writer.py:1244(writer_is_fsspec_uri)xrspatial/geotiff/_backends/gpu.py:350, 1056(GPU backend HTTP routing)_is_fsspec_urionly rejects lowercasehttp:///https://, soHTTP://127.0.0.1/foo.tifmatches://and routes to_CloudSource(fsspec). The SSRF validator, private-host check, and pinned-DNS connection are all skipped.Reproducer
Fix direction
Parse the URL once with
urlparse(source).scheme.lower()and use the lower-cased scheme at every dispatch site._is_fsspec_urishould reject HTTP(S) case-insensitively. Add regression tests forHTTP://127.0.0.1/...andHTTPS://....Versions