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
This commit is contained in:
@@ -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}"))
|
||||
|
||||
Reference in New Issue
Block a user