A newly disclosed vulnerability in Langroid, the popular open-source framework for building LLM-powered agents, shows how a security patch meant to close a dangerous file-read flaw left the door open through a simple syntax trick.
Tracked as CVE-2026-54760 and published as GHSA-6xc5-4r68-67fc, the flaw affects Langroid’s SQLChatAgent component and carries a High severity rating.
The story begins with an earlier flaw, CVE-2026-25879 (GHSA-pmch-g965-grmr), which allowed attacker-influenced SQL to invoke PostgreSQL’s pg_read_file function and read arbitrary server-side files.
Langroid Flaw
Langroid’s maintainers responded by adding a regex-based blocklist to _validate_query, the function responsible for screening SQL statements before execution.
That fix, however, relied on raw-text pattern matching rather than proper query parsing. The regex \bpg_(read|stat|ls|current_logfile)[A-Za-z0-9_]*\s*\( only catches function calls where the name is immediately followed by whitespace and an opening parenthesis.
Security researcher pchalasani, who published the advisory on June 10, demonstrated that PostgreSQL happily accepts several equivalent ways to call the same function that slip past the regex entirely:
- Quoted identifiers:
SELECT "pg_read_file"('/etc/passwd') - Inline comments splitting the token:
SELECT pg_read_file/**/('/etc/passwd') - Schema-qualified calls:
SELECT pg_catalog."pg_read_file"('/etc/passwd')
Each of these forms still parses as a valid SELECT statement, satisfying Langroid’s secondary sqlglot-based allowlist check. Because that check only enforces statement type and never inspects normalized function names within the parsed AST, the dangerous call sails through undetected.
The researcher’s reproduction used a live PostgreSQL 16 container with sqlglot 30.8.0, the same version shipped in Langroid. The control query using plain pg_read_file( was correctly rejected, but all three obfuscated variants executed successfully and returned file contents from the server.
The vulnerability sits at the intersection of two well-known weakness classes: CWE-89 (SQL Injection) and CWE-22 (Path Traversal).
The precondition is specific but realistic: any deployment where untrusted user input or prompt content can influence LLM-generated SQL, combined with a PostgreSQL role that has pg_read_server_files privileges or superuser access, becomes exploitable.
This isn’t a new attack surface it’s the same pg_read_file primitive the original advisory tried to close. The difference is that the underlying architecture, a regex chasing raw text instead of validating parsed structure, made the fix trivially bypassable.
The advisory’s suggested remediation reflects a broader lesson in secure coding: don’t fight SQL injection with string matching when you already have an AST.
Langroid’s maintainers are advised to walk the sqlglot-parsed tree, strip quoting and schema qualifiers, case-fold function names, and reject any call matching a dangerous set that includes pg_read_file, pg_read_binary_file, pg_ls_dir, pg_stat_file, lo_import, lo_export, load_file, and load_extension.
Langroid version 0.65.1 contains the patch. Organizations running SQLChatAgent against PostgreSQL should upgrade immediately and, as a defense-in-depth measure, restrict the database role used by the agent so it lacks pg_read_server_files entirely ensuring that even a future bypass can’t turn into a file-disclosure incident.