fix(assets): set a timeout on every outbound request - #259
Merged
Merged
Conversation
53 tasks
LeadcodeDev
force-pushed
the
fix/http-timeout
branch
2 times, most recently
from
September 22, 2026 08:36
268592c to
fa7b242
Compare
I read ureq 3.2.0's impl Default for Timeouts (config.rs:898-911): global, per_call, resolve, connect, send_request, send_body, recv_response and recv_body are all None; only await_100 is set (1 s). None of the four call sites configures one — assets.rs:141 (Iconify), google_fonts.rs:189 and google_fonts.rs:217 (Google Fonts CSS + TTF), rustmotion/src/include.rs:221 (arbitrary remote include). A host that accepts the TCP connection and then stalls, or trickles one byte per minute, blocks indefinitely; ureq's 10 MB body cap bounds bytes, not time. The icon path is the worst case: icon.rs:55 can reach fetch_icon_svg from inside paint_content, i.e. on a render worker thread, so one stalled connection wedges a render that has no user at the keyboard (CI, --frames a-b distributed segments). Combined with the remote- include finding, a scenario chooses the host that stalls. Fix: Build one shared ureq::Agent with Config::builder().timeout_global(Some (Duration::from_secs(20))).timeout_connect(Some(Duration::from_secs(5))) (plus https_only(true)) and route all four call sites through it, instead of the bare ureq::get(...) free function which always uses the default (untimed) agent. Refs #220
LeadcodeDev
force-pushed
the
fix/http-timeout
branch
from
September 22, 2026 08:45
fa7b242 to
1878d51
Compare
LeadcodeDev
added a commit
that referenced
this pull request
Sep 22, 2026
I read ureq 3.2.0's impl Default for Timeouts (config.rs:898-911): global, per_call, resolve, connect, send_request, send_body, recv_response and recv_body are all None; only await_100 is set (1 s). None of the four call sites configures one — assets.rs:141 (Iconify), google_fonts.rs:189 and google_fonts.rs:217 (Google Fonts CSS + TTF), rustmotion/src/include.rs:221 (arbitrary remote include). A host that accepts the TCP connection and then stalls, or trickles one byte per minute, blocks indefinitely; ureq's 10 MB body cap bounds bytes, not time. The icon path is the worst case: icon.rs:55 can reach fetch_icon_svg from inside paint_content, i.e. on a render worker thread, so one stalled connection wedges a render that has no user at the keyboard (CI, --frames a-b distributed segments). Combined with the remote- include finding, a scenario chooses the host that stalls. Fix: Build one shared ureq::Agent with Config::builder().timeout_global(Some (Duration::from_secs(20))).timeout_connect(Some(Duration::from_secs(5))) (plus https_only(true)) and route all four call sites through it, instead of the bare ureq::get(...) free function which always uses the default (untimed) agent. Refs #220
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Severity Low, category security. Location:
crates/rustmotion-core/src/engine/renderer/assets.rs:141Impact
I read ureq 3.2.0's
impl Default for Timeouts(config.rs:898-911):global,per_call,resolve,connect,send_request,send_body,recv_responseandrecv_bodyare allNone; onlyawait_100is set (1 s). None of the four call sites configures one —assets.rs:141(Iconify),google_fonts.rs:189andgoogle_fonts.rs:217(Google Fonts CSS + TTF),rustmotion/src/include.rs:221(arbitrary remote include). A host that accepts the TCP connection and then stalls, or trickles one byte per minute, blocks indefinitely; ureq's 10 MB body cap bounds bytes, not time. The icon path is the worst case:icon.rs:55can reachfetch_icon_svgfrom insidepaint_content, i.e. on a render worker thread, so one stalled connection wedges a render that has no user at the keyboard (CI,--frames a-bdistributed segments). Combined with the remote-includefinding, a scenario chooses the host that stalls.Fix
Build one shared
ureq::AgentwithConfig::builder().timeout_global(Some(Duration::from_secs(20))).timeout_connect(Some(Duration::from_secs(5)))(plushttps_only(true)) and route all four call sites through it, instead of the bareureq::get(...)free function which always uses the default (untimed) agent.Evidence the audit read
Part of the September 2026 audit remediation chantier. Refs #220 (RM-41).