


























The Model Context Protocol (MCP) Server provided by Xata, available at xataio/agent, is designed to facilitate agentic workflows with various database servers, including PostgreSQL. However, I identified a critical security flaw in the server’s implementation, which fails to enforce a true “read-only” mode.
This vulnerability exposes the server to SQL injection attacks, potentially leading to denial of service and unauthorized data manipulation. This article explores the vulnerability, its exploitation, and recommended mitigations.
Disclaimer: The flawed code was responsibly disclosed to the Xata team through the GitHub Security Advisory reporting mechanism upon which the maintainers decided to remove the flawed MCP server code entirely from the repository.
The vulnerability arises from the assumption that the client.query() method in the PostgreSQL interface only executes a single query. In reality, the pg package allows multiple queries to be executed if separated by semicolons. This oversight can be exploited to bypass the intended “read-only” mode, allowing attackers to execute unauthorized write operations or cause service disruptions.
The vulnerable code is located in the mcp-postgres.ts file of the Xata repository:
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'query') {
const sql = request.params.arguments?.sql as string;
const client = await pool.connect();
try {
await client.query('BEGIN TRANSACTION READ ONLY');
const result = await client.query(sql);
return {
content: [{ type: 'text', text: JSON.stringify(result.rows, null, 2) }],
isError: false
};
} finally {
client.release();
}
}
});
The vulnerability stems from the naive implementation of a “read-only” transaction, which is easily bypassed by injecting additional SQL commands. For instance, an attacker can terminate the read-only transaction and execute a write operation:
COMMIT; INSERT INTO users (name, email) VALUES ('Eve', 'eve@gibson.com');
This injection effectively bypasses the read-only constraint, allowing unauthorized data manipulation.
Consider the following scenarios demonstrating the vulnerability:
Bypassing Read-Only Mode:
SELECT id, name, email FROM users WHERE id > 5 ORDER BY id;
COMMIT; INSERT INTO users (name, email) VALUES ('Eve', 'eve@gibson.com');
Denial of Service:
COMMIT; SET statement_timeout TO 1;
Even without stored procedures, attackers can exploit the MCP interface to perform administrative operations, such as terminating backend processes:
SELECT pid, usename, state, query FROM pg_stat_activity;
SELECT pg_terminate_backend(PID);
To mitigate this vulnerability, consider the following recommendations:
SELECT. Implement strict validation to prevent multiple queries.The vulnerability is primarily due to the assumption that client.query() executes only a single query, allowing attackers to inject additional commands.
Attackers can inject SQL commands to bypass the read-only mode, perform unauthorized write operations, or cause denial of service.
Implement strict query validation, enforce single query transactions, and apply fine-grained access controls on the database server.
The identified vulnerability in Xata’s MCP Server highlights the importance of robust security practices in database interactions. By understanding the root cause and implementing the recommended mitigations, developers can protect their systems from SQL injection attacks and ensure the integrity and availability of their services.
For further insights and updates, follow Liran Tal on X and explore more on GitHub.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。