diff --git a/SECURITY_AUDIT_2026-08-28_GEMINI-3.7-HIGH_TEAMWORK.md b/SECURITY_AUDIT_2026-08-28_GEMINI-3.7-HIGH_TEAMWORK.md
deleted file mode 100644
index a7eed76..0000000
--- a/SECURITY_AUDIT_2026-08-28_GEMINI-3.7-HIGH_TEAMWORK.md
+++ /dev/null
@@ -1,922 +0,0 @@
-# Comprehensive Security Audit Report: lanspread P2P Game Library Sharing
-
-**Target System**: `lanspread` Peer-to-Peer Game Library Sharing Platform
-**Target Repository**: `/home/pfs/shm/ls`
-**Date of Audit**: 2026-08-28
-**Audit Scope**: All workspace crates (`crates/lanspread-*`) and Tauri GUI client (`crates/lanspread-tauri-deno-ts/`)
-**Assessment Type**: White-box Source Code Security Review, Threat Modeling, Architecture Analysis & Vulnerability Assessment
-
----
-
-## Table of Contents
-
-1. [Executive Summary & Overall Security Posture](#1-executive-summary--overall-security-posture)
-2. [Threat Model & Attack Surface Breakdown](#2-threat-model--attack-surface-breakdown)
- - [2.1 Adversary Model & Trust Assumptions](#21-adversary-model--trust-assumptions)
- - [2.2 LAN mDNS Discovery & Peer Spoofing](#22-lan-mdns-discovery--peer-spoofing)
- - [2.3 QUIC Transport, TLS 1.3 & Wire Protocol Framing](#23-quic-transport-tls-13--wire-protocol-framing)
- - [2.4 Download Path Traversal, Chunk Verification & Archive Extraction](#24-download-path-traversal-chunk-verification--archive-extraction)
- - [2.5 Tauri IPC Boundaries, Webview Isolation & Frontend Security](#25-tauri-ipc-boundaries-webview-isolation--frontend-security)
- - [2.6 Database & Persistence Integrity](#26-database--persistence-integrity)
-3. [Audit Scope & Component Coverage](#3-audit-scope--component-coverage)
-4. [Comprehensive Findings Matrix](#4-comprehensive-findings-matrix)
-5. [Detailed Vulnerability & Hardening Write-ups](#5-detailed-vulnerability--hardening-write-ups)
- - [5.1 P2P Networking, Discovery & Wire Protocol](#51-p2p-networking-discovery--wire-protocol)
- - [Finding NET-01: Unauthenticated Inbound QUIC Streams & Forged Change Hints Trigger Reflected State-Pull Flooding (High)](#finding-net-01-unauthenticated-inbound-quic-streams--forged-change-hints-trigger-reflected-state-pull-flooding)
- - [Finding NET-02: Missing IP Address & Port Validation in Discovered mDNS Services Enables Handshake Redirection to Multicast / Broadcast Targets (Medium)](#finding-net-02-missing-ip-address--port-validation-in-discovered-mdns-services-enables-handshake-redirection-to-multicast--broadcast-targets)
- - [Finding NET-03: Inbound Request Framing Uses Excessive 8 MiB Limit Allowing Stream Memory Exhaustion DoS (Medium)](#finding-net-03-inbound-request-framing-uses-excessive-8-mib-limit-allowing-stream-memory-exhaustion-dos)
- - [Finding NET-04: Global Capacity Cap in RecentCandidates Allows LAN Adversary to Deny Peer Discovery (Medium)](#finding-net-04-global-capacity-cap-in-recentcandidates-allows-lan-adversary-to-deny-peer-discovery)
- - [Finding NET-05: Unbounded Collection Deserialization in Response::decode Prior to Semantic Bounds Validation (Low)](#finding-net-05-unbounded-collection-deserialization-in-responsedecode-prior-to-semantic-bounds-validation)
- - [Finding NET-06: Unauthenticated Game Chunk and Stream-Install Egress on QUIC Server (Informational)](#finding-net-06-unauthenticated-game-chunk-and-stream-install-egress-on-quic-server)
- - [5.2 File Transfer, Storage Safety, Chunk Verification & Archive Extraction](#52-file-transfer-storage-safety-chunk-verification--archive-extraction)
- - [Finding EXP2-SEC-01: Unsafe Archive Extraction in SidecarUnpacker (Missing Post-Unpack Manifest Validation & Symlink Redirection Risk) (High)](#finding-exp2-sec-01-unsafe-archive-extraction-in-sidecarunpacker-missing-post-unpack-manifest-validation--symlink-redirection-risk)
- - [Finding EXP2-SEC-02: Unbounded Archive Decompression (Zip/RAR Bomb) Leading to Host Disk Exhaustion Denial of Service (Medium)](#finding-exp2-sec-02-unbounded-archive-decompression-ziprar-bomb-leading-to-host-disk-exhaustion-denial-of-service)
- - [Finding EXP2-SEC-03: Incomplete Path Sanitization in path_validation.rs (Omission of Windows Device Names & Trailing Dots/Spaces) (Medium)](#finding-exp2-sec-03-incomplete-path-sanitization-in-path_validationrs-omission-of-windows-device-names--trailing-dotsspaces)
- - [Finding EXP2-SEC-04: Under-Constrained game_id Validation in lanspread-proto Wire Protocol Boundary (Medium)](#finding-exp2-sec-04-under-constrained-game_id-validation-in-lanspread-proto-wire-protocol-boundary)
- - [Finding EXP2-SEC-05: Direct Pre-Verification Chunk Writes to Filesystem (Low / Defense-in-Depth)](#finding-exp2-sec-05-direct-pre-verification-chunk-writes-to-filesystem)
- - [Finding EXP2-SEC-06: Predictable Fallback State Directory in World-Writable Shared /tmp Location (Low)](#finding-exp2-sec-06-predictable-fallback-state-directory-in-world-writable-shared-tmp-location)
- - [Finding EXP2-SEC-07: Ambient File Creation in stream_install.rs Bypassing Capability-Based ConfinedGameRoot (Low / Hardening)](#finding-exp2-sec-07-ambient-file-creation-in-stream_installrs-bypassing-capability-based-confinedgameroot)
- - [5.3 Tauri Desktop Shell, IPC Boundaries, Webview Isolation & Frontend Security](#53-tauri-desktop-shell-ipc-boundaries-webview-isolation--frontend-security)
- - [Finding SEC-IPC-01: Elevated Administrator Execution of Untrusted P2P Batch Scripts with Fragile Parameter Parsing (High)](#finding-sec-ipc-01-elevated-administrator-execution-of-untrusted-p2p-batch-scripts-with-fragile-parameter-parsing)
- - [Finding SEC-IPC-02: Disabled Content Security Policy (csp: null) in Tauri Webview Configuration (High)](#finding-sec-ipc-02-disabled-content-security-policy-csp-null-in-tauri-webview-configuration)
- - [Finding SEC-IPC-03: Unvalidated game_id Path Resolution & Leftover Debug Macro in get_game_thumbnail (Medium)](#finding-sec-ipc-03-unvalidated-game_id-path-resolution--leftover-debug-macro-in-get_game_thumbnail)
- - [Finding SEC-IPC-04: Unsandboxed External Archive Extraction (unrar) for Untrusted P2P Archives (Medium)](#finding-sec-ipc-04-unsandboxed-external-archive-extraction-unrar-for-untrusted-p2p-archives)
- - [Finding SEC-IPC-05: Broad Webview Window Creation Capabilities (allow-create-webview-window) (Low)](#finding-sec-ipc-05-broad-webview-window-creation-capabilities-allow-create-webview-window)
- - [Finding SEC-FE-01: Client-Side Regular Expression Denial of Service (ReDoS) in Log Viewers (Low)](#finding-sec-fe-01-client-side-regular-expression-denial-of-service-redos-in-log-viewers)
- - [5.4 Database & Data Persistence Integrity](#54-database--data-persistence-integrity)
- - [Finding SEC-DB-01: Missing Defensive SQLite PRAGMAs (trusted_schema = OFF) on Catalog Database Pool (Low / Defense-in-Depth)](#finding-sec-db-01-missing-defensive-sqlite-pragmas-trusted_schema--off-on-catalog-database-pool)
-6. [Prioritized Recommendations & Hardening Roadmap](#6-prioritized-recommendations--hardening-roadmap)
-7. [Codebase Health & Verification Results](#7-codebase-health--verification-results)
-
----
-
-## 1. Executive Summary & Overall Security Posture
-
-`lanspread` is a peer-to-peer (P2P) desktop application designed for local area network (LAN) party environments, enabling nodes to discover neighboring peers via Multicast DNS (mDNS-SD), synchronize library metadata and real-time "Call to Play" events over QUIC/TLS 1.3, and download, unpack, and launch game packages directly across machines. The system is implemented as a Rust workspace with an asynchronous backend (`tokio`, `s2n-quic`, `sqlx`) and a desktop user interface built with Tauri (Vite, Deno, TypeScript, React).
-
-### Threat Environment
-The operational context of `lanspread` is a local network environment (LAN party, shared gaming lounge, university dormitory, or open Wi-Fi). In this environment:
-- Physical and link-layer network access is untrusted and unauthenticated.
-- Any participant on the subnet can inject raw UDP packets (including spoofed mDNS multicast on UDP 5353 and arbitrary QUIC UDP frames).
-- Any participant can establish direct QUIC connections to running peers, open bidirectional streams, and send arbitrary control or data payloads.
-- Peers may run modified, hostile versions of `lanspread` crafted to harvest metadata, exhaust node resources, disrupt network discovery, or deliver malicious archive content and scripts.
-
-### Major Architectural Strengths
-1. **Capability-Based Directory Confinement (`cap_primitives`)**: The core download engine enforces filesystem sandboxing using `ConfinedGameRoot` and handle-relative file operations with `FollowSymlinks::No`, preventing path traversal during standard chunk transfers.
-2. **Cryptographic Manifest Authority (BLAKE3)**: Game file manifests (`CatalogContentManifest`) enforce strict 4 MiB chunk-level and file-level BLAKE3 cryptographic digests. Corrupted or tampered chunks are detected during transfer.
-3. **Crash-Consistent Transactional File Management**: The download manager uses temporary write handles, journaled file ownership (`DownloadOwnershipTransaction`), and deferred sentinel writing (`version.ini`) to ensure incomplete downloads are never committed or published.
-4. **Parameterized Database Layer**: SQLite interactions in `lanspread-db` and `lanspread-compat` utilize `sqlx` prepared queries with parameter binding, eliminating classic SQL injection vulnerabilities.
-5. **Single Wire Protocol Policy**: By strictly disallowing legacy wire version fallbacks, backward-compatibility shims, and permissive serde escape hatches (`#[serde(other)]`), the wire protocol surface remains compact and auditable.
-
-### Key Security Posture Risks
-Despite these robust foundational designs, the security audit identified **20 distinct vulnerabilities and hardening deficiencies** (4 High, 7 Medium, 8 Low, 1 Informational). The primary risks include:
-- **Elevated Remote Code Execution via Untrusted P2P Scripts**: When launching games or starting dedicated servers on Windows, `lanspread` executes batch scripts (`game_setup.cmd`, `game_start.cmd`, `server_start.cmd`) downloaded from untrusted peers with elevated Administrator privileges (`runas` verb via `cmd.exe`).
-- **Reflected State-Pull Amplification & Unauthenticated Inbound Streams**: The QUIC server does not enforce Mutual TLS (mTLS) client authentication (`.with_no_client_auth()`). Unauthenticated attackers can inject forged `ChangeHint` messages impersonating other peers, triggering concurrent outbound QUIC connection floods directed at victim nodes.
-- **Disabled Webview Content Security Policy**: `tauri.conf.json` explicitly sets `"csp": null`, eliminating browser-level defenses against Cross-Site Scripting (XSS) and remote resource loading.
-- **Unchecked External Archive Extraction (`SidecarUnpacker`)**: Extraction of `.eti` (RAR) archives via the external `unrar` sidecar lacks post-extraction manifest verification, symlink auditing, and disk volume capacity preflight checks.
-
-```
-+---------------------------------------------------------------------------------------------------+
-| LANSPREAD ARCHITECTURE |
-| |
-| +---------------------------------------------------------------------------------------------+ |
-| | FRONTEND (Vite / Deno / React) | |
-| | - UI Components, CtpChat, Log Viewers (ReDoS risk: SEC-FE-01) | |
-| +---------------------------------------------------------------------------------------------+ |
-| | IPC (invoke) |
-| v |
-| +---------------------------------------------------------------------------------------------+ |
-| | TAURI DESKTOP SHELL (src-tauri/) | |
-| | - Disabled CSP ("csp": null, SEC-IPC-02) | |
-| | - Elevated UAC batch execution (cmd.exe runas, SEC-IPC-01) | |
-| | - Unvalidated thumbnail path resolver (SEC-IPC-03) | |
-| | - Sidecar Unpacker spawning unrar (EXP2-SEC-01, EXP2-SEC-02, SEC-IPC-04) | |
-| +---------------------------------------------------------------------------------------------+ |
-| | | |
-| v v |
-| +---------------------------------------+ +-------------------------------------------+ |
-| | DATABASE & COMPAT | | CORE P2P BACKEND (lanspread-peer) | |
-| | - lanspread-db / lanspread-compat | | - QUIC Server (No mTLS: NET-01) | |
-| | - Parameterized sqlx (SEC-DB-01) | | - mDNS Discovery (Candidate DoS: NET-04) | |
-| | - Manifest parser & BLAKE3 digests | | - Download Engine (ConfinedGameRoot) | |
-| +---------------------------------------+ | - Stream Install (Ambient FS: EXP2-SEC-07)| |
-| +-------------------------------------------+ |
-+---------------------------------------------------------------------------------------------------+
-```
-
----
-
-## 2. Threat Model & Attack Surface Breakdown
-
-### 2.1 Adversary Model & Trust Assumptions
-- **LAN Adversary**: An attacker with network access on the local subnet (IP layer and broadcast/multicast domain). The adversary can capture, forge, and inject UDP packets, establish QUIC connections, and execute modified protocol implementations.
-- **Untrusted Peer Content**: Games, metadata, file chunks, and archive payloads hosted by remote peers must be treated as inherently untrusted. A malicious peer may attempt to deliver malicious code, craft directory traversal sequences, or exhaust victim resources.
-- **Compromised Webview**: A potential threat where malicious HTML/JS injected via peer metadata or chat messages attempts to escape the webview sandbox and invoke native host commands via Tauri IPC.
-
-### 2.2 LAN mDNS Discovery & Peer Spoofing
-- **Component**: `crates/lanspread-mdns`, `crates/lanspread-peer/src/services/discovery.rs`, `crates/lanspread-peer/src/services/advertise.rs`.
-- **Attack Surface**: Inbound multicast DNS responses received on UDP port 5353 (`_lanspread._udp.local.`).
-- **Threats**:
- - **Peer Spoofing**: An attacker can advertise arbitrary `peer_id`s, IP addresses, and ports.
- - **Discovery Denial-of-Service**: Saturating candidate rate limiters (`RecentCandidates`) to block legitimate peer discovery.
- - **Target Redirection**: Announcing multicast, broadcast, loopback, or internal infrastructure IP addresses to force victim nodes to send QUIC handshake packets to unauthorized destinations.
-
-### 2.3 QUIC Transport, TLS 1.3 & Wire Protocol Framing
-- **Component**: `crates/lanspread-peer/src/{tls.rs, quic_runtime.rs, network.rs, services/stream.rs}`, `crates/lanspread-proto`.
-- **Attack Surface**: Inbound UDP datagrams on peer QUIC listening port (e.g. 42424), TLS 1.3 handshake negotiation, bidirectional stream framing.
-- **Threats**:
- - **Unauthenticated Stream Injection**: Inbound connections have no client identity validation, allowing arbitrary anonymous nodes to send control commands.
- - **Amplification & Reflection**: Forged state change hints causing the recipient to connect to third-party victim nodes.
- - **Stream Memory Exhaustion**: Opening maximum permitted streams (64 globally) and pushing maximum frame lengths (8 MiB control frames) of buffered JSON data.
-
-### 2.4 Download Path Traversal, Chunk Verification & Archive Extraction
-- **Component**: `crates/lanspread-peer/src/{download/, stream_install.rs, install/transaction.rs, path_validation.rs}`, `crates/lanspread-utils`.
-- **Attack Surface**: Content manifests, game IDs, relative file paths, chunk streams, and downloaded `.eti` (RAR) archives.
-- **Threats**:
- - **Path Traversal / Escape**: Crafting relative paths with `../`, UNC prefixes, drive letters, Windows device names (`CON`, `PRN`, `AUX`, `NUL`), or trailing dots/spaces to write outside the game directory.
- - **Symlink Exploitation**: Archives containing symbolic links or NTFS directory junctions pointing to sensitive system locations.
- - **Decompression Bombs**: Highly compressed archives that decompress to hundreds of gigabytes, exhausting host disk space.
- - **Pre-Verification Chunk Write Corruption**: Writing unverified chunks directly to live files before completing hash checks.
-
-### 2.5 Tauri IPC Boundaries, Webview Isolation & Frontend Security
-- **Component**: `crates/lanspread-tauri-deno-ts/src-tauri/`, `crates/lanspread-tauri-deno-ts/src/`.
-- **Attack Surface**: 24 registered Tauri IPC commands, frontend DOM rendering, IPC parameter validation, webview capability configuration.
-- **Threats**:
- - **Elevated Privilege Escalation**: Invoking batch scripts via Windows `cmd.exe` with Administrator (`runas`) UAC elevation.
- - **Cross-Site Scripting (XSS)**: Execution of untrusted scripts in the webview context in the absence of a Content Security Policy (`"csp": null`).
- - **IPC Parameter Abuse**: Passing path traversal strings into asset resolution commands (`get_game_thumbnail`).
- - **Client-Side ReDoS**: Catastrophic backtracking in user-supplied regex filters in log windows.
-
-### 2.6 Database & Persistence Integrity
-- **Component**: `crates/lanspread-db`, `crates/lanspread-compat`.
-- **Attack Surface**: SQLite database file (`game.db`), content index (`catalog-content-index-v1.jsonl`), local state storage.
-- **Threats**:
- - **SQL Injection**: Attempting to manipulate database queries via unsanitized strings (mitigated by sqlx parameter binding).
- - **Corrupted Database Execution**: Exploiting SQLite features like trusted schema or custom functions in untrusted database files.
-
----
-
-## 3. Audit Scope & Component Coverage
-
-Every crate under `crates/` and all frontend directories under `crates/lanspread-tauri-deno-ts/` were thoroughly evaluated during this security audit:
-
-| Component / Subsystem | Directory Path | Primary Responsibility | Audit Evaluation & Security Posture |
-|---|---|---|---|
-| `lanspread-peer` | `crates/lanspread-peer/` | Core P2P runtime: TLS, QUIC server/client, discovery, state sync, download manager, VFS, install transactions | **Core Focus**: Identified lack of mTLS (NET-01), mDNS IP validation gaps (NET-02), discovery candidate DoS (NET-04), archive extraction integrity (EXP2-SEC-01), and path sanitization omissions (EXP2-SEC-03). Download manager confinement (`ConfinedGameRoot`) is highly robust. |
-| `lanspread-proto` | `crates/lanspread-proto/` | Wire protocol data structures, framing constants, JSON codecs | **Evaluated**: Identified symmetric 8 MiB request frame limit (NET-03), unbounded collection deserialization (NET-05), and under-constrained wire `game_id` validation (EXP2-SEC-04). Strict serialization golden tests pass. |
-| `lanspread-mdns` | `crates/lanspread-mdns/` | Multicast DNS discovery wrapper (`mdns-sd`) | **Evaluated**: Evaluated service announcement and packet reception. Found missing semantic validation on extracted socket addresses (NET-02). |
-| `lanspread-db` | `crates/lanspread-db/` | SQLite schema, catalog content manifest models, BLAKE3 hash checks | **Evaluated**: Strong validation of path components, Windows device names, and NFC normalization. No SQL injection vulnerabilities found. |
-| `lanspread-compat` | `crates/lanspread-compat/` | Catalog bundle loading, SQLite queries, ETI migration glue | **Evaluated**: SQL queries use strict parameter bindings. Identified missing defensive SQLite PRAGMA (`trusted_schema = OFF`) (SEC-DB-01). |
-| `lanspread-utils` | `crates/lanspread-utils/` | Shared filesystem and hashing helpers | **Evaluated**: Audited for safe I/O operations and symlink protections. Conforms to security baseline. |
-| `lanspread-peer-cli` | `crates/lanspread-peer-cli/` | Scripted JSONL peer test harness and external unpacker | **Evaluated**: Audited JSONL command parser and external `unrar` invocation. Identified unsandboxed archive extraction (SEC-IPC-04). |
-| `lanspread-tauri-deno-ts` (Backend) | `crates/lanspread-tauri-deno-ts/src-tauri/` | Tauri shell, IPC command handlers, Windows script execution, sidecar unpacker | **Core Focus**: Identified elevated Administrator script execution (SEC-IPC-01), disabled CSP (SEC-IPC-02), unvalidated thumbnail resolution (SEC-IPC-03), and decompression bomb risks (EXP2-SEC-02). |
-| `lanspread-tauri-deno-ts` (Frontend) | `crates/lanspread-tauri-deno-ts/src/` | React/Deno/TS GUI client, CtpChat, log viewers, state stores | **Evaluated**: Evaluated React DOM escaping and state hydration. Identified client-side ReDoS in log window regex filters (SEC-FE-01). |
-
----
-
-## 4. Comprehensive Findings Matrix
-
-The following table summarizes all 20 findings identified across the workspace, categorized by severity and vulnerability type:
-
-| Finding ID | Severity | Type | Affected Component | Primary Location | Finding Title |
-|---|---|---|---|---|---|
-| **NET-01** | **High** | Exploitable Vulnerability | `lanspread-peer` | `src/tls.rs:126-134`
`src/services/state_sync.rs:362-389` | Unauthenticated Inbound QUIC Streams & Forged Change Hints Trigger Reflected State-Pull Flooding |
-| **NET-02** | **Medium** | Exploitable Vulnerability | `lanspread-peer` / `lanspread-mdns` | `src/services/discovery.rs:393-412`
`lanspread-mdns/src/lib.rs:273-290` | Missing IP Address & Port Validation in Discovered mDNS Services Enables Handshake Redirection to Multicast / Broadcast Targets |
-| **NET-03** | **Medium** | Exploitable Vulnerability / DoS | `lanspread-proto` / `lanspread-peer` | `lanspread-proto/src/lib.rs:13`
`src/services/stream.rs:37-41` | Inbound Request Framing Uses Excessive 8 MiB Limit Allowing Stream Memory Exhaustion DoS |
-| **NET-04** | **Medium** | Exploitable Vulnerability / DoS | `lanspread-peer` | `src/services/discovery.rs:30-67, 300-309` | Global Capacity Cap in `RecentCandidates` Allows LAN Adversary to Deny Peer Discovery |
-| **NET-05** | **Low** | Defense-in-Depth / Resource Safety | `lanspread-proto` | `src/lib.rs:718-745, 811-834` | Unbounded Collection Deserialization in `Response::decode` Prior to Semantic Bounds Validation |
-| **NET-06** | **Informational** | Architectural Policy | `lanspread-peer` | `src/services/transfer.rs:258-341`
`src/services/stream.rs:273-303` | Unauthenticated Game Chunk and Stream-Install Egress on QUIC Server |
-| **EXP2-SEC-01** | **High** | Exploitable Vulnerability | `lanspread-peer` / `src-tauri` | `src/install/transaction.rs:461-468, 514-544`
`src-tauri/src/lib.rs:3195-3238` | Unsafe Archive Extraction in `SidecarUnpacker` (Missing Post-Unpack Manifest Validation & Symlink Redirection Risk) |
-| **EXP2-SEC-02** | **Medium** | Exploitable Vulnerability / DoS | `src-tauri` / `lanspread-peer` | `src-tauri/src/lib.rs:3166-3240`
`src/install/transaction.rs:514-544` | Unbounded Archive Decompression (Zip/RAR Bomb) Leading to Host Disk Exhaustion Denial of Service |
-| **EXP2-SEC-03** | **Medium** | Exploitable Vulnerability | `lanspread-peer` | `src/path_validation.rs:14-88` | Incomplete Path Sanitization in `path_validation.rs` (Omission of Windows Device Names & Trailing Dots/Spaces) |
-| **EXP2-SEC-04** | **Medium** | Defense-in-Depth / Validation Gap | `lanspread-proto` | `src/lib.rs:769-780, 912-923` | Under-Constrained `game_id` Validation in `lanspread-proto` Wire Protocol Boundary |
-| **EXP2-SEC-05** | **Low** | Defense-in-Depth / Crash Safety | `lanspread-peer` | `src/download/transport.rs:367-402` | Direct Pre-Verification Chunk Writes to Filesystem |
-| **EXP2-SEC-06** | **Low** | Hardening / Multi-user Safety | `lanspread-peer` | `src/state_paths.rs:18-32` | Predictable Fallback State Directory in World-Writable Shared `/tmp` Location |
-| **EXP2-SEC-07** | **Low** | Hardening / Architectural Parity | `lanspread-peer` | `src/stream_install.rs:1295-1316, 1895-1900` | Ambient File Creation in `stream_install.rs` Bypassing Capability-Based `ConfinedGameRoot` |
-| **SEC-IPC-01** | **High** | Exploitable Vulnerability / RCE | `lanspread-tauri-deno-ts` (src-tauri) | `src-tauri/src/lib.rs:1474-1513, 1867-1959, 2008-2064` | Elevated Administrator Execution of Untrusted P2P Batch Scripts with Fragile Parameter Parsing |
-| **SEC-IPC-02** | **High** | Defense-in-Depth / Isolation | `lanspread-tauri-deno-ts` (src-tauri) | `src-tauri/tauri.conf.json:20-22` | Disabled Content Security Policy (`csp: null`) in Tauri Webview Configuration |
-| **SEC-IPC-03** | **Medium** | Exploitable Vulnerability | `lanspread-tauri-deno-ts` (src-tauri) | `src-tauri/src/lib.rs:1534-1552` | Unvalidated `game_id` Path Resolution & Leftover Debug Macro in `get_game_thumbnail` |
-| **SEC-IPC-04** | **Medium** | Defense-in-Depth / Sandboxing | `lanspread-peer-cli` / `src-tauri` | `lanspread-peer-cli/src/lib.rs:344-370`
`src-tauri/src/lib.rs:3195-3221` | Unsandboxed External Archive Extraction (`unrar`) for Untrusted P2P Archives |
-| **SEC-IPC-05** | **Low** | Hardening / Least Privilege | `lanspread-tauri-deno-ts` (src-tauri) | `src-tauri/capabilities/default.json:11` | Broad Webview Window Creation Capabilities (`allow-create-webview-window`) |
-| **SEC-FE-01** | **Low** | Exploitable Vulnerability / UI DoS | `lanspread-tauri-deno-ts` (frontend) | `src/MainLogsWindow.tsx:160-164`
`src/UnpackLogsWindow.tsx:109-113` | Client-Side Regular Expression Denial of Service (ReDoS) in Log Viewers |
-| **SEC-DB-01** | **Low** | Defense-in-Depth / Database | `lanspread-compat` | `src/catalog_bundle.rs:67-75`
`src/eti.rs:29-45` | Missing Defensive SQLite PRAGMAs (`trusted_schema = OFF`) on Catalog Database Pool |
-
----
-
-## 5. Detailed Vulnerability & Hardening Write-ups
-
----
-
-### 5.1 P2P Networking, Discovery & Wire Protocol
-
----
-
-#### Finding NET-01: Unauthenticated Inbound QUIC Streams & Forged Change Hints Trigger Reflected State-Pull Flooding
-
-- **Severity Rating**: **High** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H)
-- **Category**: Exploitable Vulnerability / Authentication & Amplification
-- **Affected Component**: `crates/lanspread-peer` (TLS & State Sync Subsystems)
-- **File & Line References**:
- - `crates/lanspread-peer/src/tls.rs:126-134` (`server_provider`)
- - `crates/lanspread-peer/src/services/server.rs:262-348` (`handle_peer_connection`)
- - `crates/lanspread-peer/src/services/stream.rs:265-272` (`handle_peer_stream`)
- - `crates/lanspread-peer/src/services/state_sync.rs:101-114, 362-389` (`hint_requires_pull`, `perform_refresh_for_peer`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `tls.rs`, the QUIC server TLS configuration explicitly disables client certificate authentication:
-```rust
-pub(crate) fn server_provider(identity: &PeerIdentity) -> Result {
- let provider = Arc::new(rustls::crypto::aws_lc_rs::default_provider());
- let mut config = ServerConfig::builder_with_provider(provider)
- .with_protocol_versions(&[&rustls::version::TLS13])?
- .with_no_client_auth()
- .with_single_cert(vec![identity.certificate()], identity.private_key())?;
- harden_server_config(&mut config);
- Ok(S2nRustlsServer::from(config))
-}
-```
-When inbound QUIC connections are established in `server.rs`, connecting clients are completely anonymous.
-
-When an inbound bidirectional stream delivers `Request::LibraryChanged(hint)` or `Request::CallToPlayChanged(hint)`, `handle_peer_stream` in `stream.rs` passes the `ChangeHint` structure directly to `ctx.state_sync.schedule_hint(...)` without verifying that the connection's sender owns `hint.claimed_peer_id`.
-
-In `state_sync.rs`:
-```rust
-async fn hint_requires_pull(ctx: &NetworkServiceCtx, trigger: HintTrigger) -> bool {
- let snapshot = ctx
- .peer_game_db
- .read()
- .await
- .revision_snapshot(&trigger.hint.claimed_peer_id);
- hint_requires_pull_from_snapshot(ctx.peer_id, trigger, snapshot.as_ref())
-}
-```
-If `claimed_peer_id` matches a known peer in `peer_game_db` and the hint specifies an incremented revision or new session ID, `hint_requires_pull` evaluates to `true`. This causes `state_sync` to immediately queue an outbound `perform_refresh_for_peer`, triggering a full outbound QUIC connection and `Hello` snapshot pull targeting the victim peer (`claimed_peer_id`).
-
-##### Threat & Impact Analysis
-1. **Reflected DoS / Network Amplification**: An attacker on the LAN can establish unauthenticated QUIC streams to every peer on the subnet and send forged `ChangeHint` messages claiming `Peer_Victim` has published revision `999999`. Every peer node on the network will simultaneously initiate an outbound QUIC connection to `Peer_Victim` and pull its full `HelloSnapshot`, exhausting `Peer_Victim`'s network bandwidth, QUIC connection limits, and CPU.
-2. **Unauthenticated Information Harvesting**: Any anonymous client can connect to any running peer and issue `Request::Hello` or `Request::Ping` to extract complete user display names, full shared game catalogs, and real-time Call-to-Play chat messages without presenting credentials.
-
-##### Concrete Attack Scenario / Reproduction Steps
-1. An attacker on the LAN listens to mDNS broadcasts and identifies `Peer_Victim` (`PeerId_V`, IP `192.168.1.50:42424`) and 30 other participating peers (`Peer_1` through `Peer_30`).
-2. The attacker opens a standard QUIC connection to `Peer_1` (`192.168.1.10:42424`).
-3. Over a bidirectional stream, the attacker sends:
- ```json
- {"LibraryChanged":{"claimed_peer_id":"","runtime_session_id":"00000000000000000000000000000000","revision":999999}}
- ```
-4. `Peer_1` receives the frame, observes that `PeerId_V` has a new revision, and initiates `perform_refresh_for_peer(PeerId_V)`.
-5. The attacker repeats steps 2–3 across `Peer_2` through `Peer_30`.
-6. All 30 peers concurrently open QUIC connections to `Peer_Victim` and request full library snapshots, saturating `Peer_Victim`'s connection permits and CPU.
-
-##### Actionable Remediation Guidance
-1. **Enforce Mutual TLS (mTLS)**:
- - Configure `ServerConfig` to require client certificates via a custom `ClientCertVerifier` that validates the client's Ed25519 self-signed certificate and extracts their public key.
- - Configure `ClientConfig` to present the local `PeerIdentity` certificate during outbound handshakes.
-2. **Bind Inbound Commands to Verified Identity**:
- - Extract the authenticated client `PeerId` from the TLS connection metadata in `handle_peer_connection`.
- - In `stream.rs`, assert `hint.claimed_peer_id == authenticated_peer_id`. Reject and drop any hint where the claimed identity does not match the TLS identity.
-
----
-
-#### Finding NET-02: Missing IP Address & Port Validation in Discovered mDNS Services Enables Handshake Redirection to Multicast / Broadcast Targets
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:M)
-- **Category**: Exploitable Vulnerability / Input Validation
-- **Affected Component**: `crates/lanspread-peer` (Discovery) / `crates/lanspread-mdns`
-- **File & Line References**:
- - `crates/lanspread-peer/src/services/discovery.rs:393-412` (`validated_candidate_endpoint`)
- - `crates/lanspread-mdns/src/lib.rs:273-290` (`MdnsBrowser::handle_service_resolved`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `discovery.rs`:
-```rust
-fn validated_candidate_endpoint(info: &MdnsPeerInfo) -> Option {
- if info.proto_ver != Some(PROTOCOL_VERSION) {
- return None;
- }
- let Some(peer_id) = info.peer_id else {
- return None;
- };
- Some(PeerEndpoint::new(peer_id, info.addr))
-}
-```
-Neither `lanspread-mdns` nor `discovery.rs` validates the socket address `info.addr`. The application does not check if `info.addr.ip()` is a multicast address (`224.0.0.0/4`, `ff00::/8`), a broadcast address (`255.255.255.255`), an unspecified address (`0.0.0.0`, `::`), or if `info.addr.port() == 0`.
-
-##### Threat & Impact Analysis
-An attacker broadcasting forged mDNS records can specify destination IP addresses pointing to multicast (`224.0.0.1`), broadcast (`255.255.255.255`), or internal infrastructure ports. When `DiscoveryWorker` processes these candidates, it spawns `run_protocol_negotiation` which calls `connector.connect(&endpoint)`. This causes `s2n-quic` to transmit UDP Initial handshake packets to multicast or broadcast addresses, polluting network segments and triggering unexpected socket errors.
-
-##### Concrete Attack Scenario / PoC
-1. Attacker transmits an mDNS response for service `_lanspread._udp.local.` with TXT record `proto_ver=8`, `peer_id=`, and host address `224.0.0.251:42424`.
-2. `MdnsBrowser` parses the record and sends an `MdnsService` event with `addr = 224.0.0.251:42424`.
-3. `validated_candidate_endpoint` accepts the endpoint.
-4. `run_peer_discovery` dispatches a QUIC connection attempt to `224.0.0.251:42424`.
-
-##### Actionable Remediation Guidance
-Implement an admissibility filter for discovered IP addresses and ports in `discovery.rs`:
-```rust
-fn is_admissible_peer_ip(ip: std::net::IpAddr) -> bool {
- match ip {
- std::net::IpAddr::V4(v4) => !v4.is_unspecified() && !v4.is_multicast() && !v4.is_broadcast(),
- std::net::IpAddr::V6(v6) => !v6.is_unspecified() && !v6.is_multicast(),
- }
-}
-
-fn validated_candidate_endpoint(info: &MdnsPeerInfo) -> Option {
- if info.proto_ver != Some(PROTOCOL_VERSION) {
- return None;
- }
- if info.addr.port() == 0 || !is_admissible_peer_ip(info.addr.ip()) {
- log::debug!("Ignoring peer at {} with invalid IP/port", info.addr);
- return None;
- }
- let Some(peer_id) = info.peer_id else {
- return None;
- };
- Some(PeerEndpoint::new(peer_id, info.addr))
-}
-```
-
----
-
-#### Finding NET-03: Inbound Request Framing Uses Excessive 8 MiB Limit Allowing Stream Memory Exhaustion DoS
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:M)
-- **Category**: Exploitable Vulnerability / Denial of Service
-- **Affected Component**: `crates/lanspread-proto`, `crates/lanspread-peer` (Stream & Quic Runtime)
-- **File & Line References**:
- - `crates/lanspread-proto/src/lib.rs:13` (`MAX_CONTROL_FRAME_BYTES`)
- - `crates/lanspread-peer/src/quic_runtime.rs:59, 83` (`quic_server_limits`)
- - `crates/lanspread-peer/src/services/stream.rs:37-41` (`control_codec`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `lanspread-proto/src/lib.rs`:
-```rust
-pub const MAX_CONTROL_FRAME_BYTES: usize = 8 * 1024 * 1024; // 8 MiB
-```
-In `stream.rs`:
-```rust
-fn control_codec() -> LengthDelimitedCodec {
- LengthDelimitedCodec::builder()
- .max_frame_length(MAX_CONTROL_FRAME_BYTES)
- .new_codec()
-}
-```
-All valid inbound `Request` variants (`Ping`, `Hello`, `LibraryChanged`, `CallToPlayChanged`, `GetGameFileChunk`, `StreamInstall`) encode to less than 1,024 bytes. However, `handle_peer_stream` configures `FramedRead` using `MAX_CONTROL_FRAME_BYTES` (8 MiB) for incoming request streams. With `MAX_GLOBAL_CONTROL_STREAM_TASKS = 64`, up to 64 concurrent streams can each buffer up to 8 MiB before `serde_json` parsing fails.
-
-##### Threat & Impact Analysis
-An attacker opening 64 concurrent streams and pushing 8 MiB payloads of formatted JSON whitespace or long strings forces the victim process to allocate and buffer `64 * 8 MiB = 512 MiB` of raw payload in memory. On RAM-constrained gaming devices, this spike can induce out-of-memory (OOM) termination.
-
-##### Actionable Remediation Guidance
-Split `MAX_CONTROL_FRAME_BYTES` into asymmetric bounds for requests versus responses:
-```rust
-pub const MAX_REQUEST_FRAME_BYTES: usize = 64 * 1024; // 64 KiB
-pub const MAX_RESPONSE_FRAME_BYTES: usize = 8 * 1024 * 1024; // 8 MiB (for HelloSnapshot)
-```
-Configure `FramedRead` in `handle_peer_stream` to use `MAX_REQUEST_FRAME_BYTES`.
-
----
-
-#### Finding NET-04: Global Capacity Cap in `RecentCandidates` Allows LAN Adversary to Deny Peer Discovery
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:M)
-- **Category**: Exploitable Vulnerability / Denial of Service
-- **Affected Component**: `crates/lanspread-peer` (Discovery)
-- **File & Line References**:
- - `crates/lanspread-peer/src/services/discovery.rs:30-67, 300-309` (`RecentCandidates`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `discovery.rs`:
-```rust
-const MAX_ACTIVE_DISCOVERY_CANDIDATES: usize = 64;
-
-impl RecentCandidates {
- fn try_record(&mut self, candidate: PeerEndpoint, now: tokio::time::Instant) -> bool {
- self.expire(now);
- if self.entries.iter().any(|(endpoint, _)| {
- endpoint.peer_id == candidate.peer_id || endpoint.addr == candidate.addr
- }) || self.entries.len() >= MAX_ACTIVE_DISCOVERY_CANDIDATES
- {
- return false;
- }
- self.entries
- .push_back((candidate, now + DISCOVERY_CANDIDATE_COOLDOWN));
- true
- }
-}
-```
-If `self.entries.len() >= 64`, `try_record` returns `false` for all newly discovered candidate endpoints. In `run_peer_discovery`, `!candidate_is_admissible(...)` causes the discovery loop to log a warning and discard the new peer.
-
-##### Threat & Impact Analysis
-An attacker broadcasting 64 fake mDNS service announcements with distinct `PeerId`s and ports will saturate `RecentCandidates` within milliseconds. Once saturated, all legitimate new peers joining the LAN will be rejected and ignored for the 5-second cooldown window. Repeating this flood every 5 seconds creates a permanent discovery blackout.
-
-##### Actionable Remediation Guidance
-Implement FIFO/LRU eviction in `RecentCandidates` when capacity is reached instead of dropping new candidates:
-```rust
-if self.entries.len() >= MAX_ACTIVE_DISCOVERY_CANDIDATES {
- self.entries.pop_front();
-}
-self.entries.push_back((candidate, now + DISCOVERY_CANDIDATE_COOLDOWN));
-```
-
----
-
-#### Finding NET-05: Unbounded Collection Deserialization in `Response::decode` Prior to Semantic Bounds Validation
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L)
-- **Category**: Defense-in-Depth / Resource Safety
-- **Affected Component**: `crates/lanspread-proto`
-- **File & Line References**:
- - `crates/lanspread-proto/src/lib.rs:718-726, 739-745, 811-834`
-
-##### Vulnerability Description & Root Cause Analysis
-`Response::decode` executes `serde_json::from_slice::(bytes)` before calling semantic validation methods (`LibrarySnapshot::validate()`, `CallToPlayAuthorSnapshot::validate()`). A malicious peer can construct an 8 MiB response containing 100,000 minimal JSON elements in `Vec`, forcing full heap allocation before semantic validation rejects the payload.
-
-##### Actionable Remediation Guidance
-Apply streaming length checks or implement bounded deserialization helpers for large collections during the `serde` pass.
-
----
-
-#### Finding NET-06: Unauthenticated Game Chunk and Stream-Install Egress on QUIC Server
-
-- **Severity Rating**: **Informational**
-- **Category**: Architectural Policy / Access Control
-- **Affected Component**: `crates/lanspread-peer` (Transfer & Stream Services)
-- **File & Line References**:
- - `crates/lanspread-peer/src/services/transfer.rs:258-341`
- - `crates/lanspread-peer/src/services/stream.rs:273-303`
-
-##### Vulnerability Description & Root Cause Analysis
-`handle_peer_stream` allows any connected client to request arbitrary game file chunks (`Request::GetGameFileChunk`) or initiate streamed RAR installation (`Request::StreamInstall`). `admit_outbound_transfer` verifies that the game is in the catalog and ready, but performs no authentication or caller authorization.
-
-##### Actionable Remediation Guidance
-Combine with Finding NET-01 (mTLS) to record authenticated `PeerId`s for all file transfers, enabling audit logging and per-peer transfer throttling.
-
----
-
-### 5.2 File Transfer, Storage Safety, Chunk Verification & Archive Extraction
-
----
-
-#### Finding EXP2-SEC-01: Unsafe Archive Extraction in `SidecarUnpacker` (Missing Post-Unpack Manifest Validation & Symlink Redirection Risk)
-
-- **Severity Rating**: **High** (CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)
-- **Category**: Exploitable Vulnerability / Path Traversal & Integrity
-- **Affected Component**: `crates/lanspread-peer` (`install/transaction.rs`), `crates/lanspread-tauri-deno-ts` (`src-tauri/src/lib.rs`)
-- **File & Line References**:
- - `crates/lanspread-peer/src/install/transaction.rs:461-468, 490-495, 514-544` (`install_inner`, `unpack_archives`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:3195-3238` (`run_unrar_sidecar`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `install/transaction.rs`, the game installation workflow executes:
-```rust
-let staging = installing_dir(game_root);
-prepare_owned_empty_dir(&staging)?;
-root_capability.sync_game_root()?;
-unpack_archives(game_root, &staging, unpacker, cancel_token).await?;
-rename_path(&staging, &local)
- .wrap_err_with(|| format!("failed to promote install for {id}"))?;
-root_capability.sync_game_root()?;
-```
-In `src-tauri/src/lib.rs`, `run_unrar_sidecar` spawns `unrar x -p- archive.eti -y -o destination_dir`.
-When `unrar x` completes with exit status 0, `install_inner` immediately executes `rename_path(&staging, &local)`.
-
-**Root Cause**:
-1. There is **no post-extraction inspection or validation** of the files materialized in `staging`.
-2. The application does not check whether `unrar` created symlinks or Windows directory junctions pointing outside `staging` / `local`.
-3. The application does not verify extracted files against the catalog manifest's expected file list (`CatalogContentManifest`) or compute BLAKE3 hashes of extracted contents.
-4. Unlike `stream_install.rs` (which explicitly validates each entry against `CatalogExtractedEntry` and checks BLAKE3 hashes), the `.eti` archive path completely trusts the external `unrar` tool output.
-
-##### Threat & Impact Analysis
-If a malicious peer provides an `.eti` (RAR) archive containing symlinks (e.g. `link -> /home/victim/.ssh/` or `link -> C:\Windows\`), `unrar x` may extract these symlinks depending on the platform and unrar build. When `lanspread` later traverses `local/` during launch configuration (`apply_launch_settings_once`), it can read or modify files outside the game root.
-
-##### Concrete Attack Scenario / PoC
-1. Attacker creates an `.eti` archive containing:
- - Entry 1: Symlink `config -> /home/victim/.config/`
- - Entry 2: File `config/autostart.sh`
-2. Victim downloads and installs the game.
-3. `unrar x` extracts the symlink and payload into `.local.installing`.
-4. `install_inner` renames `.local.installing` to `local/` without inspecting contents.
-5. Subsequent operations traversing `local/` follow the symlink outside the game directory.
-
-##### Actionable Remediation Guidance
-Before calling `rename_path(&staging, &local)` in `install_inner`, execute a mandatory audit of `staging`:
-```rust
-for entry in walkdir::WalkDir::new(&staging) {
- let entry = entry?;
- let meta = std::fs::symlink_metadata(entry.path())?;
- if meta.file_type().is_symlink() {
- eyre::bail!("Unsafe symlink detected in extracted archive: {}", entry.path().display());
- }
-}
-```
-Verify that all regular files match the expected sizes and BLAKE3 digests in the catalog manifest.
-
----
-
-#### Finding EXP2-SEC-02: Unbounded Archive Decompression (Zip/RAR Bomb) Leading to Host Disk Exhaustion Denial of Service
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)
-- **Category**: Exploitable Vulnerability / Denial of Service
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (`src-tauri`), `crates/lanspread-peer` (`install/transaction.rs`)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:3166-3240` (`run_unrar_sidecar`)
- - `crates/lanspread-peer/src/install/transaction.rs:514-544`
-
-##### Vulnerability Description & Root Cause Analysis
-In `run_unrar_sidecar`, `ScopedProcess::spawn` captures stdout/stderr up to `UNRAR_LOG_CAPTURE_LIMIT` (1 MB), but enforces **no limit on the volume of uncompressed data written to disk**. The application does not check available disk space prior to spawning `unrar`, nor does it monitor staging folder size during extraction.
-
-##### Threat & Impact Analysis
-An attacker delivering a highly compressed RAR bomb (e.g. a 20 MB archive that expands to 500 GB of zeros) will cause `unrar` to consume all available disk space (`ENOSPC`), causing system-wide application crashes, database corruption, and host instability.
-
-##### Actionable Remediation Guidance
-1. Query available disk space using `fs2::available_space` prior to extraction, ensuring `available_space >= expected_uncompressed_bytes + SAFETY_BUFFER`.
-2. Enforce a maximum uncompressed extraction ceiling (e.g., `MAX_CATALOG_TOTAL_BYTES`).
-
----
-
-#### Finding EXP2-SEC-03: Incomplete Path Sanitization in `path_validation.rs` (Omission of Windows Device Names & Trailing Dots/Spaces)
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:M/A:L)
-- **Category**: Exploitable Vulnerability / Windows Path Traversal
-- **Affected Component**: `crates/lanspread-peer` (`path_validation.rs`)
-- **File & Line References**:
- - `crates/lanspread-peer/src/path_validation.rs:14-40` (`sanitize_relative_path`)
- - `crates/lanspread-peer/src/path_validation.rs:46-88` (`validate_relative_path`)
-
-##### Vulnerability Description & Root Cause Analysis
-`path_validation.rs` checks for empty strings, null bytes, UNC prefixes (`//`), and drive separators (`:/`). However, unlike `download/manifest.rs:381-391` and `content_manifest/path.rs:194-204`:
-1. It does **not** check for Windows DOS reserved device names (`CON`, `PRN`, `AUX`, `NUL`, `COM1`..`COM9`, `LPT1`..`LPT9`).
-2. It does **not** reject components ending in dots or spaces (`.` or `' '`), which Win32 file APIs strip automatically (e.g. `file.txt.` becomes `file.txt`).
-3. It does not check for drive-relative paths such as `C:temp`.
-
-##### Threat & Impact Analysis
-On Windows hosts, creating or resolving files named `CON` or `AUX` causes file APIs to block indefinitely or interact with console devices, leading to Denial of Service or unhandled I/O failures.
-
-##### Actionable Remediation Guidance
-Harmonize `path_validation.rs` with `content_manifest/path.rs`:
-```rust
-fn validate_component(component: &str) -> eyre::Result<()> {
- if component.is_empty() || matches!(component, "." | "..") {
- eyre::bail!("Invalid component: {component:?}");
- }
- if component.ends_with([' ', '.']) {
- eyre::bail!("Path component has trailing dot or space: {component}");
- }
- if is_windows_device_name(component) {
- eyre::bail!("Path uses Windows device name: {component}");
- }
- Ok(())
-}
-```
-
----
-
-#### Finding EXP2-SEC-04: Under-Constrained `game_id` Validation in `lanspread-proto` Wire Protocol Boundary
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)
-- **Category**: Defense-in-Depth / Input Validation
-- **Affected Component**: `crates/lanspread-proto`
-- **File & Line References**:
- - `crates/lanspread-proto/src/lib.rs:769-780, 912-923` (`validate_game_id`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `lanspread-proto`, wire requests (`Request::GetGameFileChunk`, `Request::StreamInstall`) validate `game_id` via:
-```rust
-fn validate_game_id(game_id: &str) -> Result<(), ControlValidationError> {
- if game_id.trim().is_empty() {
- return Err(ControlValidationError::EmptyField { field: "game ID" });
- }
- if game_id.len() > MAX_GAME_ID_BYTES {
- return Err(ControlValidationError::FieldTooLong { field: "game ID", maximum: MAX_GAME_ID_BYTES });
- }
- Ok(())
-}
-```
-This allows path traversal characters (`../`, `/`, `\`), null bytes, and control characters through the wire protocol decoding step. In contrast, `download/manifest.rs` and `content_manifest/path.rs` enforce single component checks, NFC normalization, and reserved directory name rejection.
-
-##### Actionable Remediation Guidance
-Add character and component constraints to `validate_game_id` in `lanspread-proto`:
-```rust
-if game_id.contains(['/', '\\', '\0']) || game_id.contains("..") {
- return Err(ControlValidationError::InvalidPathCharacters { field: "game ID" });
-}
-```
-
----
-
-#### Finding EXP2-SEC-05: Direct Pre-Verification Chunk Writes to Filesystem
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)
-- **Category**: Defense-in-Depth / Crash Consistency
-- **Affected Component**: `crates/lanspread-peer` (`download/transport.rs`)
-- **File & Line References**:
- - `crates/lanspread-peer/src/download/transport.rs:367-402` (`receive_chunk`)
-
-##### Vulnerability Description & Root Cause Analysis
-In `receive_chunk`, raw incoming bytes from peer streams are written directly to the target file via `write_chunk_bytes(&mut file, &bytes)` before `verifier.finish(...)` completes the BLAKE3 hash check. While uncommitted files are guarded by `version.ini` deferral and cleanup journals, a host crash or sudden power failure during an active download leaves corrupt chunk bytes on disk.
-
-##### Actionable Remediation Guidance
-Buffer the chunk in memory (chunks are up to 4 MiB) and compute the BLAKE3 hash before writing the verified buffer to disk.
-
----
-
-#### Finding EXP2-SEC-06: Predictable Fallback State Directory in World-Writable Shared `/tmp` Location
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N)
-- **Category**: Hardening / Multi-User Safety
-- **Affected Component**: `crates/lanspread-peer` (`state_paths.rs`)
-- **File & Line References**:
- - `crates/lanspread-peer/src/state_paths.rs:18-32` (`resolve_state_dir`)
-
-##### Vulnerability Description & Root Cause Analysis
-If neither `LANSPREAD_STATE_DIR` nor `HOME`/`USERPROFILE` environment variables are set, `resolve_state_dir` falls back to `std::env::temp_dir().join("lanspread")` (`/tmp/lanspread`). On multi-user systems, `/tmp` is world-writable, allowing a local attacker to pre-create `/tmp/lanspread` with malicious permissions or symlinks.
-
-##### Actionable Remediation Guidance
-Incorporate the process UID into the fallback path on Unix (`/tmp/lanspread-`) and enforce `0o700` directory permissions upon creation.
-
----
-
-#### Finding EXP2-SEC-07: Ambient File Creation in `stream_install.rs` Bypassing Capability-Based `ConfinedGameRoot`
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)
-- **Category**: Hardening / Architectural Parity
-- **Affected Component**: `crates/lanspread-peer` (`stream_install.rs`)
-- **File & Line References**:
- - `crates/lanspread-peer/src/stream_install.rs:1295-1316, 1895-1900`
-
-##### Vulnerability Description & Root Cause Analysis
-Unlike the standard download manager which uses capability-based `ConfinedGameRoot` with `FollowSymlinks::No`, `stream_install.rs` uses ambient `std::fs::create_dir_all` and `File::create(&path)`. While staging paths are validated as empty on initialization, using ambient filesystem APIs diverges from the project's capability-based confinement architecture.
-
-##### Actionable Remediation Guidance
-Refactor `StreamInstallReceiveState` to operate through `ConfinedGameRoot` or `MutationGameRoot` handles with `FollowSymlinks::No`.
-
----
-
-### 5.3 Tauri Desktop Shell, IPC Boundaries, Webview Isolation & Frontend Security
-
----
-
-#### Finding SEC-IPC-01: Elevated Administrator Execution of Untrusted P2P Batch Scripts with Fragile Parameter Parsing
-
-- **Severity Rating**: **High** (CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)
-- **Category**: Exploitable Vulnerability / Remote Code Execution & Privilege Escalation
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (`src-tauri/src/lib.rs`)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1474-1487` (`sanitize_username`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1506-1513` (`script_params_with_mode`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1555-1582` (`run_as_admin_detached`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1818-1864` (`run_as_admin_and_wait`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1867-1959` (`run_game_windows`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:2008-2064` (`start_server_windows`)
-
-##### Vulnerability Description & Root Cause Analysis
-When running a game or starting a dedicated server on Windows, `run_game_windows` and `start_server_windows` execute setup and launch scripts (`game_setup.cmd`, `game_start.cmd`, `server_start.cmd`) located in the downloaded game directory using `ShellExecuteExW` / `ShellExecuteW` with `lpVerb = "runas"`, triggering Administrator UAC elevation:
-```rust
-// src-tauri/src/lib.rs:1913-1918
-run_as_admin_and_wait(
- "cmd.exe",
- &setup_params,
- &game_dir,
- windows::Win32::UI::WindowsAndMessaging::SW_HIDE,
-)
-```
-These scripts originate from untrusted remote P2P peers.
-
-Furthermore, parameters are assembled via:
-```rust
-format!(
- r#"/d /s {cmd_mode} ""{}" "local" "{}" "{}" "{}"""#,
- script_path.display(),
- id,
- settings.language,
- settings.username,
-)
-```
-`sanitize_username` only strips control characters, `"`, and `%` (`!c.is_control() && *c != '"' && *c != '%'`). It does **not** filter shell meta-characters such as `&`, `|`, `^`, `<`, `>`, `(`, `)`.
-
-##### Threat & Impact Analysis
-- **Elevated Remote Code Execution**: An attacker sharing a game package on the LAN containing a malicious `game_setup.cmd` achieves full Administrator execution on the victim machine as soon as the user clicks "Play".
-- **Parameter Injection**: Unsanitized username or language values containing `&` or `|` can trigger arbitrary command chaining inside `cmd.exe`.
-
-##### Concrete Attack Scenario / PoC
-1. Attacker hosts a game on the LAN with a crafted `game_setup.cmd` that executes administrative commands (e.g. modifying system registry or installing persistent services).
-2. Victim downloads the game via P2P and clicks "Play".
-3. `lanspread` prompts the user with a standard Windows UAC dialog (invoking `cmd.exe` as Administrator).
-4. Upon user confirmation, the attacker's script executes with full Local Administrator privileges.
-
-##### Actionable Remediation Guidance
-1. **Enforce Cryptographic Script Verification**: Before executing any `.cmd` or executable file, verify its exact BLAKE3 digest against the authoritative `CatalogContentManifest`. Reject execution if the hash does not match.
-2. **Strict Username Whitelist**: Constrain username and language parameters to `[a-zA-Z0-9_-]`.
-3. **Avoid Shell Invocation**: Execute target binaries directly rather than wrapping them in `cmd.exe /c` where feasible.
-
----
-
-#### Finding SEC-IPC-02: Disabled Content Security Policy (`csp: null`) in Tauri Webview Configuration
-
-- **Severity Rating**: **High** (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N)
-- **Category**: Defense-in-Depth / Webview Isolation
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (`src-tauri/tauri.conf.json`)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src-tauri/tauri.conf.json:20-22`
-
-##### Vulnerability Description & Root Cause Analysis
-In `tauri.conf.json`:
-```json
-"app": {
- "security": {
- "csp": null
- }
-}
-```
-Setting `"csp": null` explicitly disables Tauri's Content Security Policy injection.
-
-##### Threat & Impact Analysis
-Without a CSP, the webview renderer has no browser-level restrictions on network connections, script sources, or object embedding. If an XSS vulnerability occurs anywhere in the frontend (e.g. via peer chat messages, manipulated game metadata, or a compromised frontend dependency), an attacker can execute arbitrary scripts, connect to external servers, or invoke accessible Tauri IPC commands.
-
-##### Actionable Remediation Guidance
-Define a strict Content Security Policy in `tauri.conf.json`:
-```json
-"security": {
- "csp": "default-src 'self'; img-src 'self' data: asset:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src ipc:; frame-src 'none'; object-src 'none'; base-uri 'none';"
-}
-```
-
----
-
-#### Finding SEC-IPC-03: Unvalidated `game_id` Path Resolution & Leftover Debug Macro in `get_game_thumbnail`
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)
-- **Category**: Exploitable Vulnerability / Path Resolution
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (`src-tauri/src/lib.rs`)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:1534-1552` (`get_game_thumbnail`)
-
-##### Vulnerability Description & Root Cause Analysis
-`get_game_thumbnail` is implemented as:
-```rust
-#[tauri::command]
-async fn get_game_thumbnail(
- game_id: String,
- app_handle: tauri::AppHandle,
- state: tauri::State<'_, LanSpreadState>,
-) -> tauri::Result {
- use base64::Engine;
-
- let _app_invoke = enter_app_invoke(state.inner())?;
- 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}"))
-}
-```
-Unlike `run_game_windows`, `get_game_thumbnail` does not call `is_single_component_game_id(&game_id)`. Passing `../` sequences allows resolving and reading arbitrary `.jpg` files from the resource bundle. Additionally, line 1547 contains `dbg!(&resource_path)`, which emits filesystem paths to stderr in release builds.
-
-##### Actionable Remediation Guidance
-Validate `game_id` with `is_single_component_game_id(&game_id)` and remove the `dbg!` macro.
-
----
-
-#### Finding SEC-IPC-04: Unsandboxed External Archive Extraction (`unrar`) for Untrusted P2P Archives
-
-- **Severity Rating**: **Medium** (CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:U/C:M/I:M/A:N)
-- **Category**: Defense-in-Depth / Subprocess Sandboxing
-- **Affected Component**: `crates/lanspread-peer-cli`, `crates/lanspread-tauri-deno-ts` (`src-tauri`)
-- **File & Line References**:
- - `crates/lanspread-peer-cli/src/lib.rs:344-370` (`ExternalUnrarUnpacker`)
- - `crates/lanspread-tauri-deno-ts/src-tauri/src/lib.rs:3195-3221` (`run_unrar_sidecar`)
-
-##### Vulnerability Description & Root Cause Analysis
-`ExternalUnrarUnpacker` and `run_unrar_sidecar` invoke `binaries/unrar` directly without OS-level sandboxing (e.g. Landlock, pledge, AppContainer) or symlink stripping flags (`-sl-`). If an untrusted RAR contains directory traversal paths or symlinks, unrar could write outside the destination directory.
-
-##### Actionable Remediation Guidance
-Pass symlink-disabling flags (`-sl-`) to `unrar` and verify that all extracted files reside strictly within the destination staging directory.
-
----
-
-#### Finding SEC-IPC-05: Broad Webview Window Creation Capabilities (`allow-create-webview-window`)
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N)
-- **Category**: Hardening / Least Privilege
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (`src-tauri/capabilities/default.json`)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src-tauri/capabilities/default.json:11`
-
-##### Vulnerability Description & Root Cause Analysis
-`capabilities/default.json` grants `"core:webview:allow-create-webview-window"` to the default webview. If an XSS vulnerability occurs, script injection could dynamically spawn unmonitored browser windows.
-
-##### Actionable Remediation Guidance
-Statically declare companion windows (`main-logs`, `unpack-logs`) in `tauri.conf.json` and remove dynamic window creation permissions from `default.json`.
-
----
-
-#### Finding SEC-FE-01: Client-Side Regular Expression Denial of Service (ReDoS) in Log Viewers
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L)
-- **Category**: Exploitable Vulnerability / UI DoS
-- **Affected Component**: `crates/lanspread-tauri-deno-ts` (Frontend)
-- **File & Line References**:
- - `crates/lanspread-tauri-deno-ts/src/MainLogsWindow.tsx:160-164`
- - `crates/lanspread-tauri-deno-ts/src/UnpackLogsWindow.tsx:109-113`
-
-##### Vulnerability Description & Root Cause Analysis
-User-supplied filter strings are compiled via `new RegExp(regexInput, 'i')` and executed synchronously over thousands of log lines on every keypress. A pattern with nested quantifiers (e.g. `(a+)+$`) triggers catastrophic backtracking, freezing the UI thread.
-
-##### Actionable Remediation Guidance
-Enforce a length limit on `regexInput`, debounce execution, or execute regex evaluation inside a Web Worker.
-
----
-
-### 5.4 Database & Data Persistence Integrity
-
----
-
-#### Finding SEC-DB-01: Missing Defensive SQLite PRAGMAs (`trusted_schema = OFF`) on Catalog Database Pool
-
-- **Severity Rating**: **Low** (CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N)
-- **Category**: Defense-in-Depth / Database Hardening
-- **Affected Component**: `crates/lanspread-compat`
-- **File & Line References**:
- - `crates/lanspread-compat/src/catalog_bundle.rs:67-75`
- - `crates/lanspread-compat/src/eti.rs:29-45`
-
-##### Vulnerability Description & Root Cause Analysis
-When opening SQLite database pools, `SqliteConnectOptions` configures `.read_only(true)`, but does not explicitly set `PRAGMA trusted_schema = OFF;` or `PRAGMA cell_size_check = ON;`. Setting `trusted_schema = OFF` ensures that SQLite triggers or virtual table functions in loaded databases cannot execute untrusted code.
-
-##### Actionable Remediation Guidance
-Configure connection pools with defensive SQLite PRAGMAs:
-```rust
-SqliteConnectOptions::new()
- .filename(db_path)
- .read_only(true)
- .pragma("trusted_schema", "OFF")
- .pragma("cell_size_check", "ON")
-```
-
----
-
-## 6. Prioritized Recommendations & Hardening Roadmap
-
-To systematically resolve the identified findings, the remediation efforts are prioritized into three actionable tiers:
-
-### Tier 1: Immediate Remediation (High Priority / P0)
-*Target Timeline: Immediate release / next sprint*
-1. **Mitigate Elevated Batch Script Execution (SEC-IPC-01)**:
- - Enforce cryptographic BLAKE3 manifest verification for all `.cmd` and `.exe` scripts prior to execution.
- - Enforce strict username/language character sanitization (`[a-zA-Z0-9_-]`).
-2. **Deploy Strict Webview Content Security Policy (SEC-IPC-02)**:
- - Configure `"csp": "default-src 'self'; img-src 'self' data: asset:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src ipc:; frame-src 'none'; object-src 'none'; base-uri 'none';"` in `tauri.conf.json`.
-3. **Enforce Mutual TLS & Inbound Identity Binding (NET-01)**:
- - Require client certificates in TLS 1.3 server config and verify that inbound `ChangeHint` messages originate from the connection's authenticated `PeerId`.
-4. **Post-Extraction Manifest & Symlink Audit (EXP2-SEC-01)**:
- - Add a recursive audit step in `install/transaction.rs` that validates all extracted files in `.local.installing` against manifest BLAKE3 digests and rejects any symbolic links or NTFS junctions.
-
-### Tier 2: Medium-Term Hardening (P1)
-*Target Timeline: Next minor version milestone*
-1. **mDNS Destination Sanitization (NET-02)**: Reject multicast, broadcast, unspecified, and zero-port endpoints in `validated_candidate_endpoint`.
-2. **Asymmetric Request Framing Bounds (NET-03)**: Reduce inbound request `FramedRead` limits to 64 KiB while maintaining 8 MiB for response snapshots.
-3. **Discovery Rate Limiter LRU Eviction (NET-04)**: Transition `RecentCandidates` from hard drop to FIFO/LRU eviction when at capacity.
-4. **Decompression Bomb Protection (EXP2-SEC-02)**: Preflight available disk space before spawning `unrar` and enforce maximum extraction size limits.
-5. **Path Validation Harmonization (EXP2-SEC-03, EXP2-SEC-04)**: Align `path_validation.rs` and `lanspread-proto` with `download/manifest.rs` (checking Windows reserved device names, NFC normalization, and trailing dots/spaces).
-6. **Thumbnail Command Sanitization (SEC-IPC-03)**: Enforce single-component validation in `get_game_thumbnail` and remove debug macros.
-7. **Unrar Subprocess Flags (SEC-IPC-04)**: Pass `-sl-` to `unrar` and verify destination containment.
-
-### Tier 3: Architectural Enhancements (P2)
-*Target Timeline: Long-term architectural refinement*
-1. **Pre-Verification Chunk Memory Buffering (EXP2-SEC-05)**: Buffer chunks in memory and verify BLAKE3 hashes prior to disk persistence.
-2. **UID-Isolated Temp State Directories (EXP2-SEC-06)**: Append process UID and enforce `0o700` permissions for fallback state paths in `/tmp`.
-3. **Capability VFS for Stream Install (EXP2-SEC-07)**: Refactor `stream_install.rs` to use `ConfinedGameRoot` handles with `FollowSymlinks::No`.
-4. **Log Viewer ReDoS Guards (SEC-FE-01)**: Enforce length limits and debouncing on frontend regex filters.
-5. **Defensive SQLite PRAGMAs (SEC-DB-01)**: Set `trusted_schema = OFF` and `cell_size_check = ON` on all SQLite connection pools.
-6. **Webview Capability Minimization (SEC-IPC-05)**: Statically configure log windows and revoke dynamic window creation capabilities.
-
----
-
-## 7. Codebase Health & Verification Results
-
-The workspace build, test suite, and linter were executed to verify codebase integrity. All commands passed cleanly with zero regressions:
-
-### Test Suite Execution
-- **Command**: `just test`
-- **Result**: **PASS** (100% of workspace tests passing)
-- **Summary**:
- - `lanspread-mdns`: 21 tests passed
- - `lanspread-proto`: 25 tests passed (22 unit tests + 3 integration tests)
- - `lanspread-tauri-deno-ts` (Rust backend): 62 tests passed (56 unit tests + 6 catalog gate tests)
- - `lanspread-db`: all database tests passed
- - `lanspread-peer`: all core peer tests passed
-
-### Frontend Unit Test Execution
-- **Command**: `just frontend-test`
-- **Result**: **PASS** (91 frontend reducer and state persistence tests passed in 249ms)
-
-### Clippy Linting & Static Analysis
-- **Command**: `just clippy`
-- **Result**: **PASS** (Zero warnings across all workspace crates with pedantic clippy lints enabled)
-
----
-*Report compiled and certified for the lanspread project security audit.*