Skip to content

Commit

Permalink
share collections in middleware vm context (#31043)
Browse files Browse the repository at this point in the history
When libraries are required outside of the middleware function context and they do checks such as `a instanceof Uint8Array` since the constructors are different between the two contexts they'll always yield false.

This is a problem for libraries validating user input as well as the WebCryptoAPI polyfill used outside of Edge Functions.

- Fixes #30477
- Fixes #30911

This is only a problem for the sandbox runtime, not when ran inside an Edge Function.
  • Loading branch information
panva committed Nov 9, 2021
1 parent 764e29c commit 0985b0b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
24 changes: 24 additions & 0 deletions packages/next/server/web/sandbox/sandbox.ts
Expand Up @@ -87,6 +87,30 @@ export async function run(params: {
TransformStream,
URL,
URLSearchParams,

// Indexed collections
Array,
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
BigInt64Array,
BigUint64Array,

// Keyed collections
Map,
Set,
WeakMap,
WeakSet,

// Structured data
ArrayBuffer,
SharedArrayBuffer,
}

context.self = context
Expand Down
24 changes: 23 additions & 1 deletion test/integration/middleware/core/pages/interface/_middleware.js
Expand Up @@ -2,7 +2,7 @@

import { NextResponse } from 'next/server'

export function middleware(request) {
export async function middleware(request) {
const url = request.nextUrl

if (url.pathname.endsWith('/globalthis')) {
Expand All @@ -13,6 +13,28 @@ export function middleware(request) {
})
}

if (url.pathname.endsWith('/webcrypto')) {
const response = {}
try {
const algorithm = {
name: 'RSA-PSS',
hash: 'SHA-256',
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
modulusLength: 2048,
}
const keyUsages = ['sign', 'verify']
await crypto.subtle.generateKey(algorithm, false, keyUsages)
} catch (err) {
response.error = true
} finally {
return new NextResponse(JSON.stringify(response), {
headers: {
'content-type': 'application/json; charset=utf-8',
},
})
}
}

return new Response(null, {
headers: {
'req-url-basepath': request.nextUrl.basePath,
Expand Down
6 changes: 6 additions & 0 deletions test/integration/middleware/core/test/index.test.js
Expand Up @@ -350,6 +350,12 @@ function interfaceTests(locale = '') {
expect(globals.length > 0).toBe(true)
})

it(`${locale} collection constructors are shared`, async () => {
const res = await fetchViaHTTP(context.appPort, '/interface/webcrypto')
const response = await res.json()
expect('error' in response).toBe(false)
})

it(`${locale} should validate request url parameters from a static route`, async () => {
const res = await fetchViaHTTP(
context.appPort,
Expand Down

0 comments on commit 0985b0b

Please sign in to comment.