Skip to content

Add GeoJSON and improve API#113

Merged
svenseeberg merged 1 commit into
mainfrom
fix/linting
Feb 20, 2026
Merged

Add GeoJSON and improve API#113
svenseeberg merged 1 commit into
mainfrom
fix/linting

Conversation

@svenseeberg
Copy link
Copy Markdown
Member

No description provided.

content_type, _ = mimetypes.guess_type(str(file_path))
return FileResponse(file_path.open("rb"), content_type=content_type or "application/octet-stream")
return FileResponse(
file_path.open("rb"),

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix

AI 3 months ago

In general, the fix is to normalize and validate any filesystem path derived from user input before using it, and to ensure it is contained within an intended root directory. For this view, we should: (1) ensure the input is just a filename (no directory separators), (2) resolve the combined path (settings.SIMULATION_OUTPUT + filename) to an absolute/normalized path, and (3) verify that the resolved path is indeed inside settings.SIMULATION_OUTPUT. Only then should we use it with FileResponse.

Concretely, within SimulationFileView.get in opendrift_leeway_webgui/leeway/views.py, we should:

  1. Build a base_dir = Path(settings.SIMULATION_OUTPUT).resolve() once per request.
  2. Reject any input that is not a “flat” name using a simple, robust check like if "/" in path or "\\" in path: raise Http404, which is clearer and avoids relying on Path(path).parent.
  3. Construct file_path = (base_dir / path).resolve().
  4. Ensure file_path is under base_dir; for Python 3.9+ we can use file_path.is_relative_to(base_dir), and otherwise fall back to a try/except ValueError around file_path.relative_to(base_dir). If it is outside, raise Http404.
  5. Keep the remaining logic intact: verify the file exists, extract uuid_str = file_path.stem, check ownership, and then stream the file.

These changes occur only inside the SimulationFileView.get method body; no new imports are necessary because we already import Path and settings. Functionality from the caller’s perspective remains the same (serving per-user simulation outputs by filename), but traversal and out-of-root access are now blocked in a way that satisfies CodeQL and is secure.


Suggested changeset 1
opendrift_leeway_webgui/leeway/views.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/opendrift_leeway_webgui/leeway/views.py b/opendrift_leeway_webgui/leeway/views.py
--- a/opendrift_leeway_webgui/leeway/views.py
+++ b/opendrift_leeway_webgui/leeway/views.py
@@ -140,12 +140,20 @@
         """
         Serve the requested simulation file if the user owns it.
         """
-        file_path = Path(settings.SIMULATION_OUTPUT) / path
+        base_dir = Path(settings.SIMULATION_OUTPUT).resolve()
 
-        # Only allow a flat filename — no directory traversal
-        if Path(path).parent != Path("."):
+        # Only allow a flat filename — no directory traversal or path separators
+        if "/" in path or "\\" in path:
             raise Http404
 
+        file_path = (base_dir / path).resolve()
+
+        # Ensure the resolved path is inside the simulation output directory
+        try:
+            file_path.relative_to(base_dir)
+        except ValueError:
+            raise Http404
+
         if not file_path.is_file():
             raise Http404
 
EOF
@@ -140,12 +140,20 @@
"""
Serve the requested simulation file if the user owns it.
"""
file_path = Path(settings.SIMULATION_OUTPUT) / path
base_dir = Path(settings.SIMULATION_OUTPUT).resolve()

# Only allow a flat filename — no directory traversal
if Path(path).parent != Path("."):
# Only allow a flat filename — no directory traversal or path separators
if "/" in path or "\\" in path:
raise Http404

file_path = (base_dir / path).resolve()

# Ensure the resolved path is inside the simulation output directory
try:
file_path.relative_to(base_dir)
except ValueError:
raise Http404

if not file_path.is_file():
raise Http404

Copilot is powered by AI and may make mistakes. Always verify output.
@svenseeberg svenseeberg committed this autofix suggestion 3 months ago.
Comment thread opendrift_leeway_webgui/leeway/tasks.py Fixed
Comment thread opendrift_leeway_webgui/leeway/views.py Fixed
@svenseeberg
Copy link
Copy Markdown
Member Author

GeoJSON export works:
image

@svenseeberg svenseeberg force-pushed the fix/linting branch 4 times, most recently from 6dfcc37 to 4315695 Compare February 20, 2026 18:11
Comment thread opendrift_leeway_webgui/leeway/views.py Fixed
raise Http404

base_dir = Path(settings.SIMULATION_OUTPUT).resolve()
file_path = (base_dir / path).resolve()

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix

AI 3 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

@svenseeberg svenseeberg merged commit b45bb12 into main Feb 20, 2026
4 of 17 checks passed
@svenseeberg svenseeberg deleted the fix/linting branch February 20, 2026 18:18
@julled
Copy link
Copy Markdown
Collaborator

julled commented Feb 28, 2026

best would be to use autoliniting via pre-commit with ruff as linter

@svenseeberg svenseeberg changed the title Add linting results Add GeoJSON and improve API Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants