From ed6819caa9dfbb21b280adb0155b60caadfdd727 Mon Sep 17 00:00:00 2001 From: Dylan Lee Date: Mon, 23 Mar 2026 13:25:02 -0400 Subject: [PATCH 1/3] fix: remove user-controlled data from temp file path expression --- app/routers/hydrofabric/router.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/routers/hydrofabric/router.py b/app/routers/hydrofabric/router.py index 7e103b2..8074b5c 100644 --- a/app/routers/hydrofabric/router.py +++ b/app/routers/hydrofabric/router.py @@ -94,8 +94,9 @@ async def get_hydrofabric_subset_gpkg( **Returns:** Geopackage file (.gpkg) containing the subset data """ unique_id = str(uuid.uuid4())[:8] - temp_dir = pathlib.Path(tempfile.gettempdir()) - tmp_path = temp_dir / f"subset_{identifier}_{unique_id}.gpkg" + temp_dir = pathlib.Path(tempfile.gettempdir()).resolve() + # Use only the UUID in the filename to avoid user-controlled data in path expressions + tmp_path = temp_dir / f"subset_{unique_id}.gpkg" # Resolve namespace from domain/source combination (outside try block for error handling access) try: From c709bb10c065bdd81f4b22dc0beb0783f2d00d15 Mon Sep 17 00:00:00 2001 From: Daniel Cumpton Date: Fri, 13 Mar 2026 16:26:42 -0600 Subject: [PATCH 2/3] sanitize geopackage path and change print statements to log statments --- app/routers/hydrofabric/router.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/routers/hydrofabric/router.py b/app/routers/hydrofabric/router.py index 8074b5c..8ce8c42 100644 --- a/app/routers/hydrofabric/router.py +++ b/app/routers/hydrofabric/router.py @@ -1,3 +1,4 @@ +import logging import pathlib import sqlite3 import tempfile @@ -34,6 +35,9 @@ QueryIdType, ) +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + api_router = APIRouter(prefix="/hydrofabric") @@ -183,13 +187,13 @@ async def get_hydrofabric_subset_gpkg( else: nonspatial_layers[table_name] = layer_data else: - print(f"Warning: {table_name} layer is empty") + logger.warning(f"Warning: {table_name} layer is empty") # Write spatial layers first with pyogrio for table_name, layer_data in spatial_layers.items(): pyogrio.write_dataframe(layer_data, tmp_path, layer=table_name) layers_written += 1 - print(f"Written spatial layer '{table_name}' with {len(layer_data)} records") + logger.info(f"Written spatial layer '{table_name}' with {len(layer_data)} records") # Then write non-spatial layers with sqlite3 if nonspatial_layers: @@ -197,7 +201,7 @@ async def get_hydrofabric_subset_gpkg( for table_name, layer_data in nonspatial_layers.items(): layer_data.to_sql(table_name, conn, if_exists="replace", index=False) layers_written += 1 - print(f"Written non-spatial layer '{table_name}' with {len(layer_data)} records") + logger.info(f"Written non-spatial layer '{table_name}' with {len(layer_data)} records") conn.close() if layers_written == 0: From 6a6f72026179b0b02cbb0f4e2daf9a448fbb1900 Mon Sep 17 00:00:00 2001 From: Dylan Lee Date: Mon, 23 Mar 2026 13:58:33 -0400 Subject: [PATCH 3/3] fix: update trivy-action to v0.35.0 --- .github/workflows/cicd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 2d2ebab..cbbc4a7 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -126,7 +126,7 @@ jobs: load: true tags: ${{ needs.setup.outputs.image_base }}/api:${{ needs.setup.outputs.test_image_tag }} - name: Scan API container with Trivy - uses: aquasecurity/trivy-action@0.20.0 + uses: aquasecurity/trivy-action@v0.35.0 with: # Scan the locally available image image-ref: ${{ needs.setup.outputs.image_base }}/api:${{ needs.setup.outputs.test_image_tag }} @@ -158,7 +158,7 @@ jobs: load: true tags: ${{ needs.setup.outputs.image_base }}/dashboard:${{ needs.setup.outputs.test_image_tag }} - name: Scan dashboard container with Trivy - uses: aquasecurity/trivy-action@0.20.0 + uses: aquasecurity/trivy-action@v0.35.0 with: # Scan the locally available image image-ref: ${{ needs.setup.outputs.image_base }}/dashboard:${{ needs.setup.outputs.test_image_tag }}