CVE-2023-30625 (published 2023-06-16T17:15Z)

rudder-server is part of RudderStack, an open source Customer Data Platform (CDP). Versions of rudder-server prior to 1.3.0-rc.1 are vulnerable to SQL injection. This issue may lead to Remote Code Execution (RCE) due to the `rudder` role in PostgresSQL having superuser permissions by default. Version 1.3.0-rc.1 contains patches for this issue.

CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/rudderlabs/rudder-server
commit_details: repo_url: https://github.com/rudderlabs/rudder-server
author: Aris Tzoumas
author_date: 2022-11-07 21:10:24+02:00
msg: fix: always use a sql safe table name in failed events manager (#2664)
repository: repo_url: https://github.com/rudderlabs/rudder-server
repo_name: rudderlabs/rudder-server
description: Privacy and Security focused Segment-alternative, in Golang and React  
repo_language: Go
owner: rudderlabs
file_changes: filename: failed-events-manager.go
change_type: ModificationType.MODIFY
diff: @@ -56,7 +56,7 @@ func (*FailedEventsManagerT) SaveFailedRecordIDs(taskRunIDFailedEventsMap map[st
 	}
 
 	for taskRunID, failedEvents := range taskRunIDFailedEventsMap {
-		table := `"` + strings.ReplaceAll(fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID), `"`, `""`) + `"`
+		table := getSqlSafeTablename(taskRunID)
 		sqlStatement := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s (
 		destination_id TEXT NOT NULL,
 		record_id JSONB NOT NULL,
@@ -94,7 +94,7 @@ func (fem *FailedEventsManagerT) DropFailedRecordIDs(taskRunID string) {
 	}
 
 	// Drop table
-	table := fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID)
+	table := getSqlSafeTablename(taskRunID)
 	sqlStatement := fmt.Sprintf(`DROP TABLE IF EXISTS %s`, table)
 	_, err := fem.dbHandle.Exec(sqlStatement)
 	if err != nil {
@@ -111,7 +111,7 @@ func (fem *FailedEventsManagerT) FetchFailedRecordIDs(taskRunID string) []*Faile
 
 	var rows *sql.Rows
 	var err error
-	table := `"` + strings.ReplaceAll(fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID), `"`, `""`) + `"`
+	table := getSqlSafeTablename(taskRunID)
 	sqlStatement := fmt.Sprintf(`SELECT %[1]s.destination_id, %[1]s.record_id
                                              FROM %[1]s `, table)
 	rows, err = fem.dbHandle.Query(sqlStatement)
@@ -188,3 +188,7 @@ func CleanFailedRecordsTableProcess(ctx context.Context) {
 func (fem *FailedEventsManagerT) GetDBHandle() *sql.DB {
 	return fem.dbHandle
 }
+
+func getSqlSafeTablename(taskRunID string) string {
+	return `"` + strings.ReplaceAll(fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID), `"`, `""`) + `"`
+}

programming_language: Go
repo_url: https://github.com/rudderlabs/rudder-server
commit_details: repo_url: https://github.com/rudderlabs/rudder-server
author: Aris Tzoumas
author_date: 2022-11-07 19:47:06+02:00
msg: fix: properly escape table name when querying for failed events (#2663)
repository: repo_url: https://github.com/rudderlabs/rudder-server
repo_name: rudderlabs/rudder-server
description: Privacy and Security focused Segment-alternative, in Golang and React  
repo_language: Go
owner: rudderlabs
file_changes: filename: failed-events-manager.go
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@ import (
 	"database/sql"
 	"encoding/json"
 	"fmt"
+	"strings"
 	"time"
 
 	"github.com/rudderlabs/rudder-server/utils/misc"
@@ -55,7 +56,7 @@ func (*FailedEventsManagerT) SaveFailedRecordIDs(taskRunIDFailedEventsMap map[st
 	}
 
 	for taskRunID, failedEvents := range taskRunIDFailedEventsMap {
-		table := fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID)
+		table := `"` + strings.ReplaceAll(fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID), `"`, `""`) + `"`
 		sqlStatement := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s (
 		destination_id TEXT NOT NULL,
 		record_id JSONB NOT NULL,
@@ -110,7 +111,7 @@ func (fem *FailedEventsManagerT) FetchFailedRecordIDs(taskRunID string) []*Faile
 
 	var rows *sql.Rows
 	var err error
-	table := fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID)
+	table := `"` + strings.ReplaceAll(fmt.Sprintf(`%s_%s`, failedKeysTablePrefix, taskRunID), `"`, `""`) + `"`
 	sqlStatement := fmt.Sprintf(`SELECT %[1]s.destination_id, %[1]s.record_id
                                              FROM %[1]s `, table)
 	rows, err = fem.dbHandle.Query(sqlStatement)

programming_language: Go
repo_url: https://github.com/rudderlabs/rudder-server
commit_details: repo_url: https://github.com/rudderlabs/rudder-server
author: Deepak Rai
author_date: 2022-11-04 23:26:55+05:30
msg: fix: changed query to accept user input in prepared sql statement (#2652)

* Changed query to accept user input in prepared sql statement

* Changed query to accept user input in parameterized query

* Changed query to accept user input in parameterized query

* Changed query to accept user input in parameterized query

* Changed query to accept user input in parameterized query
repository: repo_url: https://github.com/rudderlabs/rudder-server
repo_name: rudderlabs/rudder-server
description: Privacy and Security focused Segment-alternative, in Golang and React  
repo_language: Go
owner: rudderlabs
file_changes: filename: warehouse.go
change_type: ModificationType.MODIFY
diff: @@ -1794,6 +1794,7 @@ func pendingEventsHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 func getPendingStagingFileCount(sourceOrDestId string, isSourceId bool) (fileCount int64, err error) {
+	sourceOrDestId = pq.QuoteIdentifier(sourceOrDestId)
 	sourceOrDestColumn := ""
 	if isSourceId {
 		sourceOrDestColumn = "source_id"
@@ -1807,16 +1808,14 @@ func getPendingStagingFileCount(sourceOrDestId string, isSourceId bool) (fileCou
 		FROM
 		  %[1]s
 		WHERE
-		  %[1]s.%[3]s = '%[2]s';
+		  %[2]s = $1;
 `,
 		warehouseutils.WarehouseUploadsTable,
-		sourceOrDestId,
 		sourceOrDestColumn,
 	)
-
-	err = dbHandle.QueryRow(sqlStatement).Scan(&lastStagingFileIDRes)
+	err = dbHandle.QueryRow(sqlStatement, sourceOrDestId).Scan(&lastStagingFileIDRes)
 	if err != nil && err != sql.ErrNoRows {
-		err = fmt.Errorf("query: %s failed with Error : %w", sqlStatement, err)
+		err = fmt.Errorf("query: %s run failed with Error : %w", sqlStatement, err)
 		return
 	}
 	lastStagingFileID := int64(0)
@@ -1830,18 +1829,16 @@ func getPendingStagingFileCount(sourceOrDestId string, isSourceId bool) (fileCou
 		FROM
 		  %[1]s
 		WHERE
-		  %[1]s.id > %[2]v
-		  AND %[1]s.%[4]s = '%[3]s';
+		  id > %[2]v
+		  AND %[3]s = $1;
 `,
 		warehouseutils.WarehouseStagingFilesTable,
 		lastStagingFileID,
-		sourceOrDestId,
 		sourceOrDestColumn,
 	)
-
-	err = dbHandle.QueryRow(sqlStatement).Scan(&fileCount)
+	err = dbHandle.QueryRow(sqlStatement, sourceOrDestId).Scan(&fileCount)
 	if err != nil && err != sql.ErrNoRows {
-		err = fmt.Errorf("query: %s failed with Error : %w", sqlStatement, err)
+		err = fmt.Errorf("query: %s run failed with Error : %w", sqlStatement, err)
 		return
 	}
 

programming_language: Go