CVE-2024-27298: Insufficient Information (NVD-CWE-noinfo)
value: parse-server is a Parse Server for Node.js / Express. This vulnerability allows SQL injection when Parse Server is configured to use the PostgreSQL database. The vulnerability has been fixed in 6.5.0 and 7.0.0-alpha.20.

CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-03-01T18:15Z
Repository: https://github.com/parse-community/parse-server
Language: JavaScript
Files changed: spec/vulnerabilities.spec.js, src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
Commit date: 2024-03-01 16:52:05 +0100
Commit message: fix: Improve PostgreSQL injection detection; fixes security vulnerability [GHSA-6927-3vr9-fxf2](https://github.com/parse-community/parse-server/security/advisories/GHSA-6927-3vr9-fxf2) which affects Parse Server deployments using a Postgres database (#8961)


Diff: diff --git a/spec/vulnerabilities.spec.js b/spec/vulnerabilities.spec.js
index 9bfafcffcb..c0f519e78d 100644
--- a/spec/vulnerabilities.spec.js
+++ b/spec/vulnerabilities.spec.js
@@ -431,5 +431,30 @@ describe('Vulnerabilities', () => {
       obj.increment('a.b.c');
       await expectAsync(obj.save()).toBeResolved();
     });
   });
 });
+
+describe('Postgres regex sanitizater', () => {
+  it('sanitizes the regex correctly to prevent Injection', async () => {
+    const user = new Parse.User();
+    user.set('username', 'username');
+    user.set('password', 'password');
+    user.set('email', 'email@example.com');
+    await user.signUp();
+
+    const response = await request({
+      method: 'GET',
+      url:
+        "http://localhost:8378/1/classes/_User?where[username][$regex]=A'B'%3BSELECT+PG_SLEEP(3)%3B--",
+      headers: {
+        'Content-Type': 'application/json',
+        'X-Parse-Application-Id': 'test',
+        'X-Parse-REST-API-Key': 'rest',
+      },
+    });
+
+    expect(response.status).toBe(200);
+    expect(response.data.results).toEqual(jasmine.any(Array));
+    expect(response.data.results.length).toBe(0);
+  });
+});
diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
index 3ad59ec77f..efbe985bf9 100644
--- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
+++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
@@ -2654,11 +2654,11 @@ function literalizeRegexPart(s: string) {
   return s
     .replace(/([^\\])(\\E)/, '$1')
     .replace(/([^\\])(\\Q)/, '$1')
     .replace(/^\\E/, '')
     .replace(/^\\Q/, '')
-    .replace(/([^'])'/, `$1''`)
+    .replace(/([^'])'/g, `$1''`)
     .replace(/^'([^'])/, `''$1`);
 }
 
 var GeoPointCoder = {
   isValidJSON(value) {

Vulnerable code:     .replace(/([^'])'/, `$1''`)
Fixed code: 
describe('Postgres regex sanitizater', () => {
  it('sanitizes the regex correctly to prevent Injection', async () => {
    const user = new Parse.User();
    user.set('username', 'username');
    user.set('password', 'password');
    user.set('email', 'email@example.com');
    await user.signUp();

    const response = await request({
      method: 'GET',
      url:
        "http://localhost:8378/1/classes/_User?where[username][$regex]=A'B'%3BSELECT+PG_SLEEP(3)%3B--",
      headers: {
        'Content-Type': 'application/json',
        'X-Parse-Application-Id': 'test',
        'X-Parse-REST-API-Key': 'rest',
      },
    });

    expect(response.status).toBe(200);
    expect(response.data.results).toEqual(jasmine.any(Array));
    expect(response.data.results.length).toBe(0);
  });
});
    .replace(/([^'])'/g, `$1''`)