Commit c7517ab
Reject protocol-relative inputs in base_uri / persistent resolution
When HTTP::Client is configured with `base_uri:` or
`HTTP.persistent("...")`, the builder previously passed user-supplied
path strings straight into `URI#join` (via `String(base.join(uri))`)
or naive concatenation (`"#{persistent}#{uri}"`).
Per RFC 3986 §5.2, an input starting with `//` is a network-path
reference and replaces the authority of the base. The existing
`HTTP_OR_HTTPS_RE` guard only rejected `http://` and `https://`
prefixes, so a bare `//evil.example/x` slipped through and turned
a base_uri-scoped request into one to an attacker-chosen host.
The same call also keeps any connection-scoped headers (`HTTP.auth(...)`
bearer, custom `X-API-Key`, etc.), so the primitive is a one-shot
SSRF plus credential leak — no follow-redirect chain is involved,
so the usual strip-on-redirect defences never run.
Fix: when the resolver sees a `//`-prefixed input on the base_uri or
persistent branch, prepend `./` before delegating so the input
resolves as an ordinary relative path under the configured base.
Regression coverage in test/http/request/builder_test.rb covers
`//evil.com/x`, `//evil.com:port/x`, `//user:pass@evil.com/x`,
`///evil.com`, plus persistent + benign-absolute + benign-relative
shapes, mirroring the test cases used for the equivalent fix in
sibling Ruby HTTP-client gems.
Reported privately as GHSA-r98x-p6m8-xcrv.1 parent 0d2303d commit c7517ab
3 files changed
Lines changed: 80 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
8 | 19 | | |
9 | 20 | | |
10 | 21 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
87 | 93 | | |
88 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
89 | 99 | | |
90 | 100 | | |
91 | 101 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
620 | 620 | | |
621 | 621 | | |
622 | 622 | | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
623 | 682 | | |
0 commit comments