Merge pull request #1096 from bigcapitalhq/fix/predictable-s3-attachment-keys
fix(server): use CSPRNG for attachment S3 keys (GHSA-gj48-p5ff-g67f)
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.alterTable('documents', (table) => {
|
||||||
|
table.unique('key');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.alterTable('documents', (table) => {
|
||||||
|
table.dropUnique('key');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
import { randomUUID } from 'node:crypto';
|
||||||
import * as multerS3 from 'multer-s3';
|
import * as multerS3 from 'multer-s3';
|
||||||
|
import { ClsService } from 'nestjs-cls';
|
||||||
import { S3_CLIENT, S3Module } from "../S3/S3.module";
|
import { S3_CLIENT, S3Module } from "../S3/S3.module";
|
||||||
import { DeleteAttachment } from "./DeleteAttachment";
|
import { DeleteAttachment } from "./DeleteAttachment";
|
||||||
import { GetAttachment } from "./GetAttachment";
|
import { GetAttachment } from "./GetAttachment";
|
||||||
@@ -59,8 +61,12 @@ const models = [
|
|||||||
AttachmentUploadPipeline,
|
AttachmentUploadPipeline,
|
||||||
{
|
{
|
||||||
provide: MULTER_MODULE_OPTIONS,
|
provide: MULTER_MODULE_OPTIONS,
|
||||||
inject: [ConfigService, S3_CLIENT],
|
inject: [ConfigService, S3_CLIENT, ClsService],
|
||||||
useFactory: (configService: ConfigService, s3: S3Client) => ({
|
useFactory: (
|
||||||
|
configService: ConfigService,
|
||||||
|
s3: S3Client,
|
||||||
|
cls: ClsService,
|
||||||
|
) => ({
|
||||||
storage: multerS3({
|
storage: multerS3({
|
||||||
s3,
|
s3,
|
||||||
bucket: configService.get('s3.bucket'),
|
bucket: configService.get('s3.bucket'),
|
||||||
@@ -69,7 +75,11 @@ const models = [
|
|||||||
cb(null, { fieldName: file.fieldname });
|
cb(null, { fieldName: file.fieldname });
|
||||||
},
|
},
|
||||||
key: function (req, file, cb) {
|
key: function (req, file, cb) {
|
||||||
cb(null, Date.now().toString());
|
const organizationId = cls.get<string>('organizationId');
|
||||||
|
if (!organizationId) {
|
||||||
|
return cb(new Error('Tenant context required for upload.'), undefined as any);
|
||||||
|
}
|
||||||
|
cb(null, `${organizationId}/${randomUUID()}`);
|
||||||
},
|
},
|
||||||
acl: function(req, file, cb) {
|
acl: function(req, file, cb) {
|
||||||
// Conditionally set file to public or private based on isPublic flag
|
// Conditionally set file to public or private based on isPublic flag
|
||||||
|
|||||||
Reference in New Issue
Block a user