mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
feat(server): sanitized path for asset creation process to avoid security risk (#717)
* feat(server): sanitized path for asset creation process to avoid security risk * Sanitize resize path
This commit is contained in:
parent
ece94f6bdc
commit
e3ccc3ee6b
5 changed files with 323 additions and 842 deletions
|
@ -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) => {
|
||||
|
@ -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 });
|
||||
|
@ -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));
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
@ -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));
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -46,9 +49,12 @@ export class ThumbnailGeneratorProcessor {
|
|||
|
||||
@Process({ name: generateJPEGThumbnailProcessorName, concurrency: 3 })
|
||||
async generateJPEGThumbnail(job: Job<JpegGeneratorProcessor>) {
|
||||
const { asset } = job.data;
|
||||
const basePath = APP_UPLOAD_LOCATION;
|
||||
|
||||
const resizePath = `upload/${asset.userId}/thumb/${asset.deviceId}/`;
|
||||
const { asset } = job.data;
|
||||
const sanitizedDeviceId = sanitize(asset.deviceId);
|
||||
|
||||
const resizePath = join(basePath, asset.userId, 'thumb', sanitizedDeviceId);
|
||||
|
||||
if (!existsSync(resizePath)) {
|
||||
mkdirSync(resizePath, { recursive: true });
|
||||
|
|
1133
server/package-lock.json
generated
1133
server/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -37,7 +37,6 @@
|
|||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/passport": "^8.2.2",
|
||||
"@nestjs/platform-express": "^8.4.7",
|
||||
"@nestjs/platform-fastify": "^8.4.7",
|
||||
"@nestjs/platform-socket.io": "^8.4.7",
|
||||
"@nestjs/schedule": "^2.0.1",
|
||||
"@nestjs/swagger": "^5.2.1",
|
||||
|
@ -56,13 +55,14 @@
|
|||
"fluent-ffmpeg": "^2.1.2",
|
||||
"joi": "^17.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"passport": "^0.5.2",
|
||||
"passport": "^0.6.0",
|
||||
"passport-jwt": "^4.0.0",
|
||||
"pg": "^8.7.1",
|
||||
"redis": "^3.1.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.2.0",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sharp": "^0.28.0",
|
||||
"socket.io-redis": "^6.1.1",
|
||||
"swagger-ui-express": "^4.4.0",
|
||||
|
|
Loading…
Reference in a new issue