Summary
On Windows desktop builds, the Tauri IPC command open_url routes an attacker-influenceable URL through cmd.exe (cmd /c start "" <url>) without neutralizing shell metacharacters. Rust's std only quotes an argument that contains whitespace/quotes; a URL has none, so it is emitted unquoted and cmd.exe treats & as a command separator. A malicious link rendered in a trusted app window becomes arbitrary command execution in the victim's user context after a single click (CWE-78, OS Command Injection). macOS and Linux are unaffected.
Details
Sink. open_in_shell (src-tauri/src/main.rs:522-527, Windows branch) runs:
Command::new("cmd").args(["/c", "start", "", arg])
Rust's std command builder wraps an argument in quotes only when it contains a space, tab, or quote. A URL such as https://example.com/?x=1&calc contains none (spaces would be %20), so it lands on the command line unquoted. cmd.exe then parses the unquoted & as a statement separator and executes the trailing token(s) as separate commands — e.g. &calc&whoami.
Taint path (attacker → RCE):
- An attacker-controlled
<link> in any aggregated RSS/news feed is rendered as an anchor inside a trusted app window.
- The capture-phase click handler (
src/app/event-handlers.ts:690-704) reads anchor.href, runs new URL() (scheme/origin checks only — no metacharacter stripping), and calls invokeTauri('open_url', { url }) (:704).
open_url (src-tauri/src/main.rs:548-561) runs require_trusted_window (validates the window, not the URL) and Url::parse (validates only the scheme), then calls open_in_shell(parsed.as_str()).
Why the guards fail. require_trusted_window checks the origin window, which is legitimately the trusted main window carrying tainted feed content. Url::parse enforces https/http-localhost but does not remove & | < > ^ ( ) — all legal in a URL query/fragment. macOS (open) and Linux (xdg-open) exec a single argv with no shell, so only Windows is affected.
PoC
On a Windows build, in the main window devtools console:
window.__TAURI_INTERNALS__.invoke('open_url', { url: 'https://example.com/?x=1&calc' })
// -> calc.exe launches
Full chain: point the app at a feed whose item link is that URL, then click the headline.
Modeled command-line parse (faithful model of the documented Windows cmd.exe behavior; included as poc-F2-tauri-cmd-injection.mjs):
built command line: cmd /c start "" https://example.com/?a=1&calc&whoami
cmd.exe runs 3 command(s): ["cmd /c start \"\" https://example.com/?a=1", "calc", "whoami"]
>>> INJECTED: ["calc", "whoami"]
Impact
Arbitrary command execution in the victim's user context on Windows desktop builds, triggered by clicking a malicious headline/link that the app renders from aggregated feed content. Full confidentiality/integrity/availability impact within that user account (file theft, persistence, further payload download). Requires user interaction (a click) and is Windows-only, hence High rather than Critical.
Remediation
Never route URLs through cmd.exe. Open links via ShellExecuteW, the open/opener crate, or tauri-plugin-opener, or spawn the browser binary directly with an argv vector (no shell interpretation). A tested unified-diff patch (F2-tauri-cmd-injection.patch) is available in the coordinated-disclosure package.
Maintainer validation (2026-07-04): Valid historically, but no longer live on current origin/main. Tauri open_url no longer shells through cmd.exe on Windows; it uses opener/ShellExecuteW-style handling, and src-tauri/open-url-safety.test.mjs asserts cmd.exe is not spawned. Published advisories cannot be closed through the GitHub API, so this is marked in-description as fixed/no longer active.
Summary
On Windows desktop builds, the Tauri IPC command
open_urlroutes an attacker-influenceable URL throughcmd.exe(cmd /c start "" <url>) without neutralizing shell metacharacters. Rust's std only quotes an argument that contains whitespace/quotes; a URL has none, so it is emitted unquoted andcmd.exetreats&as a command separator. A malicious link rendered in a trusted app window becomes arbitrary command execution in the victim's user context after a single click (CWE-78, OS Command Injection). macOS and Linux are unaffected.Details
Sink.
open_in_shell(src-tauri/src/main.rs:522-527, Windows branch) runs:Rust's
stdcommand builder wraps an argument in quotes only when it contains a space, tab, or quote. A URL such ashttps://example.com/?x=1&calccontains none (spaces would be%20), so it lands on the command line unquoted.cmd.exethen parses the unquoted&as a statement separator and executes the trailing token(s) as separate commands — e.g.&calc&whoami.Taint path (attacker → RCE):
<link>in any aggregated RSS/news feed is rendered as an anchor inside a trusted app window.src/app/event-handlers.ts:690-704) readsanchor.href, runsnew URL()(scheme/origin checks only — no metacharacter stripping), and callsinvokeTauri('open_url', { url })(:704).open_url(src-tauri/src/main.rs:548-561) runsrequire_trusted_window(validates the window, not the URL) andUrl::parse(validates only the scheme), then callsopen_in_shell(parsed.as_str()).Why the guards fail.
require_trusted_windowchecks the origin window, which is legitimately the trusted main window carrying tainted feed content.Url::parseenforceshttps/http-localhostbut does not remove& | < > ^ ( )— all legal in a URL query/fragment. macOS (open) and Linux (xdg-open) exec a single argv with no shell, so only Windows is affected.PoC
On a Windows build, in the main window devtools console:
Full chain: point the app at a feed whose item link is that URL, then click the headline.
Modeled command-line parse (faithful model of the documented Windows
cmd.exebehavior; included aspoc-F2-tauri-cmd-injection.mjs):Impact
Arbitrary command execution in the victim's user context on Windows desktop builds, triggered by clicking a malicious headline/link that the app renders from aggregated feed content. Full confidentiality/integrity/availability impact within that user account (file theft, persistence, further payload download). Requires user interaction (a click) and is Windows-only, hence High rather than Critical.
Remediation
Never route URLs through
cmd.exe. Open links viaShellExecuteW, theopen/openercrate, ortauri-plugin-opener, or spawn the browser binary directly with an argv vector (no shell interpretation). A tested unified-diff patch (F2-tauri-cmd-injection.patch) is available in the coordinated-disclosure package.Maintainer validation (2026-07-04): Valid historically, but no longer live on current origin/main. Tauri open_url no longer shells through cmd.exe on Windows; it uses opener/ShellExecuteW-style handling, and src-tauri/open-url-safety.test.mjs asserts cmd.exe is not spawned. Published advisories cannot be closed through the GitHub API, so this is marked in-description as fixed/no longer active.