Skip to content

Commit 0bbbd74

Browse files
fix: sanitization for improved security and stability
1 parent d0afcf5 commit 0bbbd74

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

src/stack.ts

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,8 +1857,9 @@ export class Stack {
18571857
$or: [],
18581858
}
18591859

1860+
const sanitizedQueryBucket = this.sanitizeQueryBucket(queryBucket);
18601861
for (let i = 0, j = paths.length; i < j; i++) {
1861-
this.fetchPathDetails(entries, locale, paths[i].split('.'), queryBucket, shelf, true, entries, 0)
1862+
this.fetchPathDetails(entries, locale, paths[i].split('.'), sanitizedQueryBucket, shelf, true, entries, 0)
18621863
}
18631864

18641865
if (shelf.length === 0) {
@@ -1869,7 +1870,7 @@ export class Stack {
18691870
content_type_uid: this.types.assets,
18701871
locale,
18711872
}, this.collectionNames))
1872-
.find(queryBucket)
1873+
.find(sanitizedQueryBucket) // Use sanitized query here
18731874
.project({
18741875
_content_type_uid: 0,
18751876
_id: 0,
@@ -2017,14 +2018,12 @@ export class Stack {
20172018

20182019
private async bindLeftoverAssets(queries: IQuery, locale: string, pointerList: IShelf[]) {
20192020
// const contents = await readFile(getAssetsPath(locale) + '.json')
2020-
if (!this.sanitizeIQuery(queries)) {
2021-
throw new Error('Invalid queries provided');
2022-
}
2021+
const queriesSanitize = this.sanitizeQueryBucket(queries)
20232022
const filteredAssets = await this.db.collection(getCollectionName({
20242023
content_type_uid: this.types.assets,
20252024
locale,
20262025
}, this.collectionNames))
2027-
.find(queries)
2026+
.find(queriesSanitize)
20282027
.project({
20292028
_content_type_uid: 0,
20302029
_id: 0,
@@ -2434,4 +2433,52 @@ export class Stack {
24342433
}
24352434
return true;
24362435
}
2436+
2437+
private sanitizeQueryBucket(queryBucket: any): any {
2438+
// Validate basic structure
2439+
if (!queryBucket || typeof queryBucket !== 'object') {
2440+
return { $or: [] };
2441+
}
2442+
2443+
// Create a new sanitized query object
2444+
const sanitized = { $or: [] };
2445+
2446+
// Ensure $or is an array
2447+
if (!Array.isArray(queryBucket.$or)) {
2448+
return sanitized;
2449+
}
2450+
2451+
// Process each item in the $or array
2452+
for (const item of queryBucket.$or) {
2453+
if (!item || typeof item !== 'object') {
2454+
continue;
2455+
}
2456+
2457+
const safeItem: any = {};
2458+
2459+
// Only allow specific fields with proper type validation
2460+
if (typeof item._content_type_uid === 'string') {
2461+
safeItem._content_type_uid = item._content_type_uid;
2462+
}
2463+
2464+
if (typeof item.uid === 'string') {
2465+
safeItem.uid = item.uid;
2466+
}
2467+
2468+
if (typeof item.locale === 'string') {
2469+
safeItem.locale = item.locale;
2470+
}
2471+
2472+
if (item._version && typeof item._version === 'object' &&
2473+
typeof item._version.$exists === 'boolean') {
2474+
safeItem._version = { $exists: item._version.$exists };
2475+
}
2476+
2477+
// Only add if required fields are present
2478+
if (safeItem._content_type_uid && safeItem.uid) {
2479+
sanitized.$or.push(safeItem);
2480+
}
2481+
}
2482+
return sanitized;
2483+
}
24372484
}

0 commit comments

Comments
 (0)