Vulnerability: SQL injection vulnerability in ARAX-UI Synonym Lookup functionality in GitHub repository rtxteam/rtx prior to checkpoint_2022-04-20 . This vulnerability is critical as it can lead to remote code execution and thus complete server takeover.
Vulnerability ID: CVE-2022-1531
CWE: CWE-89
Severity score: 10
Project: https://github.com/rtxteam/rtx
Published: 2022-04-29
File: code/autocomplete/rtxcomplete.py
Commit message: avoid SQL injection exploits
Commit author: Eric Deutsch

Vulnerable version (before fix):
 def load():     database_name = f"{autocomplete_filepath}{os.path.sep}{RTXConfig.autocomplete_path.split('/')[-1]}"     conn = sqlite3.connect(database_name)     cursor = conn.cursor()     return True   def get_nodes_like(word,requested_limit):     if len(word) < 2:         return values      floor = word[:-1]     ceiling = floor + 'zz'  def get_nodes_like(word,requested_limit):         if found_fragment is None:              #### Cache this fragment in the database             cursor.execute("INSERT INTO cached_fragments(fragment) VALUES(?)", (word,))             fragment_id = cursor.lastrowid             if debug:                 print(f"fragment_id = {fragment_id}") 

Fixed version (after fix):
 def load():     database_name = f"{autocomplete_filepath}{os.path.sep}{RTXConfig.autocomplete_path.split('/')[-1]}"     conn = sqlite3.connect(database_name)     cursor = conn.cursor()     #print(f"INFO: Connected to {database_name}",file=sys.stderr)     return True   def get_nodes_like(word,requested_limit):     if len(word) < 2:         return values      #### Try to avoid SQL injection exploits by sanitizing input #1823     word = word.replace('"','')      floor = word[:-1]     ceiling = floor + 'zz'  def get_nodes_like(word,requested_limit):         if found_fragment is None:              #### Cache this fragment in the database             try:                 cursor.execute("INSERT INTO cached_fragments(fragment) VALUES(?)", (word,))                 fragment_id = cursor.lastrowid             except:                 print(f"ERROR: Unable to INSERT into cached_fragments(fragment)",file=sys.stderr)                 fragment_id = 0             if debug:                 print(f"fragment_id = {fragment_id}") 

Patch:
patch: @@ -23,6 +23,7 @@ def load():
     database_name = f"{autocomplete_filepath}{os.path.sep}{RTXConfig.autocomplete_path.split('/')[-1]}"
     conn = sqlite3.connect(database_name)
     cursor = conn.cursor()
+    #print(f"INFO: Connected to {database_name}",file=sys.stderr)
     return True
 
 
@@ -39,6 +40,9 @@ def get_nodes_like(word,requested_limit):
     if len(word) < 2:
         return values
 
+    #### Try to avoid SQL injection exploits by sanitizing input #1823
+    word = word.replace('"','')
+
     floor = word[:-1]
     ceiling = floor + 'zz'
 
@@ -103,8 +107,12 @@ def get_nodes_like(word,requested_limit):
         if found_fragment is None:
 
             #### Cache this fragment in the database
-            cursor.execute("INSERT INTO cached_fragments(fragment) VALUES(?)", (word,))
-            fragment_id = cursor.lastrowid
+            try:
+                cursor.execute("INSERT INTO cached_fragments(fragment) VALUES(?)", (word,))
+                fragment_id = cursor.lastrowid
+            except:
+                print(f"ERROR: Unable to INSERT into cached_fragments(fragment)",file=sys.stderr)
+                fragment_id = 0
             if debug:
                 print(f"fragment_id = {fragment_id}")
path: code/autocomplete/rtxcomplete.py