From c0be00d9fef100dfd4b741a6ed2b7710f1ce5e89 Mon Sep 17 00:00:00 2001 From: joan vicens Date: Wed, 30 Nov 2022 15:52:58 +0100 Subject: [PATCH] fix: sanitaze paths before validating them --- src/workers/utils/name-verification.ts | 14 ++++- .../utils/test/name-verification.test.ts | 59 ++++++++++++++++--- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/workers/utils/name-verification.ts b/src/workers/utils/name-verification.ts index a6ad54ff4..be77f3675 100644 --- a/src/workers/utils/name-verification.ts +++ b/src/workers/utils/name-verification.ts @@ -1,13 +1,21 @@ +import path from 'path'; + const isWindowsRootDirectory = /[a-zA-Z]:[\\/]/; const containsNullCharacter = /\0/g; const validations = [ (name: string) => name.includes('../'), + (name: string) => name.includes('..'), (name: string) => name.startsWith('/'), (name: string) => isWindowsRootDirectory.test(name), - (name: string) => name.includes('\\'), (name: string) => containsNullCharacter.test(name), ]; -export const fileNameIsValid = (fileName: string): boolean => - validations.every((validation) => !validation(fileName)); +const sanitazeRelativePath = (relativePath: string) => + relativePath.replaceAll(path.sep, '/'); + +export const fileNameIsValid = (fileName: string): boolean => { + const sanitazedPath = sanitazeRelativePath(fileName); + + return validations.every((validation) => !validation(sanitazedPath)); +}; diff --git a/src/workers/utils/test/name-verification.test.ts b/src/workers/utils/test/name-verification.test.ts index 8b269bce6..18c02455e 100644 --- a/src/workers/utils/test/name-verification.test.ts +++ b/src/workers/utils/test/name-verification.test.ts @@ -2,6 +2,8 @@ import { fileNameIsValid } from '../name-verification'; import sensibleFiles from './sensible-files.json'; +const path = require('path'); + describe('name verifiaction test', () => { const INVALID = false; const VALID = true; @@ -24,15 +26,6 @@ describe('name verifiaction test', () => { }); describe('firts level files', () => { - it('startup folder is not valid', () => { - const maliciousFileName = - '..App\\DataRoaming\\MicrosoftWindows\\Start Menu\\Programs\\Startup'; - - const result = fileNameIsValid(maliciousFileName); - - expect(result).toBe(INVALID); - }); - it('parent folder is not valid', () => { const maliciousFileName = '../file.txt'; @@ -106,4 +99,52 @@ describe('name verifiaction test', () => { expect(result).toBe(INVALID); }); }); + + describe('windows file system', () => { + let originalPathSeparation: string; + + beforeAll(() => { + originalPathSeparation = path.sep as string; + path.sep = '\\'; + }); + + afterAll(() => { + path.sep = originalPathSeparation; + }); + + it('startup folder is not valid', () => { + const maliciousFileName = + '..App\\DataRoaming\\MicrosoftWindows\\Start Menu\\Programs\\Startup'; + + const result = fileNameIsValid(maliciousFileName); + + expect(result).toBe(INVALID); + }); + + it('second level files on windows are valid', () => { + const fileName = 'folder_name\\my-image.jpg'; + + const result = fileNameIsValid(fileName); + + expect(result).toBe(VALID); + }); + + describe('n level files', () => { + const correctWindowsFiles = [ + 'folder_name\\my-images\\cat.jpg', + 'cat.jpg', + 'folder_name\\my-images\\february\\cat.jpg', + 'folder_name\\my-image.jpg', + ]; + + it.each(correctWindowsFiles)( + 'valid paths are correctly validated', + (fileName: string) => { + const result = fileNameIsValid(fileName); + + expect(result).toBe(VALID); + } + ); + }); + }); });