Skip to content

Commit

Permalink
Validate the router state header on the server (#46925)
Browse files Browse the repository at this point in the history
Ensure that the router tree state header is one single, valid value.

Fixes NEXT-136.
  • Loading branch information
shuding authored Mar 8, 2023
1 parent b3220fe commit bae5d6f
Showing 1 changed file with 21 additions and 9 deletions.
30 changes: 21 additions & 9 deletions packages/next/src/server/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,22 @@ async function renderToString(element: React.ReactElement) {
})
}

function parseFlightRouterState(stateHeader: string | string[] | undefined) {
if (typeof stateHeader === 'undefined') {
return undefined
}
if (Array.isArray(stateHeader)) {
throw new Error(
'Multiple router state headers were sent. This is not allowed.'
)
}
try {
return JSON.parse(stateHeader)
} catch (err) {
throw new Error('The router state header was sent but could not be parsed.')
}
}

function validateURL(url: string | undefined): string {
if (!url) {
throw new Error('Invalid request URL')
Expand Down Expand Up @@ -835,23 +851,21 @@ export async function renderToHTMLOrFlight(
}

// don't modify original query object
query = Object.assign({}, query)
query = { ...query }
stripInternalQueries(query)

const isPrefetch =
req.headers[NEXT_ROUTER_PREFETCH.toLowerCase()] !== undefined

// TODO-APP: verify the tree is valid
// TODO-APP: verify query param is single value (not an array)
// TODO-APP: verify tree can't grow out of control
/**
* Router state provided from the client-side router. Used to handle rendering from the common layout down.
*/
let providedFlightRouterState: FlightRouterState = isFlight
? req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
? JSON.parse(
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()] as string
)
: undefined
? parseFlightRouterState(
req.headers[NEXT_ROUTER_STATE_TREE.toLowerCase()]
)
: undefined

/**
Expand All @@ -871,8 +885,6 @@ export async function renderToHTMLOrFlight(

const searchParamsProps = { searchParams: query }

stripInternalQueries(query)

const LayoutRouter =
ComponentMod.LayoutRouter as typeof import('../client/components/layout-router').default
const RenderFromTemplateContext =
Expand Down

0 comments on commit bae5d6f

Please sign in to comment.