From 4cdd812ae3ffa535508603b2412bf4d738618bce Mon Sep 17 00:00:00 2001 From: Shane Israel Date: Sun, 30 Aug 2026 10:51:03 -0600 Subject: [PATCH] fix SSRF in game asset update via URL parser confusion --- app/client/package.json | 4 ++-- app/server/fireshare/api/game.py | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/client/package.json b/app/client/package.json index 83d46b0a..f48bc1b3 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -1,6 +1,6 @@ { "name": "fireshare", - "version": "1.7.8", + "version": "1.7.9", "private": true, "dependencies": { "@emotion/react": "^11.9.0", @@ -39,4 +39,4 @@ "build": "vite build", "preview": "vite preview" } -} \ No newline at end of file +} diff --git a/app/server/fireshare/api/game.py b/app/server/fireshare/api/game.py index ec27b259..02bbbf28 100644 --- a/app/server/fireshare/api/game.py +++ b/app/server/fireshare/api/game.py @@ -84,15 +84,19 @@ def update_game_asset(steamgriddb_id): if not url: return Response(status=400, response='url is required.') - from urllib.parse import urlparse + # Validate with urllib3's parser (the one requests uses to connect), not + # urllib.parse — the two disagree on backslash handling, which lets a URL + # like https://127.0.0.1\@cdn.steamgriddb.com pass an urlparse hostname + # check while requests actually connects to 127.0.0.1 (SSRF). + from urllib3.util import parse_url _ALLOWED_STEAMGRIDDB_HOSTS = { 'cdn2.steamgriddb.com', 'cdn.steamgriddb.com', 'steamgriddb.com', } try: - parsed = urlparse(url) - if parsed.scheme not in ('https',) or parsed.hostname not in _ALLOWED_STEAMGRIDDB_HOSTS: + parsed = parse_url(url) + if parsed.scheme not in ('https',) or parsed.host not in _ALLOWED_STEAMGRIDDB_HOSTS: return Response(status=400, response='url must be a SteamGridDB asset URL.') except Exception: return Response(status=400, response='Invalid url.')