allow file names with .. in it

Massimo Melina committed Feb 7, 2022 at 18:32 UTC 6fdd8e92dab967cf097ba1864481cdcf3514d8c4
4 files changed +12 -7
src/api.file_list.ts
+3 -3
@@ -2,7 +2,7 @@ import { getNodeName, vfs, VfsNode, walkNode } from './vfs'
2 import { ApiError, ApiHandler } from './apis'
3 import { stat } from 'fs/promises'
4 import { mapPlugins } from './plugins'
5 -import { pattern2filter } from './misc'
5 +import { dirTraversal, pattern2filter } from './misc'
6 import { FORBIDDEN } from './const'
7 import EventEmitter from 'events'
8
@@ -12,8 +12,8 @@ export const file_list:ApiHandler = async ({ path, offset, limit, search, omit,
12 return
13 if (node.forbid)
14 return new ApiError(FORBIDDEN)
15 - if (search?.includes('..'))
16 - return new ApiError(400)
15 + if (dirTraversal(search))
16 + return new ApiError(418)
17 if (node.default)
18 return { redirect: path }
19 offset = Number(offset)
src/middlewares.ts
+3 -2
@@ -5,7 +5,7 @@ import { BUILD_TIMESTAMP, SESSION_DURATION } from './index'
5 import Application from 'koa'
6 import { FORBIDDEN, FRONTEND_URI } from './const'
7 import { vfs } from './vfs'
8 -import { isDirectory } from './misc'
8 +import { dirTraversal, isDirectory } from './misc'
9 import { zipStreamFromFolder } from './zip'
10 import { serveFileNode } from './serveFile'
11 import { serveFrontend } from './serveFrontend'
@@ -79,7 +79,7 @@ export const frontendAndSharedFiles: Koa.Middleware = async (ctx, next) => {
79
80 export const someSecurity: Koa.Middleware = async (ctx, next) => {
81 try {
82 - if (decodeURI(ctx.path).includes('..'))
82 + if (dirTraversal(decodeURI(ctx.path)))
83 return ctx.status = 418
84 }
85 catch {
@@ -87,3 +87,4 @@ export const someSecurity: Koa.Middleware = async (ctx, next) => {
87 }
88 return next()
89 }
90 +
src/misc.ts
+4
@@ -148,3 +148,7 @@ export function debounceAsync(cb: any, ms: number=100, ...args:any[]) {
148 finally { busy = false }
149 }
150 }
151 +
152 +export function dirTraversal(s?: string) {
153 + return s && /(^|[/\\])\.\.($|[/\\])/.test(s)
154 +}
src/vfs.ts
+2 -2
@@ -1,7 +1,7 @@
1 import fs from 'fs/promises'
2 import { basename } from 'path'
3 import { isMatch } from 'micromatch'
4 -import { enforceFinal, isDirectory, isWindows, onlyTruthy } from './misc'
4 +import { dirTraversal, enforceFinal, isDirectory, isWindows, onlyTruthy } from './misc'
5 import Koa from 'koa'
6 import glob from 'fast-glob'
7 import _ from 'lodash'
@@ -43,7 +43,7 @@ export class Vfs {
43 async urlToNode(url: string, ctx?: Koa.Context, root?: VfsNode) : Promise<VfsNode | undefined> {
44 let run = root || this.root
45 const decoded = decodeURI(url)
46 - if (decoded.includes('..')) {
46 + if (dirTraversal(decoded)) {
47 if (ctx)
48 ctx.status = 418
49 return