Skip to content

fix(include): require opt-in for remote includes - #262

Merged
LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/remote-include-optin
Sep 22, 2026
Merged

LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/remote-include-optin

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Low, category security. Location: crates/rustmotion/src/include.rs:220

Impact

Any scenario handed to rustmotion render/validate can make the user's machine issue GETs to hosts of the author's choosing, with no host/scheme allowlist, no redirect policy, no timeout set on the call, and no --offline switch to refuse. On a developer laptop or a CI runner this reaches loopback services, RFC1918 addresses and cloud link-local metadata (169.254.169.254), and it doubles as a silent beacon that fires merely from validating a file (validation::load goes through the same resolve_includes). Fetching remote includes is clearly deliberate design, so the finding is the absence of any control around it, not the feature.

Fix

Gate remote includes behind an explicit opt-in flag (default deny), and when enabled reject non-public destinations after DNS resolution (loopback, link-local, RFC1918/ULA), set an explicit timeout, and cap the response size. Report the URLs a scenario wants to fetch before fetching them.

Evidence the audit read

fn fetch_remote(url: &str) -> Result<String> {
    let response = ureq::get(url)
        .call()
        .map_err(|e| RustmotionError::IncludeRemoteFetch {
            url: url.to_string(),
            reason: e.to_string(),
        })?;
---
    let is_remote =
        directive.include.starts_with("http://") || directive.include.starts_with("https://");

Stacked on fix/expand-node-budget, 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-46).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/expand-node-budget branch from 62393d5 to 4dc047f Compare September 22, 2026 06:11
@LeadcodeDev
LeadcodeDev force-pushed the fix/remote-include-optin branch from 1a96e5a to b24e80d Compare September 22, 2026 06:11
@LeadcodeDev
LeadcodeDev force-pushed the fix/expand-node-budget branch from 4dc047f to 9daff5f Compare September 22, 2026 08:36
@LeadcodeDev
LeadcodeDev force-pushed the fix/remote-include-optin branch from b24e80d to 4149673 Compare September 22, 2026 08:36
@LeadcodeDev
LeadcodeDev force-pushed the fix/expand-node-budget branch from 9daff5f to 226b364 Compare September 22, 2026 08:46
@LeadcodeDev
LeadcodeDev force-pushed the fix/remote-include-optin branch from 4149673 to 7151be0 Compare September 22, 2026 08:46
@LeadcodeDev
LeadcodeDev changed the base branch from fix/expand-node-budget to chantier/audit-2026-09 September 22, 2026 08:54
@LeadcodeDev
LeadcodeDev force-pushed the fix/remote-include-optin branch from 7151be0 to da2106a Compare September 22, 2026 09:02
Any scenario handed to `rustmotion render`/`validate` can make the user's machine issue GETs to hosts of the author's choosing, with no host/scheme allowlist, no redirect policy, no timeout set on the call, and no `--offline` switch to refuse. On a developer laptop or a CI runner this reaches loopback services, RFC1918 addresses and cloud link-local metadata (169.254.169.254), and it doubles as a silent beacon that fires merely from *validating* a file (validation::load goes through the same `resolve_includes`). Fetching remote includes is clearly deliberate design, so the finding is the absence of any control around it, not the feature.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/remote-include-optin branch from da2106a to 915a105 Compare September 22, 2026 09:06
@LeadcodeDev
LeadcodeDev merged commit a37916f into chantier/audit-2026-09 Sep 22, 2026
LeadcodeDev added a commit that referenced this pull request Sep 22, 2026
Any scenario handed to `rustmotion render`/`validate` can make the user's machine issue GETs to hosts of the author's choosing, with no host/scheme allowlist, no redirect policy, no timeout set on the call, and no `--offline` switch to refuse. On a developer laptop or a CI runner this reaches loopback services, RFC1918 addresses and cloud link-local metadata (169.254.169.254), and it doubles as a silent beacon that fires merely from *validating* a file (validation::load goes through the same `resolve_includes`). Fetching remote includes is clearly deliberate design, so the finding is the absence of any control around it, not the feature.

Refs #220
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