Skip to content

Hosted npm scan appends allow-remote=all to a CRLF .npmrc with no final newline as "\nallow-remote=all\r", leaving an LF line and a bare-CR ending that socket-patch's own .npmrc planner refuses #1196

Closed

Description

[agent] Found by the scheduled npm bug-hunt routine (ledger #302).

Summary

A project .npmrc with CRLF line endings whose last line has no terminator (common for files saved by Windows editors) gets the hosted allow-remote=all line spliced in as …<last line>\nallow-remote=all\r. The old last line now ends in a bare LF, and the file now ends in a bare CR. That's the CR-only shape CLI_CONTRACT says socket-patch never writes to ("one with bare-\r line endings … is left untouched"), and plan_npmrc_allow_remote refuses it on any later run that would need to change it.

Impact

Low. npm splits on /[\r\n]+/, so npm 12.2.0 still reads allow-remote=all and npm ci installs the patched bytes. But the committed file is corrupted: mixed LF/CRLF plus a trailing lone CR. The line survives rollback (npm_allow_remote_left, documented), so the mangled ending stays in the repo. Any later planner pass over this file, for example after the user edits the value, hits the bare-CR Unsupported arm.

Repro (Linux, npm 10.9.4 / 12.2.0, local mock patch API)

echo '{"name":"proj","version":"1.0.0","dependencies":{"ms":"2.1.2"}}' > package.json
npm install
printf 'fund=false\r\naudit=false' > .npmrc        # CRLF, no final newline
socket-patch scan --mode hosted --yes
od -c .npmrc
# f u n d = f a l s e \r \n a u d i t = f a l s e \n a l l o w - r e m o t e = a l l \r

Controls: fund=false\r\naudit=false\r\n (CRLF with a final newline) appends allow-remote=all\r\n correctly; an LF file without a final newline appends \nallow-remote=all, which is consistent. A mixed file with a CRLF majority is fine too.

Expected vs actual

Expected (docs/testing/npm-compatibility.md: the .npmrc append covers "BOM, CRLF"; CLI_CONTRACT: bare-\r files are out of scope because "the line splice does not" handle them): the appended line uses the file's CRLF terminator and the previous line keeps CRLF, giving …audit=false\r\nallow-remote=all (or …\r\n at the end).

Actual: …audit=false\nallow-remote=all\r.

Matrix

OS npm Result
Linux 10.9.4 (×3: main 16106b1 ×2, ef48495) fail
Linux 12.2.0 / Node 24.21 file mangled; npm ci still patched, npm config get allow-remote → all

The code is OS-independent. Not a regression: ef48495 (before #1108) behaves the same.

Suspect code

crates/socket-patch-core/src/patch/redirect/npmrc.rs:612-625: the planner splits on '\n' and inserts "allow-remote=all\r" after the last non-empty line, then joins with "\n". When the last line has no \n it isn't followed by an element, so the inserted line becomes the new tail: the previous line gets the join's bare \n, and the new line keeps a dangling \r with no \n after it.

Activity

  1. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    v5 triage: P2, not a release blocker. Retain the CRLF .npmrc with no final newline normalization at P2; fix the ordinary forward/install blockers first.

    This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.

  2. mikolalysenko commented on Oct 12, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: the .npmrc planner inserts the allow-remote line after an unterminated last line, so the CR lands at end of file). Branch: agent/fix-npmrc-crlf-unterminated-append. Claim-ID: 2026-10-12T04:21:13Z-2dc601


    Generated by Claude Code

  3. added a commit that references this issue on Oct 12, 2026
    b9c4d85
  4. mikolalysenko commented on Oct 12, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR: #1417


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions