fix(core): restrict web viewport URLs to public http/https#64
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR adds URL validation to the web viewport renderer to restrict loading to absolute HTTP/HTTPS URLs with valid, non-private hosts. A new ChangesWeb Viewport URL Validation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@crates/hypercolor-core/src/effect/builtin/web_viewport.rs`:
- Around line 401-406: The is_private_or_loopback_ip function fails to detect
IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1) so those addresses bypass the
IPv4 private/loopback checks; update is_private_or_loopback_ip to recognize
IPv4-mapped IPv6 (in the IpAddr::V6 arm) by extracting the embedded IPv4 address
and applying the same checks used for IpAddr::V4
(is_private/is_loopback/is_link_local), and add the proposed tests asserting
that "::ffff:127.0.0.1" and "::ffff:192.168.1.1" return true while
"::ffff:8.8.8.8" returns false to cover this case.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: ae3f949c-f07e-4d4c-a3f5-cb3266426926
📒 Files selected for processing (1)
crates/hypercolor-core/src/effect/builtin/web_viewport.rs
is_private_or_loopback_ip classified ::ffff:127.0.0.1 and other IPv4-mapped IPv6 literals only against the V6 predicates, which never match a mapped loopback or private address. A web viewport URL using that form would connect to the embedded IPv4 target and slip past the SSRF policy. Mapped addresses are now unwrapped and checked as IPv4.
d7ca558 to
685893a
Compare
The web viewport SSRF guard from #64 classified hosts through `Url::host_str()`, which renders IPv6 literals in bracketed form (`[::1]`). `host.parse::<IpAddr>()` then fails on that bracket text, so `is_private_or_loopback_ip` was never reached: loopback, IPv4-mapped loopback, and unique-local IPv6 destinations all slipped the filter and were fetched freely. Two narrower gaps rode along. The unspecified addresses `0.0.0.0` and `[::]` connect to the local host yet matched no private or loopback predicate. And a trailing dot (`localhost.`) sidestepped the literal `localhost` comparison while resolving identically. Match on the parsed `Url::host()` enum so IPv6 literals arrive as `Host::Ipv6` and reach the classifier, reject unspecified addresses explicitly, and strip a trailing dot before the local-hostname check. New tests drive `validate_web_url` with concrete attack URLs instead of only exercising the IP predicate in isolation. Co-authored-by: Nova (Claude Opus 4.7) <noreply@anthropic.com>
Motivation
file://and private/localhost IPs) and published full rendered frames to a preview channel, enabling a local-file/SSRF exfiltration chain on default unauthenticated loopback installs.Description
validate_web_url()to enforce onlyhttp/httpsschemes and rejectlocalhost/.localhostnames and loopback/private/link-local IP literals before passing a URL to Servo.is_private_or_loopback_ip()helper used by the policy, update theurlcontrol help text to removefile://guidance, and adjust URL-normalization-related unit tests.Testing
cargo test -p hypercolor-core web_viewport(compilation progressed in this environment but the full test run did not complete during the session). (partial)cargo fmt --check -p hypercolor-corewhich reported formatting diffs (failed due to crate-wide formatting differences). (failed)rustfmton the modified file to fix formatting (succeeded). (succeeded)Codex Task
Summary by CodeRabbit
Release Notes