Skip to content

Commit 7936062

Browse files
committed
fix: critical security risk
1 parent 68c8ea6 commit 7936062

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

  • apps/frontend/src/app/(app)/api/uploads/[[...path]]

apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NextRequest, NextResponse } from 'next/server';
22
import { createReadStream, statSync } from 'fs';
3+
import { resolve, sep } from 'path';
34
// @ts-ignore
45
import mime from 'mime';
56
async function* nodeStreamToIterator(stream: any) {
@@ -28,8 +29,13 @@ export const GET = async (
2829
}
2930
) => {
3031
const { path } = await context.params;
31-
const filePath =
32-
process.env.UPLOAD_DIRECTORY + '/' + (path ?? []).join('/');
32+
const base = resolve(process.env.UPLOAD_DIRECTORY!);
33+
const filePath = resolve(base, (path ?? []).join('/'));
34+
// Confine reads to UPLOAD_DIRECTORY. resolve() collapses any `..` segments
35+
// (including URL-decoded ones), so this blocks every path-traversal variant.
36+
if (filePath !== base && !filePath.startsWith(base + sep)) {
37+
return new NextResponse('Not found', { status: 404 });
38+
}
3339
const response = createReadStream(filePath);
3440
const fileStats = statSync(filePath);
3541
const contentType = mime.getType(filePath) || 'application/octet-stream';

0 commit comments

Comments
 (0)