VYPR
Moderate severityNVD Advisory· Published Jun 23, 2023· Updated Nov 7, 2024

When setting EntityOptions.apiPrefilter to a function, the filter is not applied to API requests for a resource by Id

CVE-2023-35167

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.

PackageAffected versionsPatched versions
remultnpm
< 0.20.60.20.6

Affected products

2

Patches

1
6892ae971341

fixed api prefilter

https://github.com/remult/remultNoam HonigJun 19, 2023via ghsa
6 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

News mentions

0

No linked articles in our index yet.