fix: Ensure trailing slash is added to source URIs added via gem sources#9055
fix: Ensure trailing slash is added to source URIs added via gem sources#9055hsbt merged 4 commits intoruby:masterfrom
Conversation
a9fbf4c to
7a78385
Compare
7a78385 to
fd55c7e
Compare
|
@kou I fixed some issues of this PR. Could you review this again? |
| end | ||
|
|
||
| @fetcher.data["#{uri}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string | ||
| @fetcher.data["#{uri.chomp("/")}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string |
There was a problem hiding this comment.
Can we revert this change if we always use URI that has a trailing slash for setup_fake_source?
We don't need accept non trailing slash URI in setup_fake_source, right?
There was a problem hiding this comment.
Without chomp, passing "https://example.com/path/" produces "https://example.com/path//specs...".
It's difficult to check for the presence or absence of slashes in every call to the helper, so I think it's reasonable to remove them here.
| ui = Gem::MockGemUi.new "n" | ||
|
|
||
| use_ui ui do | ||
| assert_raise Gem::MockGemUi::TermError do | ||
| @cmd.execute | ||
| end | ||
| use_ui @ui do | ||
| @cmd.execute | ||
| end |
There was a problem hiding this comment.
I'm not sure why the existing passed with Gem::MockGemUi.new "n"...
It seems that https://rubygems.org/ passes both of check_typo_squatting and check_rubygems_https...
61fdc11 to
17124e6
Compare
GitHub's private gem registry expects the first path segment after the host
to represent the namespace, typically the organization or user name. [1]
When adding a source with
```
gem sources --add https://user:password@rubygems.pkg.github.com/my-org
```
without a trailing slash, the last path segment ("my-org") is interpreted as a
file and removed during relative path resolution. This causes the resulting
URI to become
```
https://user:password@rubygems.pkg.github.com/gems/foo.gem
```
instead of the correct
```
https://user:password@rubygems.pkg.github.com/my-org/gems/foo.gem. [2]
```
Example error:
```
gem source -a https://user:password@rubygems.pkg.github.com/my-org
gem install -rf foo.gem
rubygems/remote_fetcher.rb:238:in `fetch_http': bad response Not Found 404 (https://user:REDACTED@rubygems.pkg.github.com/gems/foo-0.7.1.gem) (Gem::RemoteFetcher::FetchError)
```
Although this behavior complies with RFC 2396, it's incompatible with GitHub's
gem registry requirements.
The remote fetcher is just append a relative path without using ./ [3]
To address this, we automatically append a trailing slash when adding new gem
sources.
As illustrated in [4] and [5], given the base URI
```
http://a/b/c/d;p?q
```
and a relative path
```
g/f
```
the resolution process replaces "d;p?q" and yields
```
http://a/b/c/g/f
```
[1] https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-rubygems-registry#authenticating-with-a-personal-access-token
[2] https://github.com/ruby/rubygems/blob/master/lib/rubygems/vendor/uri/lib/uri/generic.rb#L1053
[3] https://github.com/ruby/rubygems/blob/master/lib/rubygems/remote_fetcher.rb#L148
[4] https://www.rfc-editor.org/rfc/rfc2396#section-5.2
[5] https://www.rfc-editor.org/rfc/rfc2396#appendix-C
- Rename add_trailing_slash to normalize_source_uri to better reflect that it also removes duplicated trailing slashes - Extract build_source and build_new_source to eliminate duplicated source creation pattern across add_source, append_source, prepend_source, and remove_source - Apply URI normalization to remove_source as well - Use \z instead of $ in trailing slash regex for correctness Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix setup_fake_source double-slash bug: normalize URI before registering spec data to prevent URL mismatch in load_specs - Fix test_execute_add/append_https_rubygems_org: these tests were incorrectly expecting TermError due to the double-slash bug - Fix test_execute_prepend_without_trailing_slash: correct expected source order (prepend adds to front, not end) - Fix test_execute_remove_redundant_source_trailing_slash: path-less URIs are not modified by normalize_source_uri - Use assert_equal for Gem.sources to improve failure diagnostics Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
17124e6 to
da8d622
Compare
GitHub's private gem registry expects the first path segment after the host
to represent the namespace, typically the organization or user name. [1]
When adding a source with
without a trailing slash, the last path segment ("my-org") is interpreted as a
file and removed during relative path resolution. This causes the resulting
URI to become
instead of the correct
Example error:
Although this behavior complies with RFC 2396, it's incompatible with GitHub's
gem registry requirements.
The remote fetcher is just append a relative path without using ./ [3]
To address this, we automatically append a trailing slash when adding new gem
sources.
As illustrated in [4] and [5], given the base URI
and a relative path
the resolution process replaces "d;p?q" and yields
[1] https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-rubygems-registry#authenticating-with-a-personal-access-token
[2] https://github.com/ruby/rubygems/blob/master/lib/rubygems/vendor/uri/lib/uri/generic.rb#L1053
[3] https://github.com/ruby/rubygems/blob/master/lib/rubygems/remote_fetcher.rb#L148
[4] https://www.rfc-editor.org/rfc/rfc2396#section-5.2
[5] https://www.rfc-editor.org/rfc/rfc2396#appendix-C