diff --git a/packages/core/src/utils.test.ts b/packages/core/src/utils.test.ts index 8780ded..8e44938 100644 --- a/packages/core/src/utils.test.ts +++ b/packages/core/src/utils.test.ts @@ -108,6 +108,10 @@ it('getFilenameFromContentDisposition', () => { expect(getFilenameFromContentDisposition('inline; x="; filename*=utf-8\'\'evil.exe')).toEqual(undefined) expect(getFilenameFromContentDisposition('inline; filename="a\\"')).toEqual(undefined) + // malformed escapes in filename* are kept as-is, the valid ones are still decoded + expect(getFilenameFromContentDisposition('attachment; filename*=utf-8\'\'%E4%B8%AD%ZZ.txt')).toEqual('中%ZZ.txt') + expect(getFilenameFromContentDisposition('inline; filename*=%E2%82%AC%.txt')).toEqual('€%.txt') + // quoted filename* is tolerated expect(getFilenameFromContentDisposition('attachment; filename*="utf-8\'\'%E2%82%AC.txt"')).toEqual('€.txt') diff --git a/packages/shared/src/uri.test.ts b/packages/shared/src/uri.test.ts index dca337a..34fef34 100644 --- a/packages/shared/src/uri.test.ts +++ b/packages/shared/src/uri.test.ts @@ -28,9 +28,15 @@ describe('safeDecodeURIComponent', () => { expect(safeDecodeURIComponent('')).toBe('') }) - it('returns malformed input unchanged instead of throwing', () => { - expect(safeDecodeURIComponent('invalid%20value%')).toBe('invalid%20value%') + it('keeps malformed escapes as-is and still decodes the valid ones instead of throwing', () => { + expect(safeDecodeURIComponent('invalid%20value%')).toBe('invalid value%') expect(safeDecodeURIComponent('%E0%A4%A')).toBe('%E0%A4%A') // Invalid UTF-8 sequence expect(safeDecodeURIComponent('%ZZ')).toBe('%ZZ') + expect(safeDecodeURIComponent('%ZZ%e4%b8%ad%')).toBe('%ZZ中%') + expect(safeDecodeURIComponent('%FF-%E2%82%AC')).toBe('%FF-€') + // a run of escapes that is not valid UTF-8 is kept as a whole + expect(safeDecodeURIComponent('%E4%B8%AD%FF%')).toBe('%E4%B8%AD%FF%') + // decoded output is not decoded again + expect(safeDecodeURIComponent('%2541%ZZ')).toBe('%41%ZZ') }) }) diff --git a/packages/shared/src/uri.ts b/packages/shared/src/uri.ts index d0e2e67..cc72a6e 100644 --- a/packages/shared/src/uri.ts +++ b/packages/shared/src/uri.ts @@ -1,4 +1,5 @@ const LONE_SURROGATE_REGEX = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(? { + try { + // eslint-disable-next-line no-restricted-globals + return decodeURIComponent(escapes) + } + catch { + return escapes + } + }) } }