Three weeks. Three separate CVEs. Retrieval, model serving, database access — the full AI infrastructure stack has now bled from the same wound, and no one wants to name the underlying diagnosis. The latest disclosure arrived with a CVSS score of 9.2 and a one-line summary that should have triggered sirens across every Fortune 500 data team that has adopted Model Context Protocol servers in production. CVE-2026-85620 is not a cryptographic failure. It is not an injection attack requiring sophisticated payload engineering. It is an AST parser that simply forgot to check one type of node — and that omission converts a security boundary designed for production into what security researchers now call a false boundary.
The vulnerability lives inside Postgres MCP Pro, the open-source MCP server from the crystaldba/postgres-mcp repository that has become a default choice for AI agents needing structured database access. In its restricted mode, the server promises a hard security envelope: read-only transactions enforced at the database layer plus an allowlist verification layer that inspects every SQL statement before execution. That envelope, it turns out, was never a sealed container. It was a perimeter built from paper, and the breach vector requires nothing more than understanding how PostgreSQL genuinely parses a query.
The grammar of the bypass
Let me be precise about what failed, because precision matters when we are discussing who gets to access your TLS keys. The allowlist mechanism in Postgres MCP Pro relies on a module called safe_sql.py, which parses incoming SQL and checks each function call against an approved list. The implementation walks the abstract syntax tree and inspects FuncCall nodes. If a function like pg_read_file appears inside a SELECT list, the parser flags it and blocks execution. That logic functioned as designed. The flaw is not in what the parser checked; it is in the nodes it never bothered to examine.
In PostgreSQL's grammar, functions can appear in multiple positions within a query. They can sit in the target list after SELECT, inside a WHERE clause as a predicate, and critically, inside the FROM clause as what the parser designates a RangeFunction node. Consider the statement: SELECT * FROM pg_read_file('/etc/passwd'). From the perspective of PostgreSQL's execution engine, this is a legitimate query that calls the superuser-level file-reading function and returns its contents as a table. From the perspective of safe_sql.py, there is no FuncCall node to inspect — the function invocation is nested inside RangeFunction, a node type the allowlist logic simply never visits.
The result is a classic parser coverage gap, and it transforms restricted mode into a configuration that operators were told to trust in production but which an unauthenticated attacker can defeat with a single syntactic trick. The attack requires no authentication against the restricted logic itself. Any MCP client or AI agent instance that can reach a Postgres MCP Pro server running in restricted mode — version 0.3.0 or earlier — can issue the crafted query and read arbitrary files from the underlying host. System configuration. Credential stores. TLS private keys.
I have spent the last six years watching security failures compound across crypto and AI infrastructure, and there is a pattern here that deserves naming: the code does not lie, but it does not care. The parser behaved exactly as it was written. It examined FuncCall nodes and performed its allowlist verification flawlessly across that domain. Nothing in the codebase claimed to cover RangeFunction nodes. The lie, if there is one, was in the marketing of restricted mode as a production-grade security boundary — and in the mental model of every operator who assumed that read-only transactions plus SQL allowlisting constituted defense in depth.
The scale problem hiding beneath the syntax
This disclosure deserves attention not merely because it is severe, but because it arrives at a moment when the Model Context Protocol ecosystem has achieved what can only be described as hyperscale adoption without mature security modeling. The numbers deserve scrutiny: 97 million monthly SDK downloads, more than 10,000 active MCP servers, and 28 percent of Fortune 500 companies running MCP components in production. A Department of Defense document circulating in infrastructure circles has already flagged the core tension — MCP's adoption velocity is outpacing the maturity of its security architecture. Data whispers what the gatekeepers refuse to shout: we are deploying trust boundaries into production environments without verifying that those boundaries cover every path an execution engine can traverse.
The restricted mode design philosophy itself deserves examination. The architecture envisioned two independent layers of defense. First, PostgreSQL-level permissions configured to enforce read-only access. Second, application-level AST verification to prevent dangerous function calls. The theory was that even if one layer failed, the other would catch unauthorized access. But this vulnerability demonstrates that the two layers share an implicit assumption — that the SQL parser sees all function invocations uniformly. When a function hides inside a RangeFunction node, both layers are blindsided simultaneously because both operate on the same incomplete parse tree.
This is what I call the parser incompleteness risk, and it is not unique to Postgres MCP Pro. Every system that analyzes SQL at the AST level must confront the gap between the grammar specification and the parser implementation. In my years of auditing smart contracts and database middleware, I have learned that the most dangerous vulnerabilities are rarely sophisticated exploits against complex cryptography. They are nearly always structural gaps between what a security control claims to cover and what the underlying language grammar can actually express.
Reading files through a read-only transaction
The mechanics of the exploit deserve full articulation because they reveal how the security layers failed in parallel. PostgreSQL implements read-only transactions by rejecting any statement that attempts to write data. That protection remains intact — the attacker cannot modify tables or execute destructive operations. But read-only is a statement about data mutation, not about data exfiltration. The pg_read_file function reads files from the server's filesystem, a capability orthogonal to write access. A transaction can be entirely read-only while still exposing /etc/passwd, application configuration files, or certificate private keys to anyone who crafts the correct query shape.
The allowlist layer was supposed to catch exactly this class of dangerous function. IONIX Threat Center and VulnCheck have both classified CVE-2026-85620 as CWE-863, Incorrect Authorization — a categorization that correctly places the failure at the authorization boundary rather than at the cryptographic or injection layer. The authorization model assumed that the AST representation of an incoming query would faithfully enumerate every function invocation that PostgreSQL would execute. That assumption was empirically demonstrated false.
Let me parse the affected surface area with appropriate granularity. Any Postgres MCP Pro deployment running version 0.3.0 or earlier is vulnerable when restricted mode is enabled. If the MCP server process runs with PostgreSQL privileges that include pg_read_server_files — a common configuration when operators prioritize convenience over least privilege — the exploit returns the entire filesystem to the attacker. The official remediation guidance is direct: stop using restricted mode as a security boundary, run the MCP server under a role that lacks file-access permissions, and monitor for queries containing pg_read_file or similar functions inside FROM clauses.
There is an uncomfortable operational lesson embedded in that remediation. The mitigation is not a fix to the parser. It is an acknowledgment that the parser should never have been the security boundary in the first place. Database-level permissions are the only layer that PostgreSQL itself fully controls and enforces.
A pattern across the agent stack
The broader context is genuinely alarming for anyone tracking AI infrastructure security. CVE-2026-85620 is the third critical vulnerability disclosed within a month across the MCP ecosystem, following CVE-2026-82526 and CVE-2026-85695. Together they span the three layers that AI agents depend on: retrieval infrastructure, model serving, and database access. The clustering of these disclosures suggests not isolated developer error but a systematic immaturity in security engineering across the MCP ecosystem.
Industry surveys reinforce this reading. Half of MCP server builders now identify security control complexity as their primary implementation challenge. That figure is a confession disguised as a statistic — it tells us that the ecosystem's builders recognize the problem but have not yet developed shared patterns for solving it. When 50 percent of your developer community flags the same bottleneck, you have a systemic gap, not an individual project failure.
My own experience auditing code under pressure has taught me that these moments reveal character. Winter reveals who is building and who is waiting. The developers at the crystaldba repository have a fix PR under review, and the responsible disclosure process appears to have followed appropriate protocol. But the underlying question is whether the community treats this as a one-off bug or as evidence that the entire approach to AI-agent database security needs rethinking.
The contrarian reading: the real story is the trust model itself
Here is where I diverge from the conventional security reporting narrative. The predictable takeaway from this disclosure is that Postgres MCP Pro shipped a flawed parser and needs to patch it. That framing is technically accurate but strategically incomplete. The deeper problem is not the missing RangeFunction check. It is the architectural assumption that an application-level AST validator constitutes a meaningful security boundary against queries generated by untrusted AI agents.
Think about what restricted mode was designed to accomplish. It was meant to create an environment where operators could grant AI agents database access without needing to fully trust the agent's outputs. The mode was the compromise between allowing agents to be useful and preventing them from being dangerous. And it functioned — until functioned — until it demonstrated that any parser-based control inherits every blind spot of the grammar it parses.
Behind every algorithm lies a moral blind spot, and the moral blind spot here belongs less to the parser than to the deployment culture that treated a developer convenience feature as a security perimeter. I have watched this movie before. In the crypto winter of 2022, when the Terra/Luna collapse erased $10 billion in value, the prevailing narrative blamed smart contract bugs and economic design. My analysis, written from a cabin in rural Virginia after three weeks of forced disconnection, argued something different — that the crash was a failure of trust accounting, not technical execution. The same framing applies here.
Ethics are the unlisted asset in every ledger. The asset that Postgres MCP Pro listed was a restricted mode that promised bounded SQL execution. The liability that was not recorded was the parser's incomplete coverage of PostgreSQL's grammar. When the liability came due, the real asset — operator trust in the system — was impaired far more deeply than the codebase itself.
History repeats not in prices, but in prejudices. The prejudice at work across the AI infrastructure ecosystem is the belief that the tools that got us here will get us to production safely if we add enough validation layers. This vulnerability falsifies that belief in a technically demonstrable way. No number of additional AST checks can create an impenetrable boundary, because the space of SQL grammar constructs is too large and too nuanced for any hand-written parser to fully enumerate. The fix is not to build a better parser. The fix is to relocate trust to the one layer that PostgreSQL itself controls: the permission model enforced by the database engine.
For operators running Postgres MCP Pro today, the immediate recommendations are unambiguous. Remove restricted mode from production environments immediately. Run the MCP server under a PostgreSQL role that explicitly lacks pg_read_server_files, pg_write_server_files, and superuser privileges. Implement network-level restrictions on which clients can reach the MCP server at all. Watch the postgres-mcp repository for the patch release and schedule deployment the day it lands. These are table stakes.
But the strategic recommendation is deeper than the tactical list. We need a fundamental reorientation in how we secure agent-database interactions. The security community should treat application-level SQL analysis as an auxiliary control that catches mistakes rather than as a primary boundary that stops adversaries. The real boundary must be layered: database-level privileges are the foundation, network isolation is the second wall, and AST validation is a helpful monitoring layer that flags suspicious queries rather than pretending to disarm them.
Positioning for the next cycle
The MCP ecosystem will not slow down because of this vulnerability. The adoption numbers are too strong, and the productivity gains are too real. What will change is the security maturity curve. I expect to see within two to three quarters a new generation of database integration layers that embed permission checks directly at the driver level — not parser validations but actual account isolation where the AI agent connects with per-query, per-session scoped credentials and cannot reach data its role has not been granted. This is the architecture that survives contact with adversarial AI agents.
The organizations that treat this moment as a strategic opportunity rather than a compliance burden will build durable advantage. The ones that patch their parser dependency and declare victory will repeat this exercise within eighteen months, because the next vulnerability will come from a different grammatical blind spot, and the one after that from a different layer of the stack. The code does not lie, but it does not care — and it will keep exposing the gap between claimed security and actual coverage until the trust model itself is redesigned.
The question that should animate every security architect reading this is not when the next CVE lands. It is whether we are willing to stop treating middleware validation as a wall and start treating it as what it has always been: a gate that filters the careless but never stops the determined. The gate has its place. But the wall must be built in the database's own permission engine, where PostgreSQL has always known how to say no.