Skip to content

Vendored gem mode writes the rewired gem line of a CRLF Gemfile with an LF ending, leaving the Gemfile with mixed line endings #1821

Closed

Description

[agent] Found by the scheduled Bundler (RubyGems) bug-hunt routine (ledger #316).

Summary

When vendored mode rewires a gem declaration in a CRLF Gemfile, the new gem "x", "<ver>", path: "…" line is written with a bare \n. Every other line keeps \r\n. So after socket-patch vendor the Gemfile has mixed line endings:

source "https://rubygems.org"\r\n
\r\n
gem "rack", "3.2.7", path: ".socket/vendor/gem/<uuid>/rack-3.2.7"\n     <- was "...\"~> 3.1\"\r\n"

vendor --revert, rollback and remove restore the recorded original line (with its \r), so the round trip is byte-exact. The vendored state in between is the problem. Bundler parses the file fine, so installs and bundle exec aren't affected.

This is separate from #1808, which is about the CRLF Gemfile.lock (the lock surgery). Its fix PR #1811 only touches the lock path and doesn't change the Gemfile line.

Impact

Severity is low: the file still works. It's a correctness and hygiene defect in a user-owned manifest.

Repro

This is a scratch addition to gem_vendor_fresh_checkout_bundle_install_and_revert in crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs, with a real bundle install from rubygems.org and the patch staged offline with stage_patch_with_vuln:

Gemfile (CRLF):  source "https://rubygems.org"\r\n\r\ngem "rack", "~> 3.1"\r\n
bundle config set --local path vendor/bundle && bundle install      # Gemfile.lock stays LF
# stage a lib/rack.rb patch for pkg:gem/rack@3.2.7
socket-patch vendor --json --offline        # exit 0, applied 1
ruby -e 'p File.binread("Gemfile")'
# => "source \"https://rubygems.org\"\r\n\r\ngem \"rack\", \"3.2.7\", path: \".socket/vendor/gem/<uuid>/rack-3.2.7\"\n"
socket-patch vendor --revert --json         # (or rollback / remove <purl>) -> Gemfile byte-exact CRLF again

Expected vs actual

Matrix (Linux, Ruby 3.3.6; the edit is pure text handling, so it doesn't depend on the OS)

Case Bundler 2.6.9 Bundler 4.0.23
vendor on CRLF Gemfile + LF lock: vendored Gemfile has mixed endings fail (×3) fail (×3)
… then vendor --revert / rollback / remove: Gemfile and lock byte-exact pass pass
LF Gemfile (control) pass pass

macOS / Windows probes are unavailable (push-triggered probe runs don't start, see #316). Tested on main ecd4924 (v5.0.1).

Suspect code

  • crates/socket-patch-core/src/vendor/gem.rs:1346-1360 (plan_gemfile_edit): new_line is built from scratch (format!("gem {q}{name}{q}, …")) while original_line is lines[idx] from text.split('\n'), so it still carries the \r. The new line drops it unless a trailing comment happens to carry it. apply_gemfile_plan (gem.rs:1610-1633) then joins with \n.
  • The RewireOurs arm keeps the \r (replacen on the original), and the Append arm (transitive gem, GemfilePlan::Append { block }) appends an LF-only block. I didn't run the Append arm here.
  • A related shape I saw (not filed separately): after a vendored LF pair is re-checked-out as CRLF, restore_gemfile_line (gem.rs:2403) writes back the recorded LF original into the CRLF file. With Fix vendored gems on CRLF Gemfile.lock (#1808) #1811 applied, vendor --revert on such a checkout then leaves the Gemfile mixed as well (…\r\n\r\ngem "rack", "~> 3.1"\n).

Activity

  1. mikolalysenko commented on Oct 29, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p1 (Bundler). Not a duplicate of #1808: that one is the Gemfile.lock surgery (PR #1811), this is the Gemfile line writer. Confirmed on main ecd4924: plan_gemfile_edit (crates/socket-patch-core/src/vendor/gem.rs) builds the Rewrite new_line from scratch while original_line keeps its \r, and the Append managed block is LF-only, so both arms write LF lines into a CRLF Gemfile.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 29, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: vendored Gemfile writer builds new/appended lines with LF regardless of the file's line endings). Branch: agent/fix-vendored-gemfile-crlf-line. Claim-ID: 2026-10-29T09:20:55Z-e4d7ea


    Generated by Claude Code

  3. mikolalysenko commented on Oct 29, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft fix PR: #1822


    Generated by Claude Code

  4. added 3 commits that reference this issue on Oct 29, 2026
    43e13f6
    fc0b23a
    6cb35bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentpm:bundlerBundler (RubyGems)priority:p1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions