diff --git a/.changeset/calm-pans-work.md b/.changeset/calm-pans-work.md new file mode 100644 index 0000000000..b74c02d243 --- /dev/null +++ b/.changeset/calm-pans-work.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Resolve the `basePath` before constructing the target path diff --git a/packages/backend-common/src/paths.test.ts b/packages/backend-common/src/paths.test.ts index a9a557c8fe..6073d43a24 100644 --- a/packages/backend-common/src/paths.test.ts +++ b/packages/backend-common/src/paths.test.ts @@ -59,5 +59,11 @@ describe('paths', () => { 'Relative path is not allowed to refer to a directory outside its parent', ); }); + + it('should not throw an error when a folder is referenced that doesnt already exist', () => { + expect(resolveSafeChildPath(workspacePath, 'template')).toEqual( + `${workspacePath}/template`, + ); + }); }); }); diff --git a/packages/backend-common/src/paths.ts b/packages/backend-common/src/paths.ts index 0e784a60db..c77f232633 100644 --- a/packages/backend-common/src/paths.ts +++ b/packages/backend-common/src/paths.ts @@ -63,15 +63,17 @@ export function resolvePackagePath(name: string, ...paths: string[]) { * @returns A path that is guaranteed to point to or within the base path. */ export function resolveSafeChildPath(base: string, path: string): string { - const targetPath = resolvePath(base, path); + const resolvedBasePath = resolveRealPath(base); + const targetPath = resolvePath(resolvedBasePath, path); - if (!isChildPath(resolveRealPath(base), resolveRealPath(targetPath))) { + if (!isChildPath(resolvedBasePath, resolveRealPath(targetPath))) { throw new NotAllowedError( 'Relative path is not allowed to refer to a directory outside its parent', ); } - return targetPath; + // Don't return the resolved path as the original could be a symlink + return resolvePath(base, path); } function resolveRealPath(path: string): string {