fix: Prevent illegal file paths from being generated

This commit is contained in:
Joachim Van Herwegen 2023-06-08 13:24:30 +02:00
parent 3fbdc69f3f
commit fdee4b334f
2 changed files with 22 additions and 2 deletions

View File

@ -155,16 +155,31 @@ export function toCanonicalUriPath(path: string): string {
encodeURIComponent(decodeURIComponent(part)));
}
// Characters not allowed in a Windows file path
const forbiddenSymbols = {
'<': '%3C',
'>': '%3E',
':': '%3A',
'"': '%22',
'|': '%7C',
'?': '%3F',
// `*` does not get converted by `encodeUriComponent`
'*': '%2A',
} as const;
const forbiddenRegex = new RegExp(`[${Object.keys(forbiddenSymbols).join('')}]`, 'ug');
/**
* This function is used when converting a URI to a file path. Decodes all components of a URI path,
* with the exception of encoded slash characters, as this would lead to unexpected file locations
* being targeted (resulting in erroneous behaviour of the file based backend).
* Characters that would result in an illegal file path remain percent encoded.
*
* @param path - The path to decode the URI path components of.
* @returns A decoded copy of the provided URI path (ignoring encoded slash characters).
*/
export function decodeUriPathComponents(path: string): string {
return transformPathComponents(path, decodeURIComponent);
return transformPathComponents(path, (part): string => decodeURIComponent(part)
// The characters replaced below result in illegal Windows file paths so need to be encoded
.replace(forbiddenRegex, (val): string => forbiddenSymbols[val as keyof typeof forbiddenSymbols]));
}
/**

View File

@ -96,7 +96,7 @@ describe('PathUtil', (): void => {
describe('#toCanonicalUriPath', (): void => {
it('encodes only the necessary parts.', (): void => {
expect(toCanonicalUriPath('/a%20path&/name')).toBe('/a%20path%26/name');
expect(toCanonicalUriPath('/a%20path&*/name')).toBe('/a%20path%26*/name');
});
it('leaves the query string untouched.', (): void => {
@ -138,6 +138,11 @@ describe('PathUtil', (): void => {
expect(decodeUriPathComponents('/a%25252Fb')).toBe('/a%25252Fb');
expect(decodeUriPathComponents('/a%2525252Fb')).toBe('/a%2525252Fb');
});
it('ensures illegal path characters are encoded.', async(): Promise<void> => {
expect(decodeUriPathComponents('/a<path%3F%3E/*:name?abc=def&xyz'))
.toBe('/a%3Cpath%3F%3E/%2A%3Aname?abc=def&xyz');
});
});
describe('#encodeUriPathComponents', (): void => {