Top/Articles/PyAthena SQL injection can expose other tables (CVE-2026-65321)
pyathena-cve-cover-en

PyAthena SQL injection can expose other tables (CVE-2026-65321)

PyAthena, the standard Python client for Amazon Athena, mishandles quotes in DELETE and CTAS statements, letting untrusted input inject SQL. Update to 3.35.4.

NewsPublished Aug. 3, 2026 Updated today
Table of contents
Key takeaways

PyAthena, the standard Python client for Amazon Athena, mishandles quotes in DELETE and CTAS statements, letting untrusted input inject SQL. Update to 3.35.4.

A vulnerability has been found in PyAthena, the component used to connect to AWS's Amazon Athena from Python, that lets an outsider slip SQL commands in through values the application passes along. It is CVE-2026-65321, scored 9.8 out of 10 — the most severe band. The fixed release, 3.35.4, came out on July 31.

PyAthena is downloaded 23.52 million times a month. But not everyone is at risk. Only apps that passed untrusted values, such as user input, straight into a statement that deletes data (DELETE) or builds a table from query results (CTAS) are affected. The full set of conditions comes later in this article.

The awkward part is somewhere else. As of August 3, 2026, this vulnerability is listed neither in GitHub's advisory database nor in OSV. That means automated scanners like Dependabot are saying nothing at all. On top of that, several downstream tools cannot install the fix even if they want to.

What PyAthena is, and why you may have it without knowing

Amazon Athena is a service that lets you run SQL directly against files stored in AWS. Because you can aggregate huge volumes of logs or sales data without running a server, it is a common foundation for data analytics work.

PyAthena is the client that connects Python to Athena. It is not an official AWS release — it is an open-source project started by one person, published under the MIT license. The developer is a Japanese engineer who goes by laughingman7743, and in February 2026 the repository moved from a personal account to an organization called pyathena-dev, with documentation now hosted on its own domain.

What matters here is that you may have PyAthena installed without ever choosing it yourself. GitHub alone counts 2,240 repositories and 168 packages depending on it. Checking the dependency chains, the following tools pull PyAthena in.

ToolPurposeHow it pulls it in
dbt-athenaData transformationRequired dependency
Apache Airflow
(Amazon provider)
Workflow automationRequired dependency
Apache SupersetDashboards and BIOnly when using Athena
DataHub
/ OpenMetadata
Data catalogsOnly when using Athena
Great Expectations
/ Ibis
Data quality and analysisOnly when using Athena
awswrangler
(official AWS)
Data handlingDoes not depend on it

Note: awswrangler, the official AWS Python library, calls the AWS APIs itself instead of going through PyAthena, so it is unaffected. The BI tool Metabase is not written in Python and is likewise unrelated.

Who would exploit this, and what they get

The services in trouble here are those with a search box, contact form, or any other field where outsiders can type text, whose value is then used to query Athena. An attacker does not even need an account on the service — typing a crafted string into a public input field is enough.

What the attacker does is put an apostrophe into the input field to cut the text value short, then append their own SQL commands after it. Developers pass values along trusting that PyAthena handles them safely, but for reasons explained below, that handling failed for two kinds of statement.

What actually happens next depends on the AWS permissions the app uses when it connects to Athena. The vendor advisory lists reading data out of other tables that should have been off-limits, running destructive statements against data, and making the system create a table with attacker-chosen contents in an attacker-chosen location. For a service's users, that means other people's unrelated records could be dumped out along with their own. For a company, it means the entire dataset sitting in the analytics platform could be pulled out through a single input box.

The cause: Athena speaks two SQL dialects

In SQL, text values are wrapped in single quotes. If a user's input contains a quote of its own, the wrapping ends right there and the rest of the input gets read as a command. This is the classic attack known as SQL injection.

The defense is to rewrite quotes in the input into a harmless form. The catch is that there is more than one way to do that. Trino, the engine Athena uses internally, doubles the quote (''). Hive, the engine used for table-definition work, puts a backslash in front of it instead (\').

The problem is that Athena itself never treats a backslash as an escape character. Rewrite a quote the Hive way into \' and Athena sees one plain backslash followed by a raw quote. The wrapping ends at that point.

The advisory gives a concrete example. The input a' OR 1=1 -- becomes 'a\' OR 1=1 --' under the Hive style, but Athena reads that as the value "a\" followed by the command OR 1=1 --. An always-true condition gets injected and everything after it is ignored as a comment — the textbook shape of this attack.

Why only DELETE and CTAS were left behind

So why were only some statements vulnerable? Before the fix, PyAthena decided which style to use by looking at the first word of the statement. Only statements starting with one of five keywords — SELECT, WITH, INSERT, UPDATE, MERGE — were routed to the safe Trino style. Everything else fell through to the Hive style.

DELETE was not on that list of five. And CTAS (CREATE TABLE ... AS SELECT, the form that builds a new table out of query results) starts with CREATE, so it did not match either. Both are executed by Trino, yet both were being escaped for Hive. That mismatch is the whole bug.

In other words, the design listed only what to allow and dropped everything else into the unsafe default. The moment a statement type is missing from the list, a hole opens. This check has looked the same since at least the 2.x line, and the advisory accordingly covers "all versions 3.35.3 and earlier."

The fix flips the default to the safe side

The fix reverses the test. The Trino style is now the default, and only statements positively identified as Hive operations get the Hive style. A comment in the code explains why that choice was deliberate: applying the Trino style to a Hive statement produces, at worst, a display oddity, whereas the reverse lets a value terminate the string and inject SQL.

There is a second layer as well. Because a statement such as /* auto-generated */ DELETE FROM ... could fool the statement-type check by putting a comment in front, leading comments are now stripped before the check runs. CREATE TABLE ... AS ... is also explicitly excluded from the Hive branch. The tests use the same a' OR 1=1 -- string from earlier and confirm it is correctly converted using ''.

One more detail: the fix commit carries a Co-Authored-By: Claude line. The patch was written with AI assistance. In the FreeRDP case we covered the day before, an AI was credited by the vendor for finding the vulnerability. Finding and fixing, both, in the same week.

Are you affected? Only if all four conditions hold

The NVD summary says an unauthenticated attacker can inject arbitrary SQL, but that overstates it. PyAthena is a client component, not a server, and an attacker cannot connect to PyAthena directly. The vendor advisory itself limits the claim, saying the real impact depends on the permissions and schema available to the query being run.

You are genuinely exposed only when all four of the following apply.

ConditionIf it does not apply
Running PyAthena 3.35.3 or earlierNot affected
Passing untrusted input
as a parameter
Not affected
The statement is DELETE or
CREATE TABLE ... AS SELECT
Not affected
Still on the default parameter
style (pyformat)
Not affected

Apps that only run SELECT or INSERT were already routed to the safe style and are unaffected. Analytics platforms are mostly read traffic, so most users drop out of scope right here. If, on the other hand, your app deletes data in response to user actions, or builds summary tables from user-specified conditions, it is worth a look.

There is a stronger workaround the advisory does not mention

The workaround in the vendor advisory is to avoid passing untrusted values into DELETE and CTAS until you can update. But the official documentation points to a more fundamental escape route that the advisory never mentions.

PyAthena lets you choose how parameters are passed. The default is "pyformat," which means PyAthena embeds the values into the SQL text itself before sending it. The faulty escaping is used during that embedding step.

Switch to "qmark" and values are no longer embedded in the SQL text — they are handed to Athena's own parameter mechanism (prepared statements). Because values and commands travel separately from the start, the quality of the escaping stops mattering. This bug does not apply. The setting is one line.

pyathena.paramstyle = "qmark"

You do have to change how existing code is written, so it is not always something you can flip on the spot. Still, given that the whole approach of embedding values into a string has caused this kind of accident again and again, it is worth considering independently of the update. On the theme of command injection in data-pipeline components, the case of the data platform Prefect and the case of the ML data platform Feast belong to the same family.

Some downstream tools cannot take the fix

This is the most awkward part in practice. "Just upgrade to 3.35.4" does not work in some real environments.

Some of the tools that bundle PyAthena declare an upper version bound in their dependencies. Anything above that bound will not be installed. We checked the constraints declared in each tool's published package and mechanically worked out whether 3.35.4 can be installed.

ToolPyAthena constraintCan 3.35.4 install?
Airflow
(Amazon provider)
3.10.0 or laterYes
Ibis3.11.0 or laterYes
dbt-athena
1.11.0
Below 3.35No
Superset
6.1.0
Below 3No
DataHubBelow 3.0.0No
OpenMetadata3.25.x onlyNo

And since the vulnerability covers "3.35.3 and earlier," the entire 2.x line is included too. For Superset and DataHub, which cap at "below 3," there is no safe version at all inside their allowed range. Until each tool ships a release that relaxes the bound, those combinations cannot be fixed.

In the meantime, your options are the parameter-style change described above, or auditing and fixing the places where external input reaches a DELETE or CTAS. A capped constraint in one package blocking a fix from reaching everything downstream is not unusual: in the Better Auth case covered the day before, an intermediate package pinned a version and kept the fix from reaching downstream users for six months. To see what is pinned inside the packages you use, our guide to auditing dependencies in bulk may help.

Dependabot is not warning anyone yet

The vendor advisory went out on July 31, and the CVE was added to NVD in the early hours of August 3 Japan time. Even so, it has not reached the automated scanners.

We checked GitHub's global advisory database, OSV (the shared platform for vulnerability data), and the PyPA advisory-database (Python's official vulnerability database): the issue is in none of them. GitHub's Dependabot draws on that global database to raise alerts, so even with Dependabot enabled, you will get no notification right now. The vulnerability scanning service Snyk likewise still shows that no direct vulnerabilities have been found in PyAthena.

When a maintainer publishes an advisory on their own repository, there is a lag before it lands in the global databases. That this is the state of things for a package downloaded 23.52 million times a month means anyone relying on automated detection alone will be in the dark for a while. The issue is not on the US government CISA list of vulnerabilities under active attack either (though the latest edition of that list is dated July 29 and holds 1,656 entries, so it was compiled before this CVE number existed). We have found no reports of exploitation or published proof-of-concept code, and the EPSS score that estimates exploitation likelihood has not been calculated yet.

How this differs from the 11 CVEs a day earlier

The day before, this site covered 11 CVE IDs registered all at once on that same August 2. Those were IDs attached after the fact to advisories that had already been published and fixed. The PyAthena ID was issued by the same body, VulnCheck, and registered on the same August 2. But its character is the exact opposite.

The giveaway is the date the ID was reserved. A CVE ID can be set aside in advance of disclosure. Line up that reservation date against the date the advisory actually appeared, and you can see which came first.

CaseID reservedAdvisory publishedOrder
Better Auth
(3 cases)
July 18, 2026November-December 2025Reserved 7 months
after disclosure
FreeRDP
Vikunja and others
July 29-31, 2026July 17-20, 2026Reserved
after disclosure
PyAthenaJuly 21, 2026July 31, 2026Reserved 10 days
before disclosure

PyAthena alone runs the other way. Reserve the ID first, build the fix, ship the fixed release and the advisory together, and write the pre-reserved ID into both. That is what coordinated disclosure is supposed to look like. Sure enough, the CVE ID appears from the outset in the fix commit, the release notes, and the advisory text. Rahul Karne is credited as the reporter, and VulnCheck is named as the coordinator.

Three minutes passed between the fixed release and the advisory, and two days and two and a half hours between the release and the NVD entry. Against the months-long delay behind the 11 CVEs from the day before, that is a completely different speed. The same organization registered both sets of IDs on the same day, and yet they mean entirely different things. When you see a CVE ID, check when it was reserved first — that is the surest way to tell the two apart.

Note: the CVE record gives August 2, 2026 as the publication date, but the vendor advisory actually went live on July 31. There is a two-day discrepancy.

Made in Japan, with no Japanese-language warning

One last point. PyAthena was built by a Japanese engineer and is widely used for AWS data analytics in Japan. Even so, we found no Japanese-language coverage of this issue at all.

Searching JVN iPedia, the vulnerability database run by Japan's Information-technology Promotion Agency and partners, returns zero results for both "PyAthena" and "Athena." JPCERT/CC has issued no alert. Qiita has 14 articles about PyAthena, but the most recent was posted in April and none touch on this issue. We have found no coverage in Japanese media either.

How-to articles are available in Japanese, but the warning is only reachable if you go read the English advisory page yourself. We saw exactly the same pattern in the Better Auth case the day before. The gap tends to be widest for precisely those components people learned to use through Japanese-language material.

The bottom line

Update PyAthena to 3.35.4. It has been available since July 31. The affected group, though, is limited to apps that passed external input as a parameter into a DELETE or CTAS statement. Read-only usage is out of scope.

If updating is not an option, switching the parameter style to "qmark" routes values through Athena's own parameter mechanism and sidesteps the bug entirely. That approach is not mentioned in the vendor advisory. dbt-athena, Superset, DataHub and others cap the version, so they cannot install 3.35.4 as they stand. Until each tool responds, this workaround or a review of the affected code is what you have to work with.

And automated detection such as Dependabot is not running yet. There will always be a window like this one, where the maintainer has published a warning but the automated systems have not caught up. For the components you cannot afford to have go wrong, it pays to keep one direct route to the repository's advisory page.

Sources

avatar-m-1

Makoto Horikawa

Backend Engineer / AWS / Django