fix: API rename allowed moving a file in an existing subfolder on Windows
Massimo Melina committed
Jan 17, 2026 at 10:27 UTC
1de04730773f3abd26885377c348d7e018ba7452
2 files changed
+7
-2
src/frontEndApis.ts
+1
-1
@@ -86,7 +86,7 @@ export const frontEndApis: ApiHandlers = {
86
const node = await urlToNode(uri, ctx)
87
if (!node)
88
throw new ApiError(HTTP_NOT_FOUND)
89
- if (isRoot(node) || dest.includes('/') || hasDirTraversal(dest))
89
+ if (isRoot(node) || !isValidFileName(dest))
90
throw new ApiError(HTTP_FORBIDDEN)
91
if (statusCodeForMissingPerm(node, 'can_delete', ctx))
92
throw new ApiError(ctx.status)
tests/test.ts
+6
-1
@@ -8,7 +8,7 @@ import _ from 'lodash'
8
import { findDefined, randomId, try_, tryJson, UPLOAD_TEMP_HASH, wait } from '../src/cross'
9
import { httpStream, stream2string, XRequestOptions } from '../src/util-http'
10
import { ThrottledStream, ThrottleGroup } from '../src/ThrottledStream'
11
-import { mkdir, rm, writeFile } from 'fs/promises'
11
+import { mkdir, rm, rename, writeFile } from 'fs/promises'
12
import { Readable } from 'stream'
13
/*
14
import { PORT, srv } from '../src'
@@ -332,6 +332,11 @@ describe('after-login', () => {
332
throw "partial file missing"
333
await reqUpload(UPLOAD_DEST, 200, Readable.from(BIG_CONTENT.slice(partial)), BIG_CONTENT.length, partial)()
334
})
335
+ test('rename.backslash', async () => {
336
+ await reqApi('rename', { uri: UPLOAD_DEST, dest: 'sub\\file' }, process.platform === 'win32' ? 403 : 200)()
337
+ const d = resolve(ROOT, UPLOAD_DIR)
338
+ await rename(resolve(d, 'sub\\file'), resolve(d, basename(UPLOAD_DEST))).catch(() => {})
339
+ })
340
const renameTo = 'z'
341
test('rename.ok', reqApi('rename', { uri: UPLOAD_DEST, dest: renameTo }, 200))
342
test('delete.miss renamed', req(UPLOAD_DEST, 404, { method: 'delete' }))