Skip to content

Commit

Permalink
fix: SQL injection when using Parse Server with PostgreSQL; fixes sec…
Browse files Browse the repository at this point in the history
…urity vulnerability [GHSA-c2hr-cqg6-8j6r](GHSA-c2hr-cqg6-8j6r) (#9167)
  • Loading branch information
mtrezza committed Jun 30, 2024
1 parent ae72cf0 commit 2edf1e4
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
"test:mongodb:5.3.2": "npm run test:mongodb --dbversion=5.3.2",
"test:mongodb:6.0.2": "npm run test:mongodb --dbversion=6.0.2",
"test:mongodb:7.0.1": "npm run test:mongodb --dbversion=7.0.1",
"test:postgres:testonly": "cross-env PARSE_SERVER_TEST_DB=postgres PARSE_SERVER_TEST_DATABASE_URI=postgres://postgres:password@localhost:5432/parse_server_postgres_adapter_test_database npm run testonly",
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
"test": "npm run testonly",
Expand Down
22 changes: 13 additions & 9 deletions src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2614,16 +2614,16 @@ function isAnyValueRegexStartsWith(values) {
});
}

function createLiteralRegex(remaining) {
function createLiteralRegex(remaining: string) {
return remaining
.split('')
.map(c => {
const regex = RegExp('[0-9 ]|\\p{L}', 'u'); // Support all unicode letter chars
const regex = RegExp('[0-9 ]|\\p{L}', 'u'); // Support all Unicode letter chars
if (c.match(regex) !== null) {
// don't escape alphanumeric characters
// Don't escape alphanumeric characters
return c;
}
// escape everything else (single quotes with single quotes, everything else with a backslash)
// Escape everything else (single quotes with single quotes, everything else with a backslash)
return c === `'` ? `''` : `\\${c}`;
})
.join('');
Expand All @@ -2633,14 +2633,14 @@ function literalizeRegexPart(s: string) {
const matcher1 = /\\Q((?!\\E).*)\\E$/;
const result1: any = s.match(matcher1);
if (result1 && result1.length > 1 && result1.index > -1) {
// process regex that has a beginning and an end specified for the literal text
// Process Regex that has a beginning and an end specified for the literal text
const prefix = s.substring(0, result1.index);
const remaining = result1[1];

return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
}

// process regex that has a beginning specified for the literal text
// Process Regex that has a beginning specified for the literal text
const matcher2 = /\\Q((?!\\E).*)$/;
const result2: any = s.match(matcher2);
if (result2 && result2.length > 1 && result2.index > -1) {
Expand All @@ -2650,14 +2650,18 @@ function literalizeRegexPart(s: string) {
return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
}

// remove all instances of \Q and \E from the remaining text & escape single quotes
// Remove problematic chars from remaining text
return s
// Remove all instances of \Q and \E
.replace(/([^\\])(\\E)/, '$1')
.replace(/([^\\])(\\Q)/, '$1')
.replace(/^\\E/, '')
.replace(/^\\Q/, '')
.replace(/([^'])'/g, `$1''`)
.replace(/^'([^'])/, `''$1`);
// Ensure even number of single quote sequences by adding an extra single quote if needed;
// this ensures that every single quote is escaped
.replace(/'+/g, match => {
return match.length % 2 === 0 ? match : match + "'";
});
}

var GeoPointCoder = {
Expand Down

0 comments on commit 2edf1e4

Please sign in to comment.