From 3216494a5435b229764a98c4ae7874da93602e0c Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 24 Feb 2025 10:06:33 -0800 Subject: [PATCH 1/2] fix 0323 code ql --- src/server/serverBase.ts | 7 ++++--- src/server/utils.ts | 21 +++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/server/serverBase.ts b/src/server/serverBase.ts index d19b8308..bd962efc 100644 --- a/src/server/serverBase.ts +++ b/src/server/serverBase.ts @@ -14,7 +14,7 @@ import * as he from 'he'; import { EventHubConsumerClient, Subscription, ReceivedEventData, earliestEventPosition } from '@azure/event-hubs'; import { generateDataPlaneRequestBody, generateDataPlaneResponse } from './dataPlaneHelper'; import { convertIotHubToEventHubsConnectionString } from './eventHubHelper'; -import { fetchDirectories, findMatchingFile, readFileFromLocal, SAFE_ROOT } from './utils'; +import { checkPath, fetchDirectories, findMatchingFile, readFileFromLocal, SAFE_ROOT } from './utils'; export const SERVER_ERROR = 500; export const SUCCESS = 200; @@ -89,9 +89,10 @@ export const handleReadFileRequest = (req: express.Request, res: express.Respons res.status(BAD_REQUEST).send(); } else { - const fileNames = fs.readdirSync(filePath); + const resolvedPath = checkPath(filePath); + const fileNames = fs.readdirSync(resolvedPath); try { - const foundContent = findMatchingFile(filePath, fileNames, expectedFileName); + const foundContent = findMatchingFile(resolvedPath, fileNames, expectedFileName); if (foundContent) { res.status(SUCCESS).send(foundContent); } diff --git a/src/server/utils.ts b/src/server/utils.ts index 8db30a5c..8e381bc1 100644 --- a/src/server/utils.ts +++ b/src/server/utils.ts @@ -29,13 +29,7 @@ export const SAFE_ROOT = getSafeRoot(); export const fetchDirectories = (dir: string, res: express.Response) => { try { - // Resolve the requested directory relative to the safe root - const resolvedPath = fs.realpathSync(path.resolve(SAFE_ROOT, path.relative(SAFE_ROOT, dir))); - - // Ensure resolvedPath is still inside SAFE_ROOT (prevents traversal attacks) - if (!resolvedPath.startsWith(SAFE_ROOT)) { - return res.status(403).send({ error: "Access denied. Unsafe directory." }); - } + const resolvedPath = checkPath(dir); const result: string[] = []; for (const item of fs.readdirSync(resolvedPath)) { @@ -101,12 +95,19 @@ const isFileExtensionJson = (fileName: string) => { export const readFileFromLocal = (filePath: string, fileName: string) => { // Resolve the requested directory relative to the safe root - const resolvedPath = fs.realpathSync(path.resolve(SAFE_ROOT, path.relative(SAFE_ROOT, `${filePath}/${fileName}`))); + const resolvedPath = checkPath(`${filePath}/${fileName}`); + + return fs.readFileSync(resolvedPath, 'utf-8'); +} + +export const checkPath = (filePath: string) => { + // Resolve the requested directory relative to the safe root + const resolvedPath = fs.realpathSync(path.resolve(SAFE_ROOT, path.relative(SAFE_ROOT, filePath))); // Ensure resolvedPath is still inside SAFE_ROOT (prevents traversal attacks) if (!resolvedPath.startsWith(SAFE_ROOT)) { throw new Error("Access denied. Unsafe directory."); } - - return fs.readFileSync(`${filePath}/${fileName}`, 'utf-8'); + + return resolvedPath; } From cbe78e4f6ed2bed06e57a4532021c0069475c5f2 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 14 Mar 2025 12:20:17 -0700 Subject: [PATCH 2/2] fix error message --- .../components/listItemConfigurableRepo.spec.tsx | 2 -- src/server/serverBase.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/modelRepository/components/listItemConfigurableRepo.spec.tsx b/src/app/modelRepository/components/listItemConfigurableRepo.spec.tsx index 72580fb4..2faf176e 100644 --- a/src/app/modelRepository/components/listItemConfigurableRepo.spec.tsx +++ b/src/app/modelRepository/components/listItemConfigurableRepo.spec.tsx @@ -9,8 +9,6 @@ import { ListItemConfigurableRepo } from './listItemConfigurableRepo'; import { REPOSITORY_LOCATION_TYPE } from '../../constants/repositoryLocationTypes'; import { getInitialModelRepositoryFormState } from '../state'; import { getInitialModelRepositoryFormOps } from '../interface'; -import { act } from 'react-dom/test-utils'; -import { TextField } from '@fluentui/react'; describe('ListItemConfigurableRepo', () => { it('matches snapshot', () => { diff --git a/src/server/serverBase.ts b/src/server/serverBase.ts index bd962efc..ec55cf13 100644 --- a/src/server/serverBase.ts +++ b/src/server/serverBase.ts @@ -101,7 +101,7 @@ export const handleReadFileRequest = (req: express.Request, res: express.Respons } } catch (error) { - res.status(NOT_FOUND).send(error.message); // couldn't find matching file, and the folder contains json files that cannot be parsed + res.status(NOT_FOUND).send('Not able to find any matching file.'); // couldn't find matching file, and the folder contains json files that cannot be parsed } }