diff --git a/server/routes/api/torrents.test.ts b/server/routes/api/torrents.test.ts index 78556e96..b3469fd4 100644 --- a/server/routes/api/torrents.test.ts +++ b/server/routes/api/torrents.test.ts @@ -28,8 +28,6 @@ const authToken = `jwt=${getAuthToken('_config')}`; const tempDirectory = getTempPath('download'); -fs.mkdirSync(tempDirectory, {recursive: true}); - jest.setTimeout(20000); const torrentFiles = [ @@ -242,7 +240,11 @@ describe('POST /api/torrents/create', () => { }; const dummyFilePath = path.join(tempDirectory, 'dummy'); - fs.writeFileSync(dummyFilePath, 'test'); + + beforeAll(() => { + fs.mkdirSync(tempDirectory, {recursive: true}); + fs.writeFileSync(dummyFilePath, 'test'); + }); it('Creates a multi-file torrent', (done) => { const torrentAdded = watchTorrentList('add'); diff --git a/server/services/interfaces/clientGatewayService.ts b/server/services/interfaces/clientGatewayService.ts index 922f8309..c52afffc 100644 --- a/server/services/interfaces/clientGatewayService.ts +++ b/server/services/interfaces/clientGatewayService.ts @@ -89,7 +89,6 @@ abstract class ClientGatewayService extends BaseService} - Rejects with error. @@ -130,6 +129,7 @@ abstract class ClientGatewayService extends BaseService} indices - Indices of contents to be altered. * @param {number} priority - Target priority. diff --git a/server/util/fileUtil.ts b/server/util/fileUtil.ts index 263dc8fc..31c501ad 100644 --- a/server/util/fileUtil.ts +++ b/server/util/fileUtil.ts @@ -20,15 +20,30 @@ export const isAllowedPath = (resolvedPath: string) => { if (config.allowedPaths == null) { return true; } + + let realPath: string | null = null; + let parentPath: string = resolvedPath; + while (realPath == null) { + try { + realPath = fs.realpathSync(parentPath); + } catch (e) { + if (e.code === 'ENOENT') { + parentPath = path.resolve(parentPath, '..'); + } else { + return false; + } + } + } + return config.allowedPaths.some((allowedPath) => { - if (resolvedPath.startsWith(allowedPath)) { + if (realPath?.startsWith(allowedPath)) { return true; } return false; }); }; -export const sanitizePath = (input: string) => { +export const sanitizePath = (input: string): string => { if (typeof input !== 'string') { throw accessDeniedError(); }