Skip to content

fix(optimize): preserve inherited NODE_OPTIONS in agent installer#1435

Open
John-David Dalton (jdalton) wants to merge 1 commit into
mainfrom
jdalton/fix-optimize-node-options-clobber
Open

fix(optimize): preserve inherited NODE_OPTIONS in agent installer#1435
John-David Dalton (jdalton) wants to merge 1 commit into
mainfrom
jdalton/fix-optimize-node-options-clobber

Conversation

@jdalton

@jdalton John-David Dalton (jdalton) commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What

socket optimize runs the package-manager install via runAgentInstall, which set the child's NODE_OPTIONS to only Socket's own Node flags:

NODE_OPTIONS: cmdFlagsToString([
  ...(skipNodeHardenFlags ? [] : getNodeHardenFlags()),
  ...getNodeNoWarningsFlags(),
  ...getNodeDisableSigusr1Flags(),
]),

A child process' NODE_OPTIONS replaces the parent's rather than extending it, so any NODE_OPTIONS the user configured globally (e.g. --max-old-space-size=4096) was silently dropped for the install.

How

Merge the inherited process.env.NODE_OPTIONS ahead of our added flags, via a new pure mergeNodeOptions() helper in util/process/cmd.mts:

NODE_OPTIONS: mergeNodeOptions(process.env['NODE_OPTIONS'], [
  ...(skipNodeHardenFlags ? [] : getNodeHardenFlags()),
  ...getNodeNoWarningsFlags(),
  ...getNodeDisableSigusr1Flags(),
]),

The value is left unquoted — it's assigned directly to an env var (no shell), and quotes would break consumers that re-tokenize NODE_OPTIONS on whitespace.

Relationship to the v1.x #1160/#1036 fix

Same class of NODE_OPTIONS-clobber bug, different code path — do not conflate:

On main, socket npm hands off to Socket Firewall and no longer builds Node flags itself, so the agent installer is the remaining place on main that needed the merge. (It's also the path an earlier fork PR, kimjune01/socket-cli#1, aimed at.)

Tests

  • test/unit/util/process/cmd.test.mts — 6 new cases for mergeNodeOptions (prepend order, undefined/empty NODE_OPTIONS, no added flags, never quoted, all-empty).
  • test/unit/commands/optimize/agent-installer.test.mts — new case asserting an inherited NODE_OPTIONS reaches the spawn env instead of being clobbered.
Verification
  • vitest run on both files — 41/41 pass.
  • oxfmt -c .config/fleet/oxfmtrc.json --list-different on changed files — clean.
  • oxlint on changed files — 0 errors.
  • Pre-existing packages/cli typecheck errors (unrelated files: output-scan-view.mts, glob.mts, parse.mts) are gated on main and not touched here.

Note

Low Risk
Small, localized CLI spawn-env change with dedicated unit tests; no auth, data, or security surface.

Overview
socket optimize package-manager installs no longer wipe the user’s global NODE_OPTIONS when spawning npm/pnpm/yarn.

runAgentInstall used to set the child’s NODE_OPTIONS to only Socket’s hardening/warning flags. Because a child env replaces the parent’s value, settings like --max-old-space-size=4096 were dropped for the install. The installer now builds NODE_OPTIONS with a new mergeNodeOptions() helper that keeps existing process.env.NODE_OPTIONS first and appends Socket’s flags (unquoted, for direct env assignment).

Unit coverage was added for mergeNodeOptions and for asserting inherited NODE_OPTIONS reaches the spawn env in the agent installer tests.

Reviewed by Cursor Bugbot for commit ed6e872. Configure here.

runAgentInstall set the child's NODE_OPTIONS to only our own Node flags
(harden / no-warnings / disable-sigusr1). A child process' NODE_OPTIONS
REPLACES the parent's rather than extending it, so any NODE_OPTIONS the
user configured globally was silently dropped when `socket optimize` ran
the package-manager install.

Merge the inherited process.env.NODE_OPTIONS ahead of our added flags via
a new pure `mergeNodeOptions` helper in util/process/cmd.mts, unit-tested
in isolation. The value is left unquoted (it is assigned to an env var,
not passed through a shell).

Same class of NODE_OPTIONS-clobber bug as the v1.x shadow-npm fix for
#1160/#1036, but a different code path: this is the `socket optimize`
agent installer on main, not the `socket npm` shadow wrapper. On main
`socket npm` hands off to Socket Firewall and no longer builds Node
flags itself, so this is the remaining place on main that needed it.
@jdalton
John-David Dalton (jdalton) force-pushed the jdalton/fix-optimize-node-options-clobber branch from ed6e872 to e471aca Compare July 24, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant