Skip to content

fix(js): op_fetch_url buffers unbounded response body → OOM DoS #581

Description

@mnaza

Summary

op_fetch_url (backing JS fetch()/XHR for absolute URLs) reads the entire response body into memory with response.bytes().await and no size cap. A malicious or misbehaving server returning a multi-GB body OOMs the process.

Location

crates/obscura-js/src/ops.rs, op_fetch_url:

let resp_bytes = response
    .bytes()
    .await   // <-- buffers the whole body, unbounded
    .map_err(...)?;

The existing response_body_byte_limit() (default 2 MiB) only gates whether the body is cached for Network.getResponseBody; it does not bound the initial allocation, the String::from_utf8_lossy copy, or the base64 encode that follow.

Exploit

Page JS does fetch('https://attacker.example/huge'); the server streams several GB (optionally without Content-Length, or with a lying one). The whole body is buffered — plus a UTF-8 copy and a base64 copy (~1.33x) — and the process OOMs.

Fix direction

Read the body via streaming (response.chunk()), rejecting with an error both when the advertised Content-Length exceeds a cap and when the streamed bytes exceed it. Make the cap configurable (env) with a generous default well above any realistic page fetch.

Severity

MEDIUM — page-JS/server-reachable memory-exhaustion DoS; not memory-unsafe.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions