
Reading other AWS accounts' SQL on Amazon Athena
Act's research team uncovered a cross-tenant security flaw in Amazon Athena that exposed recent SQL queries, Account IDs, and sensitive data from unrelated AWS accounts. By passing Catalog=system via an API parameter, queries bypassed standard validation to read shared logs directly from Trino's runtime table. We reported the issue to AWS, and they resolved it globally in four days with no action required on your end.
One extra field on an Athena API call returned the full SQL query text that other AWS accounts had just run, and the account IDs that ran it. It did not return the query results, but it did return the values in WHERE clauses and INSERT statements.
Those accounts had no relationship with ours, no shared resource and no grant of any kind.
We reported it to AWS on 6 August 2026. They fixed it in four days, and customers do not need to do anything.
Background
Athena is AWS's serverless SQL service. You point it at data sitting in S3 and query it without running a database of your own.
Athena engine v3 is Trino, and queries do not necessarily run on dedicated, single-tenant infrastructure.
Trino ships a catalog named system, and in it system.runtime.queries, a table of what ran recently on that infrastructure: query ID, submitting user, state, timing, full SQL text. On a cluster you own, that table is how you find the query eating your workers. On Athena it is a cross-tenant read.
Two ways to pass the catalog name
A catalog name can arrive in two places. Put system in the SQL and the request is refused. StartQueryExecution answers Queries of this type are not supported and hands back no execution ID.
The second place is a separate parameter. StartQueryExecution takes the SQL text, and beside it a QueryExecutionContext that holds Database and Catalog. That field is how unqualified table names get resolved.
Leave the catalog out of the SQL and pass Catalog=system there instead. The query runs.

What came back
Other AWS accounts' complete SQL statement text, and the account IDs that submitted it.
To find out what those statements contained without reading anyone's SQL, we counted pattern matches inside the engine and returned only the integers. Across 200 query landings we saw 2,794 rows and 2,590 of them belonged to other accounts.

This is the normal case and not a rare race. 102 of 109 landings returned at least one other account's row, and one landing held 43 distinct identities. system.runtime.queries also keeps about an hour of history rather than a moment of it. In the round where we measured age, 41 percent of the other accounts' rows were 15 minutes old or older and the oldest was about 54 minutes.
Disclosure timeline
6 August. We reported the finding to AWS. They answered the same day and opened a review.
8 August. The call stopped working.
10 August. AWS completed the fix in every Region. We retested in every enabled Region and the block held in all of them.
AWS was fast and professional: they replied within hours, kept us updated, and shipped the fix to every Region in four days. There is no CVE, because AWS assigns one where a customer has to act, and here nobody outside AWS had anything to install or change.
The access paths you do control
This one belonged to AWS and AWS closed it. No setting on your side would have changed the outcome.
The access inside your own account is a different matter, and that is where most of the reachable risk sits, usually as permission somebody granted for a good reason years ago and nobody has taken back.
Act Security models what is actually reachable inside your cloud, then ships the least privilege fix as pull requests to the Terraform or CloudFormation you already run.