Add validation to server methods (#49104)
This PR adds a `key` param to the IPC server to validate if a request is from a child process or not.
This commit is contained in:
parent
692d28b193
commit
f3068a5bbb
3 changed files with 21 additions and 2 deletions
|
@ -1271,9 +1271,10 @@ export default class DevServer extends Server {
|
|||
|
||||
private async invokeIpcMethod(method: string, args: any[]): Promise<any> {
|
||||
const ipcPort = process.env.__NEXT_PRIVATE_ROUTER_IPC_PORT
|
||||
const ipcKey = process.env.__NEXT_PRIVATE_ROUTER_IPC_KEY
|
||||
if (ipcPort) {
|
||||
const res = await invokeRequest(
|
||||
`http://${this.hostname}:${ipcPort}?method=${
|
||||
`http://${this.hostname}:${ipcPort}?key=${ipcKey}&method=${
|
||||
method as string
|
||||
}&args=${encodeURIComponent(JSON.stringify(args))}`,
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@ import type NextServer from '../next-server'
|
|||
import { genExecArgv, getNodeOptionsWithoutInspect } from './utils'
|
||||
import { deserializeErr, errorToJSON } from '../render'
|
||||
import { IncomingMessage } from 'http'
|
||||
import crypto from 'crypto'
|
||||
import isError from '../../lib/is-error'
|
||||
|
||||
// we can't use process.send as jest-worker relies on
|
||||
|
@ -12,11 +13,23 @@ export async function createIpcServer(
|
|||
): Promise<{
|
||||
ipcPort: number
|
||||
ipcServer: import('http').Server
|
||||
ipcValidationKey: string
|
||||
}> {
|
||||
// Generate a random key in memory to validate messages from other processes.
|
||||
// This is just a simple guard against other processes attempting to send
|
||||
// traffic to the IPC server.
|
||||
const ipcValidationKey = crypto.randomBytes(32).toString('hex')
|
||||
|
||||
const ipcServer = (require('http') as typeof import('http')).createServer(
|
||||
async (req, res) => {
|
||||
try {
|
||||
const url = new URL(req.url || '/', 'http://n')
|
||||
const key = url.searchParams.get('key')
|
||||
|
||||
if (key !== ipcValidationKey) {
|
||||
return res.end()
|
||||
}
|
||||
|
||||
const method = url.searchParams.get('method')
|
||||
const args: any[] = JSON.parse(url.searchParams.get('args') || '[]')
|
||||
|
||||
|
@ -61,12 +74,14 @@ export async function createIpcServer(
|
|||
return {
|
||||
ipcPort,
|
||||
ipcServer,
|
||||
ipcValidationKey,
|
||||
}
|
||||
}
|
||||
|
||||
export const createWorker = (
|
||||
serverPort: number,
|
||||
ipcPort: number,
|
||||
ipcValidationKey: string,
|
||||
isNodeDebugging: boolean | 'brk' | undefined,
|
||||
type: 'pages' | 'app',
|
||||
useServerActions?: boolean
|
||||
|
@ -88,6 +103,7 @@ export const createWorker = (
|
|||
.trim(),
|
||||
__NEXT_PRIVATE_RENDER_WORKER: type,
|
||||
__NEXT_PRIVATE_ROUTER_IPC_PORT: ipcPort + '',
|
||||
__NEXT_PRIVATE_ROUTER_IPC_KEY: ipcValidationKey,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
...(type === 'app'
|
||||
? {
|
||||
|
|
|
@ -268,11 +268,12 @@ export default class NextNodeServer extends BaseServer {
|
|||
this.renderWorkersPromises = new Promise<void>(async (resolveWorkers) => {
|
||||
try {
|
||||
this.renderWorkers = {}
|
||||
const { ipcPort } = await createIpcServer(this)
|
||||
const { ipcPort, ipcValidationKey } = await createIpcServer(this)
|
||||
if (this.hasAppDir) {
|
||||
this.renderWorkers.app = createWorker(
|
||||
this.port || 0,
|
||||
ipcPort,
|
||||
ipcValidationKey,
|
||||
options.isNodeDebugging,
|
||||
'app',
|
||||
this.nextConfig.experimental.serverActions
|
||||
|
@ -281,6 +282,7 @@ export default class NextNodeServer extends BaseServer {
|
|||
this.renderWorkers.pages = createWorker(
|
||||
this.port || 0,
|
||||
ipcPort,
|
||||
ipcValidationKey,
|
||||
options.isNodeDebugging,
|
||||
'pages'
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue