Skip to content

Commit

Permalink
feat(server): sanitized path for asset creation process to avoid secu…
Browse files Browse the repository at this point in the history
…rity risk (#717)

* feat(server): sanitized path for asset creation process to avoid security risk

* Sanitize resize path
  • Loading branch information
alextran1502 committed Sep 18, 2022
1 parent ece94f6 commit e3ccc3e
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 841 deletions.
12 changes: 5 additions & 7 deletions server/apps/immich/src/config/asset-upload.config.ts
Expand Up @@ -6,6 +6,7 @@ import { diskStorage } from 'multer';
import { extname, join } from 'path';
import { Request } from 'express';
import { randomUUID } from 'crypto';
import sanitize from 'sanitize-filename';

export const assetUploadOption: MulterOptions = {
fileFilter: (req: Request, file: any, cb: any) => {
Expand All @@ -19,17 +20,13 @@ export const assetUploadOption: MulterOptions = {
storage: diskStorage({
destination: (req: Request, file: Express.Multer.File, cb: any) => {
const basePath = APP_UPLOAD_LOCATION;
// TODO these are currently not used. Shall we remove them?
// const fileInfo = req.body as CreateAssetDto;

// const yearInfo = new Date(fileInfo.createdAt).getFullYear();
// const monthInfo = new Date(fileInfo.createdAt).getMonth();

if (!req.user) {
return;
}

const originalUploadFolder = join(basePath, req.user.id, 'original', req.body['deviceId']);
const sanitizedDeviceId = sanitize(req.body['deviceId']);
const originalUploadFolder = join(basePath, req.user.id, 'original', sanitizedDeviceId);

if (!existsSync(originalUploadFolder)) {
mkdirSync(originalUploadFolder, { recursive: true });
Expand All @@ -41,8 +38,9 @@ export const assetUploadOption: MulterOptions = {

filename: (req: Request, file: Express.Multer.File, cb: any) => {
const fileNameUUID = randomUUID();
const fileName = `${fileNameUUID}${req.body['fileExtension'].toLowerCase()}`;

cb(null, `${fileNameUUID}${req.body['fileExtension'].toLowerCase()}`);
cb(null, sanitize(fileName));
},
}),
};
4 changes: 3 additions & 1 deletion server/apps/immich/src/config/profile-image-upload.config.ts
Expand Up @@ -5,6 +5,7 @@ import { existsSync, mkdirSync } from 'fs';
import { diskStorage } from 'multer';
import { extname } from 'path';
import { Request } from 'express';
import sanitize from 'sanitize-filename';

export const profileImageUploadOption: MulterOptions = {
fileFilter: (req: Request, file: any, cb: any) => {
Expand Down Expand Up @@ -35,8 +36,9 @@ export const profileImageUploadOption: MulterOptions = {
return;
}
const userId = req.user.id;
const fileName = `${userId}${extname(file.originalname)}`;

cb(null, `${userId}${extname(file.originalname)}`);
cb(null, sanitize(fileName));
},
}),
};
10 changes: 8 additions & 2 deletions server/apps/microservices/src/processors/thumbnail.processor.ts
@@ -1,3 +1,4 @@
import { APP_UPLOAD_LOCATION } from '@app/common';
import { ImmichLogLevel } from '@app/common/constants/log-level.constant';
import { AssetEntity, AssetType } from '@app/database/entities/asset.entity';
import {
Expand All @@ -19,9 +20,11 @@ import { Job, Queue } from 'bull';
import ffmpeg from 'fluent-ffmpeg';
import { randomUUID } from 'node:crypto';
import { existsSync, mkdirSync } from 'node:fs';
import sanitize from 'sanitize-filename';
import sharp from 'sharp';
import { Repository } from 'typeorm/repository/Repository';
import { CommunicationGateway } from '../../../immich/src/api-v1/communication/communication.gateway';
import { join } from 'path';
import { CommunicationGateway } from 'apps/immich/src/api-v1/communication/communication.gateway';

@Processor(thumbnailGeneratorQueueName)
export class ThumbnailGeneratorProcessor {
Expand All @@ -46,9 +49,12 @@ export class ThumbnailGeneratorProcessor {

@Process({ name: generateJPEGThumbnailProcessorName, concurrency: 3 })
async generateJPEGThumbnail(job: Job<JpegGeneratorProcessor>) {
const basePath = APP_UPLOAD_LOCATION;

const { asset } = job.data;
const sanitizedDeviceId = sanitize(asset.deviceId);

const resizePath = `upload/${asset.userId}/thumb/${asset.deviceId}/`;
const resizePath = join(basePath, asset.userId, 'thumb', sanitizedDeviceId);

if (!existsSync(resizePath)) {
mkdirSync(resizePath, { recursive: true });
Expand Down

0 comments on commit e3ccc3e

Please sign in to comment.