@solidxai/core 0.1.13-beta.14 → 0.1.13-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1150 -0
- package/dist/constants/media-file-types.d.ts +2 -0
- package/dist/constants/media-file-types.d.ts.map +1 -1
- package/dist/constants/media-file-types.js +26 -7
- package/dist/constants/media-file-types.js.map +1 -1
- package/dist/filters/http-exception.filter.d.ts.map +1 -1
- package/dist/filters/http-exception.filter.js +5 -1
- package/dist/filters/http-exception.filter.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts +3 -1
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
- package/dist/helpers/bootstrap.helper.js +6 -2
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/helpers/file-download.helper.d.ts.map +1 -1
- package/dist/helpers/file-download.helper.js +6 -1
- package/dist/helpers/file-download.helper.js.map +1 -1
- package/dist/services/media-storage.utils.d.ts +1 -0
- package/dist/services/media-storage.utils.d.ts.map +1 -1
- package/dist/services/media-storage.utils.js +12 -1
- package/dist/services/media-storage.utils.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +2 -1
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +2 -1
- package/dist/services/setting.service.js.map +1 -1
- package/dist/solid-core.module.d.ts +1 -3
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +0 -39
- package/dist/solid-core.module.js.map +1 -1
- package/package.json +1 -1
- package/src/constants/media-file-types.ts +58 -9
- package/src/filters/http-exception.filter.ts +11 -1
- package/src/helpers/bootstrap.helper.ts +22 -3
- package/src/helpers/file-download.helper.ts +15 -1
- package/src/services/media-storage.utils.ts +26 -1
- package/src/services/module-metadata.service.ts +3 -1
- package/src/services/setting.service.ts +3 -1
- package/src/solid-core.module.ts +5 -12
|
@@ -5,6 +5,11 @@ import { MediaStorageProviderMetadata } from 'src/entities/media-storage-provide
|
|
|
5
5
|
import { SettingService } from 'src/services/setting.service';
|
|
6
6
|
import { DEFAULT_MEDIA_FILE_STORAGE_DIR } from 'src/services/settings/default-settings-provider.service';
|
|
7
7
|
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
8
|
+
import { normalizeUploadedFileName } from 'src/constants/media-file-types';
|
|
9
|
+
|
|
10
|
+
// Keeps the joined path well clear of filesystem NAME_MAX (255 on ext4/APFS) once the
|
|
11
|
+
// multer hash prefix and separator are added.
|
|
12
|
+
const MAX_STORED_FILE_NAME_LENGTH = 150;
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
export interface MediaRecordCreateInput {
|
|
@@ -18,9 +23,29 @@ export interface MediaRecordCreateInput {
|
|
|
18
23
|
originalFileName?: string;
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Reduces a client-supplied name to something safe to interpolate into a filesystem path.
|
|
28
|
+
* `originalname` is fully attacker-controlled, so without this a name like
|
|
29
|
+
* `../../../../tmp/pwned.png` escapes the media storage directory entirely - the multer hash
|
|
30
|
+
* prefix does not contain it, because the leading `..` simply cancels the prefix segment.
|
|
31
|
+
*
|
|
32
|
+
* Everything outside a conservative allowlist becomes `_`; the result can never contain a
|
|
33
|
+
* path separator, so the joined path always stays inside the storage root.
|
|
34
|
+
*/
|
|
35
|
+
export function sanitizeStoredMediaFileName(originalName?: string | null): string {
|
|
36
|
+
const sanitized = normalizeUploadedFileName(originalName)
|
|
37
|
+
.replace(/[^A-Za-z0-9._-]/g, '_')
|
|
38
|
+
// Collapse any run of dots so no `..` segment can survive.
|
|
39
|
+
.replace(/\.{2,}/g, '.')
|
|
40
|
+
.replace(/^[._-]+/, '')
|
|
41
|
+
.slice(0, MAX_STORED_FILE_NAME_LENGTH);
|
|
42
|
+
|
|
43
|
+
return sanitized || 'file';
|
|
44
|
+
}
|
|
45
|
+
|
|
21
46
|
// Builds the stored file name format shared by media storage implementations.
|
|
22
47
|
export function buildStoredMediaFileName(file: Pick<Express.Multer.File, 'filename' | 'originalname'>): string {
|
|
23
|
-
return `${file.filename}-${file.originalname}`;
|
|
48
|
+
return `${file.filename}-${sanitizeStoredMediaFileName(file.originalname)}`;
|
|
24
49
|
}
|
|
25
50
|
|
|
26
51
|
// Resolves the on-disk path for a media file based on settings and provider visibility.
|
|
@@ -18,6 +18,7 @@ import { ModuleMetadataHelperService } from 'src/helpers/module-metadata-helper.
|
|
|
18
18
|
import { ModuleMetadataRepository } from 'src/repository/module-metadata.repository';
|
|
19
19
|
import { PermissionMetadataSeederService } from 'src/seeders/permission-metadata-seeder.service';
|
|
20
20
|
import { DiskFileService } from 'src/services/file';
|
|
21
|
+
import { sanitizeStoredMediaFileName } from 'src/services/media-storage.utils';
|
|
21
22
|
import { BasicFilterDto } from '../dtos/basic-filters.dto';
|
|
22
23
|
import { UpdateModuleMetadataDto } from '../dtos/update-module-metadata.dto';
|
|
23
24
|
import {
|
|
@@ -609,7 +610,8 @@ export class ModuleMetadataService {
|
|
|
609
610
|
}
|
|
610
611
|
|
|
611
612
|
private getFileName(file: Express.Multer.File): string {
|
|
612
|
-
|
|
613
|
+
// originalname is attacker-controlled and feeds straight into a storage path.
|
|
614
|
+
return `${file.filename}-${sanitizeStoredMediaFileName(file.originalname)}`;
|
|
613
615
|
}
|
|
614
616
|
|
|
615
617
|
}
|
|
@@ -16,6 +16,7 @@ import { ModuleMetadataRepository } from 'src/repository/module-metadata.reposit
|
|
|
16
16
|
import type { SolidCoreSetting } from './settings/default-settings-provider.service';
|
|
17
17
|
import { Logger } from '@nestjs/common';
|
|
18
18
|
import { EncryptionService } from './encryption.service';
|
|
19
|
+
import { sanitizeStoredMediaFileName } from './media-storage.utils';
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@Injectable()
|
|
@@ -358,7 +359,8 @@ export class SettingService {
|
|
|
358
359
|
if (uploadedFiles?.length) {
|
|
359
360
|
for (const file of uploadedFiles) {
|
|
360
361
|
const settingKey = file.fieldname;
|
|
361
|
-
|
|
362
|
+
// originalname is attacker-controlled and feeds straight into a storage path.
|
|
363
|
+
const relativeFileName = `${file.filename}-${sanitizeStoredMediaFileName(file.originalname)}`;
|
|
362
364
|
|
|
363
365
|
// Read file from local disk (where Multer stores uploads) and write to storage
|
|
364
366
|
// The path builder constructs the provider-appropriate storage path
|
package/src/solid-core.module.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import "multer";
|
|
2
|
-
import { Global,
|
|
3
|
-
import * as express from "express";
|
|
2
|
+
import { Global, Module } from "@nestjs/common";
|
|
4
3
|
import { ConfigModule, ConfigService } from "@nestjs/config";
|
|
5
4
|
import {
|
|
6
5
|
APP_FILTER,
|
|
@@ -1050,13 +1049,7 @@ import { SwitchNode } from './services/workflow/nodes/switch.node';
|
|
|
1050
1049
|
WorkflowExpressionService,
|
|
1051
1050
|
],
|
|
1052
1051
|
})
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
express.json({ limit: "10mb" }),
|
|
1058
|
-
express.urlencoded({ limit: "10mb", extended: true }),
|
|
1059
|
-
)
|
|
1060
|
-
.forRoutes("*");
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1052
|
+
// Body-size limits live in bootstrapSolidApp (see SolidBootstrapOptions.bodyLimit).
|
|
1053
|
+
// They cannot be applied here: module middleware is registered in registerRouter(),
|
|
1054
|
+
// which runs after Nest's own parser middleware, so anything set here never takes effect.
|
|
1055
|
+
export class SolidCoreModule {}
|