diff --git a/packages/desktop/packages/shared/src/utils/__tests__/bundle-files.test.ts b/packages/desktop/packages/shared/src/utils/__tests__/bundle-files.test.ts index d6f8c8a04d..cfc6cc9df6 100644 --- a/packages/desktop/packages/shared/src/utils/__tests__/bundle-files.test.ts +++ b/packages/desktop/packages/shared/src/utils/__tests__/bundle-files.test.ts @@ -72,6 +72,25 @@ describe('bundle-files', () => { expect(validateBundleFile(file)).toContain('Path traversal') }) + it('rejects parent traversal segments below the bundle root', () => { + const file: BundleFile = { + relativePath: 'docs/../escape.txt', + contentBase64: Buffer.from('x').toString('base64'), + size: 1, + } + expect(validateBundleFile(file)).toContain('Path traversal') + }) + + it('accepts double dots inside a path segment', () => { + const content = Buffer.from('hello') + const file: BundleFile = { + relativePath: 'docs/release..notes.md', + contentBase64: content.toString('base64'), + size: content.length, + } + expect(validateBundleFile(file)).toBeNull() + }) + it('rejects absolute paths', () => { const file: BundleFile = { relativePath: '/etc/passwd', diff --git a/packages/desktop/packages/shared/src/utils/bundle-files.ts b/packages/desktop/packages/shared/src/utils/bundle-files.ts index c19ffffdbc..b939011774 100644 --- a/packages/desktop/packages/shared/src/utils/bundle-files.ts +++ b/packages/desktop/packages/shared/src/utils/bundle-files.ts @@ -47,6 +47,10 @@ export function fromPortableRelPath(portablePath: string): string { return portablePath.split('/').join(sep) } +function hasParentTraversalSegment(portablePath: string): boolean { + return portablePath.split('/').includes('..') +} + // ============================================================ // Validation // ============================================================ @@ -61,7 +65,7 @@ export function validateBundleFile(file: BundleFile): string | null { } // Path traversal checks - if (file.relativePath.includes('..')) { + if (hasParentTraversalSegment(file.relativePath)) { return `Path traversal detected: ${file.relativePath}` } if (file.relativePath.startsWith('/') || file.relativePath.startsWith('\\')) {