Skip to content

Gem::YAMLSerializer may not roundtrip metadata #9560

@kou

Description

@kou

Describe the problem as clearly as you can

We can specify any valid UTF-8 128 bytes key and 1024 bytes value as metadata:

https://guides.rubygems.org/specification-reference/#metadata

For example, all of the following cases are valid:

  • spec.metadata["have space"] = "space value"
  • spec.metadata["have:colon"] = "colon:value"
  • spec.metadata["\"double_quoted\""] = "\"quoted_value\""
  • spec.metadata["'single_quoted'"] = "'quoted_value'"

These quoted patterns can't be roundtrip with The current Gem::YAMLSerializer:

 diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb
index d6fef1d7de..4aa5dbff72 100644
--- a/test/rubygems/test_gem_safe_yaml.rb
+++ b/test/rubygems/test_gem_safe_yaml.rb
@@ -648,6 +648,10 @@ def test_roundtrip_specification_with_metadata
         "source_code_uri" => "https://github.com/example/metadata-test",
         "bug_tracker_uri" => "https://github.com/example/metadata-test/issues",
         "allowed_push_host" => "https://rubygems.org",
+        "\"double_quoted\"" => "\"quoted_value\"",
+        "'single_quoted'" => "'quoted_value'",
+        "have:colon" => "value:colon",
+        "have space" => "value space",
       }
     end
 
@@ -655,12 +659,17 @@ def test_roundtrip_specification_with_metadata
     loaded = Gem::SafeYAML.safe_load(yaml)
 
     assert_kind_of Gem::Specification, loaded
-    assert_kind_of Hash, loaded.metadata
-    assert_equal 4, loaded.metadata.size
-    assert_equal "https://example.com/CHANGELOG.md", loaded.metadata["changelog_uri"]
-    assert_equal "https://github.com/example/metadata-test", loaded.metadata["source_code_uri"]
-    assert_equal "https://github.com/example/metadata-test/issues", loaded.metadata["bug_tracker_uri"]
-    assert_equal "https://rubygems.org", loaded.metadata["allowed_push_host"]
+    expected_metadata = {
+      "changelog_uri" => "https://example.com/CHANGELOG.md",
+      "source_code_uri" => "https://github.com/example/metadata-test",
+      "bug_tracker_uri" => "https://github.com/example/metadata-test/issues",
+      "allowed_push_host" => "https://rubygems.org",
+      "\"double_quoted\"" => "\"quoted_value\"",
+      "'single_quoted'" => "'quoted_value'",
+      "have:colon" => "value:colon",
+      "have space" => "value space",
+    }
+    assert_equal expected_metadata, loaded.metadata
   end
 
   def test_roundtrip_version
Failure: test_roundtrip_specification_with_metadata(TestGemSafeYAML)
test/rubygems/test_gem_safe_yaml.rb:673:in 'TestGemSafeYAML#test_roundtrip_specification_with_metadata'
<{"\"double_quoted\""=>"\"quoted_value\"",
 "'single_quoted'"=>"'quoted_value'",
 "allowed_push_host"=>"https://rubygems.org",
 "bug_tracker_uri"=>"https://github.com/example/metadata-test/issues",
 "changelog_uri"=>"https://example.com/CHANGELOG.md",
 "have space"=>"value space",
 "have:colon"=>"value:colon",
 "source_code_uri"=>"https://github.com/example/metadata-test"}> expected but was
<{"\"double_quoted\""=>"quoted_value",
 "'single_quoted'"=>"quoted_value",
 "allowed_push_host"=>"https://rubygems.org",
 "bug_tracker_uri"=>"https://github.com/example/metadata-test/issues",
 "changelog_uri"=>"https://example.com/CHANGELOG.md",
 "have space"=>"value space",
 "have:colon"=>"value:colon",
 "source_code_uri"=>"https://github.com/example/metadata-test"}>

diff:
? {"\"double_quoted\""=>"\"quoted_value\"",
?  "'single_quoted'"=>"'quoted_value'",
   "allowed_push_host"=>"https://rubygems.org",
   "bug_tracker_uri"=>"https://github.com/example/metadata-test/issues",
   "changelog_uri"=>"https://example.com/CHANGELOG.md",
   "have space"=>"value space",
   "have:colon"=>"value:colon",
   "source_code_uri"=>"https://github.com/example/metadata-test"}

(Quotations (" and ') are missing for quoted_value.)

Did you try upgrading RubyGems?

Yes.

Post steps to reproduce the problem

Use the above diff.

Which command did you run?

None.

What were you expecting to happen?

Quoted values can be roundtrip.

What actually happened?

Quotations in value are missing.

Run gem env and paste the output below

RubyGems Environment:
  - RUBYGEMS VERSION: 4.1.0.dev
  - RUBY VERSION: 4.1.0 (2026-05-02 patchlevel -1) [x86_64-linux]
  - INSTALLATION DIRECTORY: /var/tmp/local/lib/ruby/gems/4.1.0+1
  - USER INSTALLATION DIRECTORY: /home/kou/.gem/ruby/4.1.0+1
  - CREDENTIALS FILE: /home/kou/.gem/credentials
  - RUBYGEMS PREFIX: /home/kou/work/ruby/rubygems
  - RUBY EXECUTABLE: /var/tmp/local/bin/ruby
  - GIT EXECUTABLE: /bin/git
  - EXECUTABLE DIRECTORY: /var/tmp/local/bin
  - SPEC CACHE DIRECTORY: /home/kou/.cache/gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /var/tmp/local/etc
  - RUBYGEMS PLATFORMS:
     - ruby
     - x86_64-linux
  - GEM PATHS:
     - /var/tmp/local/lib/ruby/gems/4.1.0+1
     - /home/kou/.gem/ruby/4.1.0+1
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => true
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /var/tmp/local/bin
     - /bin
     - /usr/local/bin
     - /usr/bin
     - /usr/games

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions