From a080f93ec126f88110c6cd16dafbe7180cf71bd5 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Wed, 2 Sep 2026 22:27:39 +0200 Subject: [PATCH] fix(tauri): validate game id in get_game_thumbnail and drop dbg! Security audit finding SEC-IPC-03. The thumbnail IPC command resolved `assets/{game_id}.jpg` from the resource directory without checking the ID, unlike every other command that maps a game ID to a path. A crafted ID containing path separators could therefore read any `.jpg` reachable from the resource root. The handler also still carried a `dbg!` that printed the resolved path to stderr in release builds. The command now rejects anything that is not a single normal path component with an `InvalidInput` I/O error, using the same `is_single_component_game_id` gate as run_game and start_server. The frontend already treats a failed thumbnail request as "no thumbnail". Test plan: `just clippy`, `just test`. In the app, thumbnails for catalog games still load; an invoke with game_id "../x" is rejected. Claude-Session: https://claude.ai/code/session_017C3Nbgwpdm3YNwZhhFLHwg --- crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs b/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs index aa05182..43e336a 100644 --- a/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs +++ b/crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs @@ -1539,13 +1539,17 @@ async fn get_game_thumbnail( use base64::Engine; let _app_invoke = enter_app_invoke(state.inner())?; + if !is_single_component_game_id(&game_id) { + log::warn!("Ignoring thumbnail request for invalid game id: {game_id}"); + return Err( + std::io::Error::new(std::io::ErrorKind::InvalidInput, "invalid game id").into(), + ); + } let resource_path = app_handle.path().resolve( format!("assets/{game_id}.jpg"), tauri::path::BaseDirectory::Resource, )?; - dbg!(&resource_path); - let image_data = scoped_blocking(|| std::fs::read(&resource_path))?; let base64_data = base64::engine::general_purpose::STANDARD.encode(&image_data); Ok(format!("data:image/jpeg;base64,{base64_data}"))