HenkDz/remote-postgres-mcp-server
highNo description
MCP server (purpose undetermined)
60async (input) => {
61 // Input is already validated by the SDK against configShape
62 await this.setState({
63 ...this.state, // Persist existing state
64 isConfigured: true,
65 dbConnectionString: input.connectionString,
66 });// Exploitable if an attacker gains access to Durable Object state or logs. For network_exposed MCP, a compromised LLM could exfiltrate the connection string via tool output.
The `configure_postgres_connection` tool stores the user-provided database connection string directly into the Durable Object's persistent state without any encryption or masking. The connection string typically contains credentials (username, password, host, port) in plaintext. This state is persisted across requests and may be logged or exposed through Cloudflare's internal systems.
ImpactAn attacker who gains access to the Durable Object's stored state (e.g., via Cloudflare dashboard, logs, or a compromised LLM) can retrieve the plaintext database credentials, leading to unauthorized database access, data exfiltration, or modification.
FixEncrypt the connection string before storing it in state, or use a secrets manager (e.g., Cloudflare Workers Secrets) to store credentials. Avoid persisting raw credentials in Durable Object state.
49private registerConfigurePostgresTool() {
50 if (!this.server) return;
51 const configShape = z.object({
52 connectionString: z.string().min(1, { message: "Connection string cannot be empty." }),
53 });
54
55 this.server.tool(
56 "configure_postgres_connection",
57 "Configures the PostgreSQL connection string for the current session. This must be called before other database tools.",
58 configShape.shape,
59 async (input) => {
60 // Input is already validated by the SDK against configShape
61 await this.setState({
62 ...this.state, // Persist existing state
63 isConfigured: true,
64 dbConnectionString: input.connectionString,
65 });// Exploitable by any user of the MCP (network_exposed) or by a compromised LLM. The tool is designed to accept arbitrary connection strings, which is beyond the intended purpose of analyzing a specific database.
The `configure_postgres_connection` tool accepts any non-empty string as a connection string with no validation of the format, allowed hosts, or network scope. An attacker (or compromised LLM) can provide a connection string pointing to any PostgreSQL server, including internal network hosts, cloud database services, or attacker-controlled servers. This enables arbitrary database connections beyond the intended scope.
ImpactAn attacker can connect to any PostgreSQL database reachable from the Cloudflare Worker, potentially exfiltrating data from internal databases, performing reconnaissance, or using the MCP as a proxy to attack other systems.
FixRestrict connection strings to a whitelist of allowed hosts or enforce a specific format (e.g., require SSL, validate host against a list). Consider using a pre-configured database connection instead of allowing arbitrary strings.
51const configShape = z.object({
52 connectionString: z.string().min(1, { message: "Connection string cannot be empty." }),
53});// Exploitable by any user of the MCP (network_exposed) or by a compromised LLM. The lack of validation increases the attack surface.
The only validation on the connection string is that it is a non-empty string. There is no check for valid URI format, required parameters (e.g., user, password, host, port), or security properties (e.g., SSL enforcement). This allows malformed or malicious strings to be passed to the database driver, potentially causing errors or unexpected behavior.
ImpactAn attacker could provide a malformed connection string that causes the database driver to behave unexpectedly, or a string that connects to a different database type (if the driver is lenient). This could lead to information disclosure or denial of service.
FixAdd validation to ensure the connection string is a valid PostgreSQL URI (e.g., using a regex or a URL parser). Require SSL mode and validate the host against an allowlist.