@@ -100,6 +100,11 @@ public ResponseEntity<?> executeQuery(
100100 .body (Map .of ("error" , "Only SELECT queries are allowed" ));
101101 }
102102
103+ if (!isSafeSelectQuery (query )) {
104+ return ResponseEntity .status (HttpStatus .SC_FORBIDDEN )
105+ .body (Map .of ("error" , "Query is not allowed" ));
106+ }
107+
103108 String jdbcUrl = buildJdbcUrl (integrationDTO );
104109 List <Map <String , Object >> results = new ArrayList <>();
105110
@@ -143,6 +148,48 @@ public ResponseEntity<?> executeQuery(
143148 }
144149 }
145150
151+ /**
152+ * Performs basic validation to ensure that only reasonably safe SELECT queries are executed.
153+ * This method is intentionally conservative and will reject queries containing
154+ * multiple statements, comments, or obvious DDL/DML keywords.
155+ */
156+ private boolean isSafeSelectQuery (String query ) {
157+ if (query == null ) {
158+ return false ;
159+ }
160+
161+ String trimmed = query .trim ();
162+ if (trimmed .isEmpty ()) {
163+ return false ;
164+ }
165+
166+ // Must start with SELECT (case-insensitive)
167+ String upper = trimmed .toUpperCase (Locale .ROOT );
168+ if (!upper .startsWith ("SELECT" )) {
169+ return false ;
170+ }
171+
172+ // Disallow multiple statements and common comment syntaxes
173+ if (upper .contains (";" ) || upper .contains ("--" ) || upper .contains ("/*" ) || upper .contains ("*/" ) || upper .contains ("#" )) {
174+ return false ;
175+ }
176+
177+ // Disallow obviously dangerous keywords that should not appear in a simple read-only query
178+ String [] forbiddenKeywords = {
179+ " INSERT " , " UPDATE " , " DELETE " , " DROP " , " ALTER " , " TRUNCATE " ,
180+ " CREATE " , " MERGE " , " GRANT " , " REVOKE " , " EXEC " , " EXECUTE " ,
181+ " INTO OUTFILE " , " INTO DUMPFILE "
182+ };
183+
184+ for (String keyword : forbiddenKeywords ) {
185+ if (upper .contains (keyword )) {
186+ return false ;
187+ }
188+ }
189+
190+ return true ;
191+ }
192+
146193 @ GetMapping ("/tables" )
147194 @ Endpoint (description = "List database tables" )
148195 @ LimitAccess (applicationAccess = {ApplicationAccessEnum .CAN_LOG_IN })
0 commit comments