feat: restrict dataset urls to configured prefixes - #169
Merged
Merged
Conversation
The ?url= parameter was an open trust boundary: any s3:// prefix the reader role can read, or file:// path in the container, could be opened. ApiSettings.allowed_url_prefixes (TITILER_MULTIDIM_ALLOWED_URL_PREFIXES, comma-separated). When set, DatasetPathParams rejects any url not starting with one of the prefixes with a 400; every data endpoint and the metadata/validate extensions route through that dependency. Empty keeps today's open behaviour so nothing changes until a deploy opts in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GDAL >= 3.12 already defaults GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE to SIBLING_OR_CHILD_OF_VRT_PATH; set it and GDAL_VRT_ENABLE_RAWRASTERBAND=NO explicitly so a base-image or GDAL version change cannot silently relax them. GDAL only encodes output here, so this is defence in depth. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The prefix check was a raw str.startswith, so: - "s3://bucket/a" also admitted "s3://bucket/abc/..."; prefixes now match whole path segments (a trailing "/" is implied). - "<prefix>/../elsewhere" passed textually; urls with "." or ".." path segments (percent-encoded included) are now refused outright rather than resolved, because S3 keeps such keys literally while HTTP servers resolve them, so no single resolution is safe. - "HTTPS://Host/" did not match "https://host/"; scheme and host are now compared case-insensitively. Paths stay case-sensitive. The original url is still what gets opened; normalisation is only used for the comparison. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- type allowed_url_prefixes as list[str] (NoDecode + CSV validator) instead of a str field whose validator returns a list - _normalize_url raises on "."/".." segments instead of returning None; a bad configured prefix now fails startup rather than being silently dropped (which rejected every request) - append the trailing "/" to the path, not after the query string, and do it in one place for both prefixes and urls - reuse reader.api_settings instead of a third ApiSettings instance - move the matching into _is_url_allowed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reader opens a scheme-less url as a local path, but the allowlist compared it as a raw string, so a "file:///data/" prefix denied "/data/x" (and a bare prefix denied file:// urls). _normalize_url now turns bare and relative paths into absolute file:// urls (relative to the working directory, as the reader opens them) after the dot-segment check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hrodmn
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This feature allows restricting what dataset urls a titiler-multidim deployment can be used for. The default stays the same (any valid URL if
TITILER_MULTIDIM_ALLOWED_URL_PREFIXESis unset. IfTITILER_MULTIDIM_ALLOWED_URL_PREFIXES, all URLs that don't validate against those prefixes will raise aHTTPException.Testing
PR checks
run-cdk-checkslabel to this PR.deploy-devlabel. It smoke-tests tiles from the native MUR, virtual MUR, and virtual NLDAS Icechunk stores after deployment.