fix(security): land the 2026-07 audit fixes — SSRF guards, roster lane, SYSTEM path hygiene
The low/medium findings from the July host+Windows security review, as implemented in the audit session's working tree: - Webhooks and library-art fetches refuse loopback/link-local/metadata targets and no longer follow redirects (SSRF pivots from the privileged host process). - The paired-client rosters (/clients, /native/clients) move off the streaming-client auth lane — one paired device could enumerate every other device's name + fingerprint; only the bearer/loopback console keeps them. - Device-name sanitizing extends to bidi/format control characters (spoofable rendering) via the shared native_pairing::is_spoofy_char; stream-marker quoting uses the same set. - The SYSTEM service resolves powershell by its full System32 path — CreateProcess checks the launching EXE's own directory first, so a planted powershell.exe beside the host binary would have run as SYSTEM. - The pf-vdisplay driver's opt-in file log moves from world-writable C:\Users\Public to WUDFHost's own temp dir. - GameStream pairing sessions are single-use (removed whatever the outcome). - Uninstall also removes the pf_mouse driver-store entry (rider from the virtual-HID-mouse work). - openapi.json regenerated (hardened-config-dir doc wording). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,19 @@ fn lutris_art(slug: &str) -> Artwork {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn lutris_image(kind: &str, slug: &str) -> Option<String> {
|
||||
use base64::Engine as _;
|
||||
// `slug` comes verbatim from Lutris's `pga.db` (untrusted at this layer). Reject any path
|
||||
// separator, parent ref, or NUL so a crafted slug can't escape the art roots and read an
|
||||
// arbitrary `<slug>.jpg` off disk — the bytes are base64-inlined into the `/api/v1/library`
|
||||
// JSON a paired client can GET, so an escape is an arbitrary-file-read exfil primitive
|
||||
// (security-review 2026-07-17). Real Lutris slugs are `[a-z0-9-]`.
|
||||
if slug.is_empty()
|
||||
|| slug.contains('/')
|
||||
|| slug.contains('\\')
|
||||
|| slug.contains("..")
|
||||
|| slug.contains('\0')
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let home = std::env::var_os("HOME").map(PathBuf::from)?;
|
||||
let roots = [
|
||||
home.join(".local/share/lutris"),
|
||||
|
||||
Reference in New Issue
Block a user