When setting EntityOptions.apiPrefilter to a function, the filter is not applied to API requests for a resource by Id
Description
Remult CRUD framework's apiPrefilter function bypass allows unauthorized read/update/delete if attacker knows entity ID; fixed in v0.20.6.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Remult CRUD framework's apiPrefilter function bypass allows unauthorized read/update/delete if attacker knows entity ID; fixed in v0.20.6.
Vulnerability
Overview
CVE-2023-35167 affects the Remult CRUD framework for TypeScript. The vulnerability lies in the apiPrefilter option of the @Entity decorator. When apiPrefilter is set to a function that returns a filter intended to restrict access, the filter is correctly applied to list queries but is not enforced for individual entity operations (get, update, delete) when the attacker knows the entity's ID [1][3]. This oversight allows the function-based prefilter to be bypassed.
Exploitation
An attacker who knows the id of an entity instance that they are not authorized to access can directly call the API endpoints for that specific entity. No additional authentication bypass is required; the vulnerability exploits the missing application of the prefilter on single-resource operations [1]. The attacker only needs to know the ID, which might be obtained through other means such as enumeration or data leaks.
Impact
Successful exploitation grants the attacker read, update, and delete access to the targeted entity. This can lead to unauthorized data exposure, modification, or deletion, depending on the entity's role in the application [1].
Mitigation
The issue is fixed in Remult version 0.20.6 [3][4]. As a workaround, users can set the apiPrefilter option to a filter object instead of a function, which ensures the filter is applied consistently across all operations [1].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
remultnpm | < 0.20.6 | 0.20.6 |
Affected products
2Patches
16 files changed · +44 −6
CHANGELOG.md+4 −0 modified@@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [0.20.6] - 2023-06-19 + +- Fixed an issue when apiPrefilter was an arrow function, it did not affect get of a specific resource + ## [0.20.5] - 2023-06-11 - fixed issue #200 transactions on mongo db
misc/dts-compare/remult-mongo.d.ts+11 −3 modified@@ -1,11 +1,19 @@ -import type { MongoClient, Db } from 'mongodb'; +import type { MongoClient, Db, ClientSession } from 'mongodb'; import { DataProvider, EntityDataProvider, EntityFilter, EntityMetadata, Remult } from '.'; import { RepositoryOverloads } from './src/remult3'; export declare class MongoDataProvider implements DataProvider { private db; private client; - constructor(db: Db, client: MongoClient); - static getDb(remult?: Remult): Db; + constructor(db: Db, client: MongoClient, options?: { + session?: ClientSession; + disableTransactions?: boolean; + }); + session?: ClientSession; + disableTransactions: boolean; + static getDb(remult?: Remult): { + db: Db; + session: ClientSession; + }; getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider; transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>; static filterToRaw<entityType>(entity: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<{
misc/dts-compare/src/shared-tests/db-tests-setup.d.ts+1 −0 modified@@ -13,6 +13,7 @@ export declare function testInMemory(key: string, what: dbTestWhatSignature, foc export declare const TestDbs: { restDataProvider: string; mongo: string; + inMemory: string; }; export declare type dbTestWhatSignature = ((db: { db: DataProvider;
projects/core/src/data-api.ts+8 −2 modified@@ -195,10 +195,16 @@ export class DataApi<T = any> { private async doOnId(response: DataApiResponse, id: any, what: (row: T) => Promise<void>) { try { - + var where: EntityFilter<any>[] = [this.repository.metadata.idMetadata.getIdFilter(id)]; + if (this.repository.metadata.options.apiPrefilter) { + if (typeof this.repository.metadata.options.apiPrefilter === "function") + where.push(await this.repository.metadata.options.apiPrefilter()); + else + where.push(this.repository.metadata.options.apiPrefilter); + } await this.repository.find({ - where: { $and: [this.repository.metadata.options.apiPrefilter, this.repository.metadata.idMetadata.getIdFilter(id)] } as EntityFilter<any> + where: { $and: where } as EntityFilter<any> }) .then(async r => { if (r.length == 0)
projects/core/src/tests/test-data-api/predefined-filter.spec.ts+15 −0 modified@@ -131,6 +131,21 @@ describe("data api", () => { await api.put(t, 1, { name: 'YAEL' }); d.test(); }); + it("put id 1 works with predefined filterand shouldnt return anything", async () => { + let [c, remult] = await createData(async (i) => { + await i(1, 'noam', 'a'); + await i(2, 'yael', 'b'); + await i(3, 'yoni', 'a'); + }, CategoriesForThisTest2); + var api = new DataApi(c, remult); + let t = new TestDataApiResponse(); + let d = new Done(); + t.notFound = () => { + d.ok(); + }; + await api.put(t, 1, { name: 'YAEL' }); + d.test(); + }); it("getArray works with predefined filter", async () => { let [c, remult] = await createData(async (i) => { await i(1, 'noam', 'a');
projects/test-angular/src/app/products-test/products.component.ts+5 −1 modified@@ -42,7 +42,11 @@ export class ProductsComponent { } -@Entity("categories", { allowApiRead: false }) +@Entity<Category>("categories", { + allowApiCrud: true, apiPrefilter: () => ({ + id: { $ne: "clj30u9o500000kr3956ph9ep" } + }) +}) export class Category { @Fields.cuid() id = ''
Vulnerability mechanics
Root cause
"The `doOnId` method in `data-api.ts` incorrectly handled `apiPrefilter` when defined as a function, leading to a failure to apply the filter during ID-based operations."
Attack vector
An attacker can bypass authorization checks by targeting an entity instance for which they know the `id`. If the application uses an `apiPrefilter` defined as a function within the `@Entity` decorator, the `doOnId` method fails to enforce this filter during read, update, or delete operations. By providing the known `id` to the API, an attacker can perform unauthorized actions on restricted data [patch_id=24408].
Affected code
The vulnerability exists in `projects/core/src/data-api.ts` within the `doOnId` method. This method is responsible for handling operations on specific entity instances by ID. The implementation failed to correctly apply the `apiPrefilter` when it was defined as a function, allowing unauthorized access [patch_id=24408].
What the fix does
The patch updates `projects/core/src/data-api.ts` to explicitly handle the `apiPrefilter` when it is a function. It now correctly constructs an `EntityFilter` array that combines the ID-based filter with the `apiPrefilter` result, ensuring that both conditions are enforced during the `repository.find` operation. This prevents the bypass by ensuring the prefilter is always evaluated before granting access to the entity [patch_id=24408].
Preconditions
- configThe application must use the `apiPrefilter` option in the `@Entity` decorator, configured as a function.
- inputThe attacker must know the `id` of the entity instance they wish to access.
Generated on May 17, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-7hh3-3x64-v2g9ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-35167ghsaADVISORY
- github.com/remult/remult/commit/6892ae97134126d8710ef7302bb2fc37730994c5ghsax_refsource_MISCWEB
- github.com/remult/remult/releases/tag/v0.20.6ghsax_refsource_MISCWEB
- github.com/remult/remult/security/advisories/GHSA-7hh3-3x64-v2g9ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.