
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
process-proxy
Advanced tools
Control a native executable proxy from Node, reading its stdin, writing to its stdout, and stderr streams
A modern npm package (requiring Node 22+) written in TypeScript that enables developers to interact with a native executable, reading its stdin, writing to its stdout, and stderr streams, reading its exit code, arguments, current directory, and environment variables.
This project is in early development and relies heavily on automated code generation using GitHub Copilot CLI. While the implementation follows a clear design specification, it has not been extensively tested in production environments. Users should expect:
Use at your own risk. Contributions, bug reports, and testing on different platforms are highly encouraged.
npm install process-proxy
This package includes a native executable that must be built before use:
npm run build
This will compile both the TypeScript library and the native C executable.
import { createProxyProcessServer, getProxyCommandPath } from 'process-proxy'
import { spawn } from 'child_process'
import { AddressInfo } from 'net'
// Create server with connection callback (idiomatic Node.js style)
const server = createProxyProcessServer((connection) => {
console.log('Native process connected!')
// Get process information
connection.getArgs().then((args) => console.log('Arguments:', args))
connection.getEnv().then((env) => console.log('Environment:', env))
connection.getCwd().then((cwd) => console.log('Working Directory:', cwd))
// Write to the process stdout
connection.stdout.write('Hello from ProcessProxy!\n')
// Read from the process stdin
connection.stdin.on('data', (data) => {
console.log('Received from stdin:', data.toString())
})
// Handle connection close
connection.on('close', () => {
console.log('Process disconnected')
})
})
// Start listening on a random port
const port = await new Promise<number>((resolve) => {
server.listen(0, '127.0.0.1', () => {
resolve((server.address() as AddressInfo).port)
})
})
// Launch the native executable with the port in environment
const nativeExe = getProxyCommandPath()
const child = spawn(nativeExe, ['arg1', 'arg2'], {
env: {
...process.env,
PROCESS_PROXY_PORT: port.toString(),
},
})
// Later, close the server
// server.close();
server.on('connection', (connection) => {
// Pipe process stdin to our stdin
process.stdin.pipe(connection.stdout)
// Pipe process stdout to our stdout
connection.stdin.pipe(process.stdout)
// Pipe process stderr to our stderr
// (Note: stderr is a writable stream on the connection)
connection.stderr.on('data', (data) => {
process.stderr.write(data)
})
})
server.on('connection', async (connection) => {
// Exit the process with a specific code
await connection.exit(0)
})
server.on('connection', async (connection) => {
connection.stdin.end()
})
Creates a TCP server that listens for incoming connections from native processes. Returns a standard Node.js net.Server instance.
import { createProxyProcessServer } from 'process-proxy'
import { AddressInfo } from 'net'
// Create server with connection callback
const server = createProxyProcessServer((connection) => {
console.log('New connection!')
connection.getArgs().then(console.log)
})
// Start listening
const port = await new Promise<number>((resolve) => {
server.listen(0, '127.0.0.1', () => {
resolve((server.address() as AddressInfo).port)
})
})
// Use standard server methods
server.on('listening', () => console.log('Server started'))
server.on('error', (err) => console.error('Server error:', err))
server.close(() => console.log('Server closed'))
Parameters:
listener: (connection: ProcessProxyConnection) => void - Callback invoked for each incoming connectionoptions?: ProxyProcessServerOptions - Optional configuration object:
validateConnection?: (token: string) => Promise<boolean> - Optional callback to validate the connection token during handshake. Receives the token from the handshake and should return a Promise resolving to true to accept the connection or false to reject it.net.ServerOpts options are also supportedReturns: Server - A standard Node.js net.Server instance
Returns the absolute path to the native proxy executable.
import { getProxyCommandPath } from 'process-proxy'
const executablePath = getProxyCommandPath()
// Returns: '/path/to/build/Release/process-proxy' (or .exe on Windows)
This utility function automatically:
.exe suffix on WindowsRepresents a connection to a single instance of the native executable.
stdin: Readable - Readable stream for the executable's stdinstdout: Writable - Writable stream for the executable's stdoutstderr: Writable - Writable stream for the executable's stderrsendCommand(command: number, payload?: Buffer): Promise<Buffer> - Sends a raw command to the executable and returns the responsegetArgs(): Promise<string[]> - Retrieves the command line arguments of the executablegetEnv(): Promise<{ [key: string]: string }> - Retrieves the environment variables of the executablegetCwd(): Promise<string> - Retrieves the current working directory of the executableexit(code: number): Promise<void> - Exits the executable with the specified exit codeclose - Emitted when the connection is closederror - Emitted when an error occurs. Listener signature: (error: Error) => voidThe native executable is written in C and compiled using node-gyp. It connects to the TCP server specified by the PROCESS_PROXY_PORT environment variable.
The native executable is built automatically when running npm run build or npm run build:native.
The native executable must be launched with the PROCESS_PROXY_PORT environment variable set:
PROCESS_PROXY_PORT=12345 ./build/Release/process-proxy [args...]
⚠️ IMPORTANT SECURITY NOTE ⚠️
The TCP server only listens on localhost (127.0.0.1), but this does not provide complete security. Other processes and users with access to the network stack on the host machine can potentially connect to the TCP server.
ProcessProxy includes a built-in authentication mechanism to validate connections during the handshake phase:
When the native executable connects, it sends a 146-byte handshake containing:
PROCESS_PROXY_TOKEN environment variableThe server validates this handshake and can optionally verify the token using a validateConnection callback
If authentication fails, the connection is immediately closed before any commands are processed
Using Token Authentication:
import crypto from 'crypto'
import { createProxyProcessServer, getProxyCommandPath } from 'process-proxy'
import { spawn } from 'child_process'
import { AddressInfo } from 'net'
// Generate a random token for this session
const expectedToken = crypto.randomBytes(32).toString('hex')
// Create server with token validation
const server = createProxyProcessServer(
(connection) => {
// Connection is already authenticated at this point
console.log('Authenticated connection established')
},
{
// Validate the token during handshake
validateConnection: async (token) => {
return token === expectedToken
},
},
)
// Start listening
const port = await new Promise<number>((resolve) => {
server.listen(0, '127.0.0.1', () => {
resolve((server.address() as AddressInfo).port)
})
})
// Launch native executable with the token
const child = spawn(getProxyCommandPath(), ['arg1', 'arg2'], {
env: {
...process.env,
PROCESS_PROXY_PORT: port.toString(),
PROCESS_PROXY_TOKEN: expectedToken, // Token passed to native process
},
})
How it works:
PROCESS_PROXY_TOKEN from its environment and includes it in the handshakevalidateConnection callback with the received tokenfalse or rejects, the connection is immediately closedAdditional Security Recommendations:
validateConnection in production environmentsThis project is licensed under the MIT License - see the LICENSE file for details.
FAQs
Control a native executable proxy from Node, reading its stdin, writing to its stdout, and stderr streams
The npm package process-proxy receives a total of 373 weekly downloads. As such, process-proxy popularity was classified as not popular.
We found that process-proxy demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.