Skip to content

Conversation

@martastain
Copy link
Member

No description provided.

@martastain martastain self-assigned this Dec 17, 2025
@martastain martastain linked an issue Dec 17, 2025 that may be closed by this pull request
@app.get("/graphiql/{path:path}", include_in_schema=False)
def explorer(path: str) -> FileResponse:
logger.debug(f"Serving GraphiQL interface: {path}")
return FileResponse(pathlib.Path("static/graphiql/") / path)

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix

AI 9 days ago

To fix this problem, user-supplied path elements must be validated before accessing the file system, so that users cannot traverse outside of static/graphiql/. The recommended best-practice is:

  1. Construct the candidate file path by joining the user input onto the static root.
  2. Normalize the resulting path using .resolve() or os.path.normpath (or .absolute() if symlinks shouldn’t be resolved).
  3. Ensure that the resolved path is still within the intended static root directory (e.g., by comparing string prefixes or using the Path.is_relative_to method in Python 3.9+).
  4. Only serve the file if it passes the check. Otherwise, return a 404 or similar error.

Apply these changes within the explorer route (lines 194–196) in ayon_server/api/server.py. Additional imports or error handling (e.g., HTTPException) may be needed if not already present.


Suggested changeset 1
ayon_server/api/server.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/ayon_server/api/server.py b/ayon_server/api/server.py
--- a/ayon_server/api/server.py
+++ b/ayon_server/api/server.py
@@ -193,9 +193,13 @@
 @app.get("/graphiql/{path:path}", include_in_schema=False)
 def explorer(path: str) -> FileResponse:
     logger.debug(f"Serving GraphiQL interface: {path}")
-    return FileResponse(pathlib.Path("static/graphiql/") / path)
+    base_dir = pathlib.Path("static/graphiql").resolve()
+    full_path = (base_dir / path).resolve()
+    if not str(full_path).startswith(str(base_dir)):
+        from fastapi import HTTPException
+        raise HTTPException(status_code=404, detail="File not found")
+    return FileResponse(full_path)
 
-
 #
 # Websocket
 #
EOF
@@ -193,9 +193,13 @@
@app.get("/graphiql/{path:path}", include_in_schema=False)
def explorer(path: str) -> FileResponse:
logger.debug(f"Serving GraphiQL interface: {path}")
return FileResponse(pathlib.Path("static/graphiql/") / path)
base_dir = pathlib.Path("static/graphiql").resolve()
full_path = (base_dir / path).resolve()
if not str(full_path).startswith(str(base_dir)):
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(full_path)


#
# Websocket
#
Copilot is powered by AI and may make mistakes. Always verify output.
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.

GraphQL: Bundle GraphIQl dependencies with the server

2 participants