Summary
/open-path validates its input via validate_user_path (restricting to user-writable roots), but the adjacent /open-uri hands a bare string straight to xdg-open, defeating that restriction.
Location
src/game_setup_hub/api/routes/utility.py:257-267; OpenUriRequest.uri (_models.py:217-218) is an unvalidated str.
Evidence
@router.post("/open-uri")
async def open_uri(body: OpenUriRequest) -> StatusResponse:
subprocess.Popen(["xdg-open", body.uri], start_new_session=True)
Failure scenario
A caller holding the token POSTs {"uri":"file:///home/user/.ssh/"} (or an arbitrary registered-scheme URI) -> xdg-open launches the associated handler on a target /open-path would have rejected.
Fix
Validate the scheme against an allowlist (e.g. steam:, https:) and reject file://, or route file targets through validate_user_path.
Summary
/open-pathvalidates its input viavalidate_user_path(restricting to user-writable roots), but the adjacent/open-urihands a bare string straight toxdg-open, defeating that restriction.Location
src/game_setup_hub/api/routes/utility.py:257-267;OpenUriRequest.uri(_models.py:217-218) is an unvalidatedstr.Evidence
Failure scenario
A caller holding the token POSTs
{"uri":"file:///home/user/.ssh/"}(or an arbitrary registered-scheme URI) ->xdg-openlaunches the associated handler on a target/open-pathwould have rejected.Fix
Validate the scheme against an allowlist (e.g.
steam:,https:) and rejectfile://, or route file targets throughvalidate_user_path.