Fix SQL injection in SQL Agent plugin via parameterized queries

Replace string concatenation with parameterized queries in all database
connectors to prevent SQL injection through LLM-generated table names.

Changes:
- PostgreSQL: Use $1, $2 placeholders with pg client parameterization
- MySQL: Use ? placeholders with mysql2 execute() prepared statements
- MSSQL: Use @p0 placeholders with request.input() parameterization
- Update handlers to support parameterized query objects
- Add formatQueryForDisplay() for logging parameterized queries

Security: Mitigates potential SQL injection when LLM passes unsanitized
user input as table_name parameter to getTableSchemaSql/getTablesSql.
GHSA-jwjx-mw2p-5wc7
This commit is contained in:
Timothy Carambat
2026-03-12 21:56:57 -07:00
parent 9e2d144dc8
commit 334ce052f0
5 changed files with 81 additions and 17 deletions

View File

@@ -6,6 +6,18 @@ module.exports.SqlAgentGetTableSchema = {
getDBClient,
} = require("./SQLConnectors/index.js");
function formatQueryForDisplay(query, params = []) {
if (!params.length) return query;
let formatted = query;
params.forEach((param, index) => {
const value = typeof param === "string" ? `'${param}'` : param;
formatted = formatted.replace(`$${index + 1}`, value);
formatted = formatted.replace(`@p${index}`, value);
formatted = formatted.replace("?", value);
});
return formatted;
}
return {
name: "sql-get-table-schema",
setup(aibitat) {
@@ -67,12 +79,17 @@ module.exports.SqlAgentGetTableSchema = {
this.super.introspect(
`${this.caller}: Querying the table schema for ${table_name} in the ${databaseConfig.database_id} database.`
);
const sqlQuery = db.getTableSchemaSql(table_name);
const isParameterized =
typeof sqlQuery === "object" && sqlQuery.query;
const queryString = isParameterized ? sqlQuery.query : sqlQuery;
const queryParams = isParameterized ? sqlQuery.params : [];
this.super.introspect(
`Running SQL: ${db.getTableSchemaSql(table_name)}`
);
const result = await db.runQuery(
db.getTableSchemaSql(table_name)
`Running SQL: ${formatQueryForDisplay(queryString, queryParams)}`
);
const result = await db.runQuery(queryString, queryParams);
if (result.error) {
this.super.handlerProps.log(