Skip to content

Commit

Permalink
fix(server): only allow absolute import paths (#13642)
Browse files Browse the repository at this point in the history
fix: only allow absolute paths
  • Loading branch information
etnoy authored Oct 21, 2024
1 parent 56bebd0 commit b411e30
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 7 deletions.
23 changes: 23 additions & 0 deletions e2e/src/api/specs/library.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,29 @@ describe('/libraries', () => {
});
});

it("should fail if path isn't absolute", async () => {
const pathToTest = `relative/path`;

const cwd = process.cwd();
// Create directory in cwd
utils.createDirectory(`${cwd}/${pathToTest}`);

const response = await utils.validateLibrary(admin.accessToken, library.id, {
importPaths: [pathToTest],
});

utils.removeDirectory(`${cwd}/${pathToTest}`);

expect(response.importPaths?.length).toEqual(1);
const pathResponse = response?.importPaths?.at(0);

expect(pathResponse).toEqual({
importPath: pathToTest,
isValid: false,
message: expect.stringMatching('Import path must be absolute, try /usr/src/app/relative/path'),
});
});

it('should fail if path is a file', async () => {
const pathToTest = `${testAssetDirInternal}/albums/nature/el_torcal_rocks.jpg`;

Expand Down
29 changes: 24 additions & 5 deletions server/src/services/library.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,9 @@ describe(LibraryService.name, () => {
storageMock.stat.mockResolvedValue({ isDirectory: () => true } as Stats);
storageMock.checkFileExists.mockResolvedValue(true);

await expect(sut.update('library-id', { importPaths: ['foo/bar'] })).resolves.toEqual(
const cwd = process.cwd();

await expect(sut.update('library-id', { importPaths: [`${cwd}/foo/bar`] })).resolves.toEqual(
mapLibrary(libraryStub.externalLibrary1),
);
expect(libraryMock.update).toHaveBeenCalledWith(expect.objectContaining({ id: 'library-id' }));
Expand Down Expand Up @@ -1300,14 +1302,31 @@ describe(LibraryService.name, () => {
});
});

it('should detect when import path is not absolute', async () => {
const cwd = process.cwd();

await expect(sut.validate('library-id', { importPaths: ['relative/path'] })).resolves.toEqual({
importPaths: [
{
importPath: 'relative/path',
isValid: false,
message: `Import path must be absolute, try ${cwd}/relative/path`,
},
],
});
});

it('should detect when import path is in immich media folder', async () => {
storageMock.stat.mockResolvedValue({ isDirectory: () => true } as Stats);
const validImport = libraryStub.hasImmichPaths.importPaths[1];
const cwd = process.cwd();

const validImport = `${cwd}/${libraryStub.hasImmichPaths.importPaths[1]}`;
storageMock.checkFileExists.mockImplementation((importPath) => Promise.resolve(importPath === validImport));

await expect(
sut.validate('library-id', { importPaths: libraryStub.hasImmichPaths.importPaths }),
).resolves.toEqual({
const pathStubs = libraryStub.hasImmichPaths.importPaths;
const importPaths = [pathStubs[0], validImport, pathStubs[2]];

await expect(sut.validate('library-id', { importPaths })).resolves.toEqual({
importPaths: [
{
importPath: libraryStub.hasImmichPaths.importPaths[0],
Expand Down
7 changes: 6 additions & 1 deletion server/src/services/library.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { R_OK } from 'node:constants';
import path, { basename, parse } from 'node:path';
import path, { basename, isAbsolute, parse } from 'node:path';
import picomatch from 'picomatch';
import { StorageCore } from 'src/cores/storage.core';
import { OnEvent } from 'src/decorators';
Expand Down Expand Up @@ -268,6 +268,11 @@ export class LibraryService extends BaseService {
return validation;
}

if (!isAbsolute(importPath)) {
validation.message = `Import path must be absolute, try ${path.resolve(importPath)}`;
return validation;
}

try {
const stat = await this.storageRepository.stat(importPath);
if (!stat.isDirectory()) {
Expand Down
2 changes: 1 addition & 1 deletion server/test/fixtures/library.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const libraryStub = {
assets: [],
owner: userStub.admin,
ownerId: 'user-id',
importPaths: ['upload/thumbs', '/xyz', 'upload/library'],
importPaths: ['upload/thumbs', 'xyz', 'upload/library'],
createdAt: new Date('2023-01-01'),
updatedAt: new Date('2023-01-01'),
refreshedAt: null,
Expand Down

0 comments on commit b411e30

Please sign in to comment.