Skip to content

fix(assets): restrict the protocols a scenario src may use - #260

Closed
LeadcodeDev wants to merge 1 commit into
fix/http-timeoutfrom
fix/media-protocol-allowlist
Closed

LeadcodeDev wants to merge 1 commit into
fix/http-timeoutfrom
fix/media-protocol-allowlist

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Low, category security. Location: crates/rustmotion-core/src/engine/renderer/assets.rs:222

Impact

src is the video component's scenario field, unfiltered. info.rs:385-391 documents this explicitly ("video's ffmpeg-backed path only reaches one incidentally by handing the string straight to ffmpeg's own demuxer") — so the network reach is acknowledged as accidental, not designed. ffmpeg is invoked without -protocol_whitelist, which means the scenario selects from ffmpeg's entire built-in protocol set: src: "http://169.254.169.254/latest/meta-data/" or http://127.0.0.1:8500/... makes the renderer issue that request (SSRF from an LLM-authored scenario, and a reliable internal port-scan oracle via the exit status printed at preload.rs:252-258). The same unfiltered string reaches preload.rs:221-222 and encode/video_audio.rs:326-327. Secondary risk: playlist/subtitle demuxers that dereference nested file: URLs would render local file content into the output video. There is no timeout on the subprocess either, so a slow remote URL stalls the render.

Fix

Add -protocol_whitelist file (plus ,http,https,tcp,tls only if remote video is a supported feature) to all three ffmpeg argument lists, and validate src against the same scheme check rustmotion/src/assets.rs:26 already uses before the string ever reaches Command. Reject anything that is neither a plain local path nor an explicitly allowed scheme.

Evidence the audit read

pub fn extract_video_frame(src: &str, time: f64, width: u32, height: u32) -> Result<Vec<u8>> {
    let output = std::process::Command::new("ffmpeg")
        .args([
            "-ss",
            &format!("{:.3}", time),
            "-i",
            src,

Stacked on fix/http-timeout, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-42).

src is the video component's scenario field, unfiltered. info.rs:385-391
documents this explicitly ("video's ffmpeg-backed path only reaches one
incidentally by handing the string straight to ffmpeg's own demuxer") — so
the network reach is acknowledged as accidental, not designed. ffmpeg is
invoked without -protocol_whitelist, which means the scenario selects from
ffmpeg's entire built-in protocol set: src:
"http://169.254.169.254/latest/meta-data/" or http://127.0.0.1:8500/...
makes the renderer issue that request (SSRF from an LLM-authored scenario,
and a reliable internal port-scan oracle via the exit status printed at
preload.rs:252-258). The same unfiltered string reaches preload.rs:221-222
and encode/video_audio.rs:326-327. Secondary risk: playlist/subtitle
demuxers that dereference nested file: URLs would render local file content
into the output video. There is no timeout on the subprocess either, so a
slow remote URL stalls the render.

Fix: Add -protocol_whitelist file (plus ,http,https,tcp,tls only if remote
video is a supported feature) to all three ffmpeg argument lists, and
validate src against the same scheme check rustmotion/src/assets.rs:26
already uses before the string ever reaches Command. Reject anything that is
neither a plain local path nor an explicitly allowed scheme.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/media-protocol-allowlist branch from edd1852 to 50f6268 Compare September 22, 2026 08:45
@LeadcodeDev
LeadcodeDev deleted the branch fix/http-timeout September 22, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant