mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
fix(vite): avoid serving arbitrary file in vite-node middleware (#20345)
This commit is contained in:
parent
dc20b22a5f
commit
886350a27c
@ -1,10 +1,11 @@
|
|||||||
import { pathToFileURL } from 'node:url'
|
import { pathToFileURL } from 'node:url'
|
||||||
|
import os from 'node:os'
|
||||||
import { createApp, createError, defineEventHandler, defineLazyEventHandler, eventHandler, toNodeListener } from 'h3'
|
import { createApp, createError, defineEventHandler, defineLazyEventHandler, eventHandler, toNodeListener } from 'h3'
|
||||||
import { ViteNodeServer } from 'vite-node/server'
|
import { ViteNodeServer } from 'vite-node/server'
|
||||||
import fse from 'fs-extra'
|
import fse from 'fs-extra'
|
||||||
import { normalize, resolve } from 'pathe'
|
import { isAbsolute, normalize, resolve } from 'pathe'
|
||||||
import { addDevServerHandler } from '@nuxt/kit'
|
import { addDevServerHandler } from '@nuxt/kit'
|
||||||
import type { ModuleNode, Plugin as VitePlugin } from 'vite'
|
import type { ModuleNode, ViteDevServer, Plugin as VitePlugin } from 'vite'
|
||||||
import { normalizeViteManifest } from 'vue-bundle-renderer'
|
import { normalizeViteManifest } from 'vue-bundle-renderer'
|
||||||
import { resolve as resolveModule } from 'mlly'
|
import { resolve as resolveModule } from 'mlly'
|
||||||
import { distDir } from './dirs'
|
import { distDir } from './dirs'
|
||||||
@ -141,6 +142,9 @@ function createViteNodeApp (ctx: ViteBuildContext, invalidates: Set<string> = ne
|
|||||||
if (moduleId === '/') {
|
if (moduleId === '/') {
|
||||||
throw createError({ statusCode: 400 })
|
throw createError({ statusCode: 400 })
|
||||||
}
|
}
|
||||||
|
if (isAbsolute(moduleId) && !isFileServingAllowed(moduleId, viteServer)) {
|
||||||
|
throw createError({ statusCode: 403 /* Restricted */ })
|
||||||
|
}
|
||||||
const module = await node.fetchModule(moduleId).catch((err) => {
|
const module = await node.fetchModule(moduleId).catch((err) => {
|
||||||
const errorData = {
|
const errorData = {
|
||||||
code: 'VITE_ERROR',
|
code: 'VITE_ERROR',
|
||||||
@ -179,3 +183,63 @@ export async function initViteNodeServer (ctx: ViteBuildContext) {
|
|||||||
`export { default } from ${JSON.stringify(pathToFileURL(manifestResolvedPath).href)}`
|
`export { default } from ${JSON.stringify(pathToFileURL(manifestResolvedPath).href)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following code is ported from vite
|
||||||
|
* Awaits https://github.com/vitejs/vite/pull/12894
|
||||||
|
*/
|
||||||
|
const VOLUME_RE = /^[A-Z]:/i
|
||||||
|
const FS_PREFIX = '/@fs/'
|
||||||
|
const isWindows = os.platform() === 'win32'
|
||||||
|
const postfixRE = /[?#].*$/s
|
||||||
|
const windowsSlashRE = /\\/g
|
||||||
|
|
||||||
|
function slash (p: string): string {
|
||||||
|
return p.replace(windowsSlashRE, '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizePath (id: string): string {
|
||||||
|
return normalize(isWindows ? slash(id) : id)
|
||||||
|
}
|
||||||
|
function fsPathFromId (id: string): string {
|
||||||
|
const fsPath = normalizePath(
|
||||||
|
id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id
|
||||||
|
)
|
||||||
|
return fsPath[0] === '/' || fsPath.match(VOLUME_RE) ? fsPath : `/${fsPath}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function fsPathFromUrl (url: string): string {
|
||||||
|
return fsPathFromId(cleanUrl(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanUrl (url: string): string {
|
||||||
|
return url.replace(postfixRE, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFileServingAllowed (
|
||||||
|
url: string,
|
||||||
|
server: ViteDevServer
|
||||||
|
): boolean {
|
||||||
|
if (!server.config.server.fs.strict) { return true }
|
||||||
|
|
||||||
|
const file = fsPathFromUrl(url)
|
||||||
|
|
||||||
|
// @ts-expect-error private API
|
||||||
|
if (server._fsDenyGlob(file)) { return false }
|
||||||
|
|
||||||
|
if (server.moduleGraph.safeModulesPath.has(file)) { return true }
|
||||||
|
|
||||||
|
if (server.config.server.fs.allow.some(dir => isParentDirectory(dir, file))) { return true }
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isParentDirectory (dir: string, file: string): boolean {
|
||||||
|
if (dir[dir.length - 1] !== '/') {
|
||||||
|
dir = `${dir}/`
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
file.startsWith(dir) ||
|
||||||
|
(file.toLowerCase().startsWith(dir.toLowerCase()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user