Repository navigation
Description
Describe the bug
Hardening report — not an active CVE. Two paper-cuts in the COG reader become real risk when a service accepts user-supplied URLs or paths.
-
Tile byte cap is HTTP-only. In
xrspatial/geotiff/_reader.py:1408-1416theXRSPATIAL_COG_MAX_TILE_BYTEScap is checked inside_fetch_decode_cog_http_tilesbut not inside_read_tilesor_read_strips. A crafted local TIFF with a hugeTileByteCountsorStripByteCountsstill walks into_decode_strip_or_tilecarrying a giant slice. Compressed payloads can be small and decompress (deflate/zstd/lzw) into hundreds of MB or GB, so the decompressor becomes the OOM trigger even though mmap slicing itself is bounded by file size. The currenttest_local_path_unaffected_by_capeven pins the broken behavior in place by asserting the cap does NOT apply locally — that needs flipping. -
SSRF in
_HTTPSource.xrspatial/geotiff/_reader.py:406-503accepts arbitrary URLs with no:- scheme allow-list (
file://,gopher://, etc.) - host filtering —
localhost,127.0.0.1, IPv6 loopback::1, link-local169.254.0.0/16(cloud IMDS), and RFC1918 private ranges all reachable - explicit connect/read timeouts (urllib defaults to infinite; urllib3 has no per-call timeout in our usage)
- explicit redirect cap
- scheme allow-list (
For a service that takes open_geotiff(url=user_input) this is a textbook SSRF surface. http://169.254.169.254/... probes cloud metadata; http://127.0.0.1:6379/ talks to internal Redis.
Expected behavior
- Local tile and strip readers apply the same
XRSPATIAL_COG_MAX_TILE_BYTEScap the HTTP path uses. Keep the existing 256 MiB default so legitimate local reads still work; the env var stays the single tuning knob. _HTTPSource.__init__rejects non-http(s) schemes by default.XRSPATIAL_GEOTIFF_ALLOWED_SCHEMESopts back in.- Hostname resolves through
socket.getaddrinfoand any loopback, link-local, or RFC1918 private IP is rejected unlessXRSPATIAL_GEOTIFF_ALLOW_PRIVATE_HOSTS=1. - Explicit timeouts: connect 10s, read 30s. Overridable via
XRSPATIAL_GEOTIFF_HTTP_CONNECT_TIMEOUTandXRSPATIAL_GEOTIFF_HTTP_READ_TIMEOUT. - Explicit redirect cap of 5.
Backward-compatibility note
Code that currently does open_geotiff('http://127.0.0.1:...') (common in tests and dev) will need XRSPATIAL_GEOTIFF_ALLOW_PRIVATE_HOSTS=1. The PR calls this out and ships the escape hatch.
Additional context
Hardening, not an exploit. Defaults stay safe; advanced users get env-var overrides.
Activity
Apply tile byte cap to local files + SSRF hardening on HTTP geotiff r…
geotiff: honour window and max_pixels for stripped HTTP reads (#1842) (…
geotiff tests: consolidate tile / strip decode cluster (#2453)
geotiff tests: consolidate remote-hardening cluster (#2436) (#2467)