Skip to content

Commit af97896

Browse files
Potential fix for code scanning alert no. 68: Query built from user-controlled sources
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Marc <[email protected]>
1 parent c6b23d0 commit af97896

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

integration-proxy/src/main/java/io/sentrius/sso/controllers/api/DatabaseProxyController.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)