fix(security): address PR #139 review findings#140
Conversation
- Reject chained ModEx normalization beyond 32 layers to prevent O(payload) CPU amplification from nested extension wrappers. - Enforce the existing TCP connect deadline across RTMP handshake and AMF command exchange so a malicious peer cannot stall read_exact or blocking command sends indefinitely. Co-authored-by: Alexander Wagner <info@alexanderwagnerdev.com>
- poll_until_deadline: recompute remaining time on each EINTR retry so a signal near the deadline can't restart a full poll interval and blow past the wall-clock connect/handshake budget. - Transport::connect_tls: accept the caller's remaining connect deadline and use it for the TLS handshake's read/write timeouts instead of a fresh fixed 10s budget, so RTMPS connects stay within the overall connect deadline. - Client: add set_connect_timeout() so embedders can raise the connect budget beyond the default 10s (needed once handshake/AMF connect I/O started sharing that deadline). - normalize_modex_payload: document that exceeding the chain-depth cap intentionally leaves the payload opaque, so downstream codec/multitrack detection can go missing for such frames.
|
Warning Review limit reached
Next review available in: 43 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe client gains an optional wall-clock connection deadline covering TCP/TLS setup, RTMP handshake, and AMF commands. TLS accepts explicit timeouts, ModEx normalization limits chained layers, and one multitrack test assertion is reformatted. ChangesConnection deadline enforcement
ModEx normalization depth guard
Multitrack test formatting
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Transport
participant RTMPHandshake
participant AMFConnection
Client->>Transport: connect TCP/TLS within deadline
Client->>RTMPHandshake: perform C0/C1/C2 handshake
Client->>AMFConnection: send connect and createStream
AMFConnection-->>Client: return responses or timeout
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoFix connect/handshake deadline enforcement and make connect timeout configurable
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
cargo-semver-checks flagged the added timeout parameter on Transport::connect_tls as a breaking change against v0.4.0. Restore the original 4-parameter signature (fixed default timeout) and add a new connect_tls_with_timeout() for the deadline-aware call Client::connect needs.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/client/mod.rs`:
- Around line 237-240: Update the deadline calculation in the connection flow to
use checked addition with the resolved connect timeout, including the default
from TCP_CONNECT_TIMEOUT_SECS. When the addition overflows, return the method’s
existing error type instead of panicking; preserve the normal deadline behavior
for valid durations.
In `@src/transport.rs`:
- Around line 168-192: Update connect_tls to enforce one absolute handshake
deadline rather than per-I/O read/write timeouts: track the caller-provided
deadline, drive Ssl::connect in a nonblocking/retry loop, and return
ErrorCode::Timeout when it expires while preserving other handshake errors. Add
a test covering a stalled or drip-fed TLS handshake that verifies it cannot
exceed the supplied timeout and reports Timeout.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 35ca857b-dd75-4464-b625-fa60272c8adc
📒 Files selected for processing (4)
src/client/mod.rssrc/ertmp/multitrack_media.rssrc/media/modex.rssrc/transport.rs
Code Review by Qodo
Context used✅ Compliance rules (platform):
11 rules✅ Cross-repo context Explored:
repo: OpenRTMP/librtmp2-server (sha: a8bb8752) 1.
|
- Client::connect: guard the deadline computation with checked_add so an oversized caller-supplied connect_timeout can't panic instead of returning an error. - Transport::connect_tls_with_timeout: drive the TLS client handshake non-blocking against one absolute deadline (mirroring the existing server-side accept_nonblocking/PendingTlsAccept pattern) instead of fixed per-syscall socket read/write timeouts, which a drip-fed peer could otherwise use to blow past the overall connect budget. Adds a regression test against a stalled peer. - poll_until_deadline (client) and the new TLS connect poll loop: stop rounding a sub-millisecond remaining budget up to a 1ms poll wait, which could overshoot the absolute deadline; treat it as expired instead. - Note the new single-deadline connect behavior and the ModEx chain cap in CHANGELOG.md under Unreleased.
|
Code review by qodo was updated up to the latest commit 93d5b7d |
Both deadline-poll loops (client's poll_until_deadline and the new TLS connect_tls_with_timeout handshake loop) clamp the remaining wall-clock budget to i32::MAX ms for poll(2), since it only takes a 32-bit signed millisecond timeout. rc == 0 after that clamped wait only means the clamped wait expired, not that the caller's real absolute deadline passed -- treating it as Timeout unconditionally could time out a connect() up to ~24.8 days early for a caller-supplied set_connect_timeout() that large. Recheck against the real deadline and loop instead of returning early.
|
Code review by qodo was updated up to the latest commit 2864f77 |
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Builds on #139 (cap ModEx chain depth + bound client connect I/O) and fixes the review findings raised on it.
Changes
poll_until_deadlinenow recomputes the remaining time on everyEINTRretry instead of reusing the timeout computed once up front, so a signal arriving near the deadline can no longer restart a full poll interval and exceed the intended wall-clock deadline for connect/handshake I/O.Transport::connect_tlsnow takes the caller's remaining connect budget and uses it for the TLS handshake's socket read/write timeouts, instead of a fresh fixed 10s timeout.Client::connectpasses the remaining time on the shared deadline through, so RTMPS connects can no longer run past the overall connect cap.Client::set_connect_timeout(Duration)so embedders (e.g.librtmp2-server's E2E tests) can raise the connect budget for slower/loaded hosts now that handshake + AMF connect I/O share that same deadline. Defaults to the previousTCP_CONNECT_TIMEOUT_SECSwhen unset.normalize_modex_payloadthat exceedingMAX_MODEX_CHAIN_LAYERSintentionally leaves the payload opaque, so downstream codec/multitrack detection (detected_video_codec/detected_audio_codec) can be absent for such frames — this is a deliberate CPU-amplification tradeoff, not a bug.Test plan
cargo build --all-featurescargo build --no-default-featurescargo test --all-features(268 unit tests + integration suites, all passing)cargo test --no-default-featurescargo clippy --all-features --all-targets(clean)cargo fmtGenerated by Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by CodeRabbit
New Features
Bug Fixes