diff --git a/packages/hflow-server/tests/test_server_runtime.py b/packages/hflow-server/tests/test_server_runtime.py index 4a99634..320b915 100644 --- a/packages/hflow-server/tests/test_server_runtime.py +++ b/packages/hflow-server/tests/test_server_runtime.py @@ -344,7 +344,15 @@ def test_ingest_rejects_absolute_and_escaping_uris_before_any_runtime( data_root = tmp_path / "bare-root" data_root.mkdir() client = _client_over(data_root, unbuilt_assets_dir) - for hostile_uri in ("/etc/passwd", "../../etc/shadow", "sub/../../escape.mcap"): + for hostile_uri in ( + ".", + "./", + "a/..", + "a/b/../..", + "/etc/passwd", + "../../etc/shadow", + "sub/../../escape.mcap", + ): response = client.post( "/api/v1/runtime/ingest", json={"uris": [hostile_uri], "profile": "full", "mode": "batch"}, diff --git a/src/hflow/uri.py b/src/hflow/uri.py index 3e75933..c38d3c1 100644 --- a/src/hflow/uri.py +++ b/src/hflow/uri.py @@ -30,7 +30,7 @@ def parse_data_root_relative_uri(uri: str) -> DataRootRelativeUri: # Preserve the candidate itself; normalize only this containment check. normalized = normpath(candidate) - if normalized == ".." or normalized.startswith("../"): + if normalized == "." or normalized == ".." or normalized.startswith("../"): raise ValueError(f"{candidate!r} is not relative to the data root") return DataRootRelativeUri(candidate) diff --git a/tests/test_runtime_cli.py b/tests/test_runtime_cli.py index 9191287..bd2ef82 100644 --- a/tests/test_runtime_cli.py +++ b/tests/test_runtime_cli.py @@ -916,7 +916,7 @@ def test_ingest_rejects_unknown_profile(pipeline_file: Path, tmp_path: Path) -> assert exit_info.value.code == 2 -@pytest.mark.parametrize("uri", ["/abs/x.mcap", "../x.mcap"]) +@pytest.mark.parametrize("uri", [".", "./", "a/..", "a/b/../..", "/abs/x.mcap", "../x.mcap"]) def test_ingest_rejects_uris_outside_data_root( uri: str, pipeline_file: Path, diff --git a/tests/test_runtime_client.py b/tests/test_runtime_client.py index 1cedec4..80113a2 100644 --- a/tests/test_runtime_client.py +++ b/tests/test_runtime_client.py @@ -376,6 +376,10 @@ def test_ingest_refuses_a_batch_count_the_run_could_not_honour(stub_server: str) "uri", [ " ", + ".", + "./", + "a/..", + "a/b/../..", "/etc/passwd", "../outside.mcap", r"\episodes-in\a.mcap",