RubyGems 2.7.6 tightens the interpretation of package input
RubyGems 2.7.6 fixes path traversal, unsafe owner-data deserialization and package-validation problems. The changes show how installation safety depends on filesystem resolution and unambiguous metadata.
A package manager interprets more than dependency names and versions. It turns archive paths into filesystem writes, parses numeric fields and displays metadata in other formats. RubyGems 2.7.6 repairs several places where those interpretations could give package-controlled input more authority than intended.
Ruby's February 17 advisory points users to the security release. Samuel Giddins's February 15 RubyGems announcement lists path traversal corrections, unsafe deserialization in the owner command, stricter tar parsing and homepage validation. The fixes address separate mechanisms, so treating the update as one generic installation bug would conceal useful detail.
I find Ruby's readable object model appealing, but that convenience does not determine how externally supplied data should be interpreted. A string can describe a path, a URL or serialized data, with different rules in each case. The package manager needs to enforce those rules at the operation that gives the string its meaning.
A path prefix needs a directory boundary
The 2.7.6 package implementation checks installation destinations before writing package files. It rejects absolute archive filenames, resolves the destination directory and expands the joined path. It then requires the result to begin with the destination directory followed by a slash.
That final separator is significant. A string beginning with the characters of a directory name need not be inside that directory. A sibling named with the same initial characters can satisfy a naive prefix comparison. Including the directory separator tests a path-component boundary.
For a conceptual destination named /srv/gems/example, a path under /srv/gems/example-other shares the initial text without being a child. This is an illustration of the comparison rule, not a claim about a particular victim installation. The corrected check expresses the containment relationship more precisely than a bare string prefix.
Expanding the path also matters because a joined filename can contain components that change its normalized destination. A security decision needs to examine the resulting path, not merely the spelling of the archive entry. The implementation combines normalization with the directory-boundary comparison.
This check protects one interpretation of the filename. It does not by itself account for every filesystem object encountered while creating intermediate directories. That is why the release also includes a distinct correction for symlinked base directories.
Filesystem resolution can change the destination
A symbolic link can make a path's textual location differ from its resolved location. The security announcement separately names traversal when writing through a symlinked base directory outside the root. The package implementation adds directory-creation logic that accounts for resolved paths as it walks the components.
Its helper resolves the destination, splits the directory path into parts and examines the path incrementally. For a component requiring creation, it checks the path against the destination and attempts creation under that condition. It raises a package path error when the operation cannot satisfy the expected conditions.
The useful lesson from this code is specific to filesystem semantics. Checking the final joined string does not establish where all intermediate components lead. A package writer must consider both normalized path spelling and the objects the operating system resolves during the write.
These are distinct checks because they answer different questions. The slash-boundary comparison addresses whether a normalized destination names a child path. Resolving intermediate filesystem paths addresses whether existing links alter where creation occurs. Both belong to interpreting an archive filename as a permitted write.
The release notes credit nmalkin and David Fifield for the path traversal findings. Their inclusion alongside the implementation changes identifies these as security corrections, rather than ordinary improvements to error messages. The public announcement does not establish that every listed issue belongs to one combined attack.
Archive fields need one valid interpretation
The tagged tar-header parser applies a strict octal conversion to numeric fields. The helper accepts a string only when it matches octal digits throughout, then converts it. An invalid field raises an argument error.
The parser applies that helper to fields including mode, size and checksum. Those values influence how an archive is read and how extracted entries are handled. Permitting an ambiguous or partially interpreted numeric spelling is inappropriate when later processing relies on the resulting number.
This change makes malformed input fail at parsing. It avoids treating an invalid field as though it were an acceptable numeric value. A package manager's archive interpretation should be explicit enough that validation and extraction do not depend on permissive conversion behavior.
Duplicate file entries receive another check in the package verifier. After verifying entries and checking for required metadata and content, the implementation groups the observed names and detects duplicates. A duplicate causes a security exception identifying the repeated names.
Repeated archive names are problematic because one logical name can then refer to more than one entry. Rejecting the package removes that ambiguity before a consumer has to decide which occurrence is authoritative. This is a validation policy distinct from whether any one path stays inside the destination directory.
The combination is useful because path containment alone does not make an archive unambiguous. A valid directory-relative path can still appear repeatedly. Likewise, unique paths do not establish that numeric headers are valid. Each check addresses a separate property needed for a package the installer can interpret consistently.
Owner lookup should deserialize data safely
The unsafe-deserialization correction appears in a command that can look informational. The owner command in 2.7.6 requests owner information from the configured gem host and parses the YAML response. It uses Gem::SafeYAML.load for that response.
This operation is separate from extracting files from a gem. It handles network response data used to display owners. The security announcement calls out the possible unsafe object deserialization vulnerability in gem owner, so a user should not assume the update matters only when installing an archive.
The intended output is a collection of owner records whose email, handle or identifier can be displayed. The command needs data from the response, not unrestricted interpretation of arbitrary serialized objects. A safer loader narrows the operation to the representation appropriate for that purpose.
My preference is for a command's implementation to match the limited authority implied by its job. Displaying ownership information should not require a broader object-construction mechanism than the data demands. The change makes that distinction at the point where the response enters the program.
Homepage metadata reaches an HTML context
The announcement also includes URL validation for a gem specification's homepage and an XSS mitigation when that homepage appears through gem server. These are related to metadata display, with different consequences from filesystem traversal.
A homepage attribute is intended to identify a web location. A value acceptable as arbitrary text is not automatically appropriate as a browser link. Validating the attribute and handling its display therefore concern the operation that consumes it, not merely whether the gem's metadata can be parsed.
The release lists these corrections independently from unsafe YAML loading. One concerns how response data becomes Ruby values. Another concerns how metadata reaches a browser. Keeping the mechanisms separate helps determine which workflows use the affected functionality.
Updating the tool is part of remediation
The published update command is the RubyGems system update operation.
gem update --system
As of this advisory, RubyGems 2.7.6 includes the listed fixes. The Ruby advisory also supplies patches for bundled copies when updating RubyGems is not possible. The release announcement publishes SHA256 checksums for its tar, zip and update-gem artifacts. Those values identify the distributed release files, complementing the instructions for obtaining the updated tool. Those paths address the package-manager implementation that performs parsing, extraction and display.
Updating an application's ordinary dependency declarations does not itself establish that this implementation has changed. The vulnerable behavior belongs to the tool operating on packages and metadata. Build environments that install gems and systems using owner lookup or the gem server have relevant workflows even before application code begins to run.
The release makes those workflows stricter in concrete ways. Installation paths receive containment checks that account for directory boundaries and filesystem resolution. Archive parsing rejects malformed numeric fields and duplicate entries. Owner responses use a safer YAML loader, while homepage metadata receives validation for its web use.