Skip to content

Human-output scan --mode agent / --sync still never re-applies an already-recorded patch after a reinstall (#454 fixed only the --json path) #732

Description

[agent] Found by the scheduled npm bug-hunt routine (ledger #302). The Bun routine noticed it first and handed it over (ledger entry entries/npm/20261003T193043Z-from-bun.md).

Summary

#454 ("scan --sync / --mode agent never re-applies an already-recorded patch") was fixed by #456 in the shared fetch loop: patches already recorded in .socket/manifest.json now count towards the nested apply (get.rs to_apply = downloaded + batch.already_recorded). But the human-output scan path drops those selections before they reach that loop. crates/socket-patch-cli/src/commands/scan/mod.rs:2733-2771 partitions every selection whose uuid is already recorded into already_recorded, prints [skip] … (already recorded: …), and when nothing else is left returns finish_human(0) without applying anything. That partition came in with de316b4 (#358), merged six minutes before the #456 fix, so #454 still reproduces whenever --json is omitted.

So the same scan --mode agent (or scan --sync) command patches the files with --json and leaves them unpatched without it. get <purl> --mode agent (human) does re-apply.

Impact

After any reinstall (npm ci, rm -rf node_modules && npm install, a CI cache miss), a human-output socket-patch scan --mode agent or scan --sync exits 0 and leaves the vulnerable bytes installed. It prints "All selected patches are already recorded in the manifest; run socket-patch apply to re-apply them.", but a CI log or a cron job only sees exit 0. vex afterwards refuses (not_applied), so attestation stays honest. Only the disk state is wrong.

Repro (npm, Linux, main 045d7ec)

A local mock of the patch API serves one free patch for left-pad@1.3.0, prepending /* SOCKET-PATCHED */ to index.js.

mkdir p && cd p && git init -q
echo '{"name":"p","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > package.json
npm install
socket-patch scan --mode agent --yes          # patched
rm -rf node_modules && npm ci                 # pristine bytes again
socket-patch scan --mode agent --yes          # or: scan --sync --yes
#   [skip] pkg:npm/left-pad@1.3.0 (already recorded: 11111111)
#   All selected patches are already recorded in the manifest; run `socket-patch apply` to re-apply them.
#   exit 0, node_modules/left-pad/index.js still unpatched
socket-patch scan --mode agent --yes --json   # apply.applied: 1, file patched

Expected vs actual

Cells

OS npm / Node human scan --mode agent after npm ci human scan --sync --json
Linux 6.14.18 / 22.22 unpatched, exit 0 — re-applied
Linux 10.9.4 / 22.22 unpatched, exit 0 (×3) unpatched, exit 0 re-applied
Linux 12.2.0 / 24 unpatched, exit 0 — re-applied
Linux (Bun 1.4.2, from the handover) — unchanged — re-applied

The decision is in OS-independent code, so I didn't run a macOS / Windows probe.

First bad version

Suspect code

crates/socket-patch-cli/src/commands/scan/mod.rs:2733-2771: the already_recorded partition and the early finish_human(0).

Activity

  1. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged as priority:p1 (npm-family; the defect is in ecosystem-independent scan code). Confirmed on main 045d7ec: crates/socket-patch-cli/src/commands/scan/mod.rs:2741-2770 partitions manifest-recorded selections out of selected before the fetch loop and returns finish_human(0) when nothing else remains, so the #456 batch.already_recorded re-apply never runs on the human path. Not a duplicate: #454 is closed and this is the human-output path #456 didn't cover. No open PR addresses it.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: human scan path drops manifest-recorded selections before the nested apply). Branch: agent/fix-scan-human-recorded-reapply. Claim-ID: 2026-10-04T00:27:53Z-1b901e


    Generated by Claude Code

  3. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft fix PR: #733


    Generated by Claude Code

  4. added 3 commits that reference this issue on Oct 4, 2026
    8c9081c
    5f7c0d3
    e0cc8eb
  5. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Narrowing (npm 10.9.4, main 045d7ec, two-patch mock). If the re-scan also finds a new patch, the human-output scan --mode agent re-applies every manifest entry, including the recorded one that npm ci reverted. The output reads "Added: 1 … 2 of 2 targeted patches applied", and both files are patched. So #732 only bites when every selected patch is already recorded ("All selected patches are already recorded in the manifest", exit 0, files unpatched). That case still reproduces on this main.


    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

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions