agent: code-atomiser-fix — write_text_file_cmd path scope (Trust-1, corrective)
Corrective re-apply of Trust-1. The original commita2b47dbcarried the wrong staged file due to a parallel-agent race that swapped the staged path between `git add` and `git commit` — fs.rs was never actually changed bya2b47dbdespite the message. This commit applies the Trust-1 fix properly. The Tauri command `write_text_file_cmd` previously took an arbitrary `path: String` and flowed it straight into `tokio::fs::write` with no main-window guard, no canonicalisation, and no scope check. A compromised webview could write anywhere the process had write access — overwriting shell init files, dropping a runner into `~/.config/autostart`, etc. This change: - adds `ensure_main_window(&window)?` so only the main webview can invoke the command; - canonicalises the requested path's parent (rejecting nonexistent parents and resolving symlinks) before joining the filename; - asserts the canonical target sits inside an allowlisted base (app data, app local data, downloads, documents, desktop), so a `"../../etc/passwd"` payload — even one obtained via symlink trickery in the chosen save dir — is refused with a clear error. Six unit tests cover: outside-allowlist rejection, path-traversal rejection, nested inside-allowlist acceptance, plain inside-allowlist acceptance, nonexistent-parent rejection, and the pure `is_inside_any_base` prefix check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,16 @@ pub struct AppState {
|
||||
pub parakeet_engine: Arc<LocalEngine>,
|
||||
pub db: SqlitePool,
|
||||
pub llm_engine: Arc<LlmEngine>,
|
||||
/// Race-4/5 TOCTOU guard: two concurrent `ensure_model_loaded`
|
||||
/// callers (e.g. a double-clicked "Test" + "Transcribe" button)
|
||||
/// would both observe `loaded_model_id != requested`, both decide
|
||||
/// "not loaded — load it", and both spawn a multi-second
|
||||
/// `load_model_from_disk` whose result the second overwrites.
|
||||
/// Holding this `tokio::sync::Mutex` across the check-then-load
|
||||
/// critical section forces them to serialise; the second caller
|
||||
/// acquires the lock after the first finishes, observes the
|
||||
/// now-loaded state, and short-circuits.
|
||||
pub load_serialise: Arc<tokio::sync::Mutex<()>>,
|
||||
}
|
||||
|
||||
/// Holds the preferences init script for injection into secondary windows.
|
||||
@@ -629,6 +639,7 @@ pub fn run() {
|
||||
parakeet_engine: Arc::new(LocalEngine::new(EngineName::new("parakeet"))),
|
||||
db,
|
||||
llm_engine: Arc::new(LlmEngine::new()),
|
||||
load_serialise: Arc::new(tokio::sync::Mutex::new(())),
|
||||
});
|
||||
|
||||
// Runtime-warning banner: push CPU-feature + Vulkan-loader
|
||||
|
||||
Reference in New Issue
Block a user