[BUG] [DEP0190] Startup hook with complex shell command triggers Node.js deprecation warning on every SessionStart

Resolved 💬 3 comments Opened May 16, 2026 by wzp0514 Closed Jun 14, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

On Windows with Node.js v24.15.0, Claude Code outputs a DEP0190
deprecation warning every time a hook with type: "command" is executed.

The warning reads:
[DEP0190] DeprecationWarning: Passing args to a child process with a
shell option can lead to security vulnerabilities. Pass the shell
command as a string instead.

This happens during SessionStart hooks, but likely affects all hook
types (PostToolUse, Stop, etc.) that run shell commands.

ROOT CAUSE ANALYSIS:
The Claude Code hooks engine internally calls Node.js
child_process.spawn() with BOTH an args array AND {shell: true}
option simultaneously. Node.js v22+ deprecates this pattern because
when args are passed as an array with shell:true, the array elements
are concatenated into a single string without proper shell escaping,
which can lead to command injection vulnerabilities.

The offending call pattern is likely something like:
spawn(shellPath, ['-c', commandString], {shell: true})
or:
spawn(command, args, {shell: true})

Per Node.js docs, the correct pattern when using shell:true is to
pass the entire command as a single string (not an array):
spawn(commandString, {shell: true})

TROUBLESHOOTING DONE:

  1. Initially suspected the user's hook command complexity (nested

$() and escaped quotes) was the trigger — simplified to pure echo
commands, but the warning persisted intermittently.

  1. Verified it's NOT a user settings.json issue — the warning

originates from within Claude Code's internal hook execution
engine, not from user-provided shell or command configurations.

  1. Confirmed PowerShell 5.1 → 7+ upgrade would NOT fix it, as the

root cause is at the Node.js child_process API call layer, not
the external shell.

  1. Also reproduced in the claude-mem community plugin's

bun-runner.js, which had the same spawn(args, {shell:true})
anti-pattern. Fixed there by platform-detecting: on Windows, pass
command as string; on Unix, use array without shell:true.

WORKAROUNDS FOUND:

  • Removing any explicit "shell" field from hook configurations in

settings.json reduces the frequency but does not eliminate the
warning entirely (Claude Code's internal shell invocation still
triggers it).

  • The only complete user-side workaround is to avoid type: "command"

hooks entirely, which is not practical.

What Should Happen?

Claude Code should execute hook commands without triggering Node.js
deprecation warnings.

When a hook with type: "command" is configured, Claude Code's
internal hook runner should:

Option A (Recommended):
Detect whether shell:true is needed and use the correct spawn
signature:

  • With shell:true → spawn(fullCommandString, {shell: true})
  • Without shell → spawn(command, args)

Option B:
On Windows, when the target is already a shell (cmd.exe /
bash.exe), invoke it directly without the shell:true flag:
spawn('C:\\Windows\\System32\\cmd.exe', ['/c', command])
instead of:
spawn('C:\\Windows\\System32\\cmd.exe', ['/c', command],
{shell: true})

Either approach would eliminate the DEP0190 warning and align with
Node.js best practices for child process security.

Error Messages/Logs

Steps to Reproduce

  1. On Windows 11 with Node.js v24.15.0, install Claude Code 2.1.139
  1. Configure a SessionStart hook in ~/.claude/settings.json:

{
"hooks": {
"SessionStart": [{
"matcher": "startup",
"hooks": [{
"type": "command",
"command": "echo 'test hook running'"
}]
}]
}
}

  1. Restart Claude Code (close and reopen the terminal, or run

claude in a new window)

  1. Observe the terminal output — the DEP0190 deprecation warning

appears during the SessionStart hook execution

  1. Also reproducible with any hook type that executes shell

commands (PostToolUse, Stop, etc.)

EXPECTED: Clean startup, no deprecation warnings
ACTUAL: [DEP0190] DeprecationWarning line appears in output

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.139

Claude Code Version

2.1.139

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

  • This is a regression/issue exposed by Node.js v24's stricter

deprecation handling. Users on Node.js v20 or earlier may not
see this warning, but the underlying security concern exists in
all versions.

  • The same anti-pattern was found and fixed in the claude-mem

community plugin's bun-runner.js and worker-service.cjs files,
serving as a reference for the required change pattern:

  • Before: spawnSync('bun', ['run', script], {shell: true})
  • After (Windows): spawnSync('bun run script', {shell: true})
  • After (Unix): spawnSync('bun', ['run', script])
  • This is particularly noticeable on Windows because the spawn

chain is longer: Claude Code → bash.exe → cmd.exe → target
command, and each layer can trigger individual warnings.

  • Related Node.js docs:

https://nodejs.org/api/child_process.html#child_processspawncommand-args-options

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗