Skip to content

fix(security): migrate remaining shell-string callsites to argv arrays #1889

@jyaunches

Description

@jyaunches

Rationale

PR #1886 introduced runArgv() / runArgvCapture() to eliminate shell injection in nim.ts, local-inference.ts, and policies.ts. However, three files still use run()/runCapture() with shell strings:

  • src/lib/onboard.ts — 18 run() + 10 runCapture() shell-string calls (~5,400 lines)
  • src/lib/agent-onboard.ts — 3 run() shell-string calls
  • src/lib/preflight.ts — 14 runCapture() shell-string calls

These callsites use shellQuote() for defense, so they are not directly vulnerable — but they remain in the weaker security posture (quoting-dependent rather than structurally safe).

Scope

Convert each shell-string call to pass an argv array to the now-polymorphic run()/runCapture() (see #1886 for the polymorphic refactor). Each conversion is mechanical:

// Before
run(`docker rm -f ${shellQuote(name)} 2>/dev/null || true`, { ignoreError: true });

// After
run(["docker", "rm", "-f", name], { ignoreError: true });

File-by-file breakdown

File run() calls runCapture() calls Notes
src/lib/onboard.ts 18 10 Largest file; migrate incrementally
src/lib/preflight.ts 0 14 Includes lsof, sysctl, df, sudo calls
src/lib/agent-onboard.ts 3 0 docker image inspect, docker build

Additional cleanup

  • Add an ESLint no-restricted-syntax rule to flag shell: true in child_process calls, preventing future reintroduction of the vulnerability class
  • Remove shellQuote imports from files once all their callsites are converted

Acceptance criteria

  • All run()/runCapture() calls in the three files pass argv arrays instead of shell strings
  • shellQuote is no longer imported in any of the three files
  • No new bash -c patterns introduced (except documented exceptions like backgrounding)
  • Existing tests pass; new injection regression tests added where user input flows into commands
  • ESLint rule added to flag shell: true in child_process options

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    securityPotential vulnerability, unsafe behavior, or access risk

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions