Skip to content

Commit 070d7e1

Browse files
committed
fix: add validation to reject insecureRawSQL and insecureRawNoSQL filters in API requests
1 parent a0f464a commit 070d7e1

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

adminforth/modules/restApi.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,6 @@ const filterConditionSchema: AnySchemaObject = {
167167
operator: { type: 'string', enum: SIMPLE_FILTER_OPERATORS },
168168
value: {},
169169
rightField: { type: 'string' },
170-
insecureRawSQL: { type: 'string' },
171-
insecureRawNoSQL: {},
172170
},
173171
additionalProperties: true,
174172
examples: [filterConditionExample],
@@ -242,6 +240,31 @@ const commonFiltersSchema: AnySchemaObject = {
242240
],
243241
};
244242

243+
function hasApiRawFilter(filters: any): boolean {
244+
if (!filters || typeof filters !== 'object') {
245+
return false;
246+
}
247+
248+
if (Array.isArray(filters)) {
249+
return filters.some(hasApiRawFilter);
250+
}
251+
252+
if (
253+
Object.prototype.hasOwnProperty.call(filters, 'insecureRawSQL') ||
254+
Object.prototype.hasOwnProperty.call(filters, 'insecureRawNoSQL')
255+
) {
256+
return true;
257+
}
258+
259+
return Array.isArray(filters.subFilters) && filters.subFilters.some(hasApiRawFilter);
260+
}
261+
262+
function rejectApiRawFilters(filters: any): { error: string } | undefined {
263+
if (hasApiRawFilter(filters)) {
264+
return { error: 'insecureRawSQL and insecureRawNoSQL filters are not allowed in API requests' };
265+
}
266+
}
267+
245268
function createErrorOrSuccessSchema(successSchema: AnySchemaObject): AnySchemaObject {
246269
return {
247270
anyOf: [
@@ -1290,6 +1313,10 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
12901313
if (!resource) {
12911314
return { error: `Resource ${resourceId} not found` };
12921315
}
1316+
const rawFilterError = rejectApiRawFilters(body.filters);
1317+
if (rawFilterError) {
1318+
return rawFilterError;
1319+
}
12931320

12941321
const meta = { requestBody: body, pk: undefined };
12951322
if (source === 'edit' || source === 'show') {
@@ -1692,6 +1719,10 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
16921719
if (!resource) {
16931720
return { error: `Resource ${resourceId} not found` };
16941721
}
1722+
const rawFilterError = rejectApiRawFilters(filters);
1723+
if (rawFilterError) {
1724+
return rawFilterError;
1725+
}
16951726

16961727
const meta = { requestBody: body, pk: undefined };
16971728
const { allowedActions } = await interpretResource(
@@ -1772,6 +1803,10 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
17721803
if (!columnConfig.foreignResource) {
17731804
return { error: `Column '${column}' in resource '${resourceId}' is not a foreign key` };
17741805
}
1806+
const rawFilterError = rejectApiRawFilters(body.filters);
1807+
if (rawFilterError) {
1808+
return rawFilterError;
1809+
}
17751810

17761811
const targetResourceIds = columnConfig.foreignResource.resourceId ? [columnConfig.foreignResource.resourceId] : columnConfig.foreignResource.polymorphicResources.filter(pr => pr.resourceId !== null).map((pr) => pr.resourceId);
17771812
const targetResources = targetResourceIds.map((trId) => this.adminforth.config.resources.find((res) => res.resourceId == trId));

0 commit comments

Comments
 (0)