| From: | Noah Misch <noah(at)leadboat(dot)com> |
|---|---|
| To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Richard Guo <guofenglinux(at)gmail(dot)com> |
| Cc: | Thom Brown <thom(at)linux(dot)com>, Jacob Brazeal <jacob(dot)brazeal(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org, underdog(at)theori(dot)io |
| Subject: | Re: remove_useless_joins vs. bug #19560 |
| Date: | 2026-09-26 17:44:57 |
| Message-ID: | 20260926174457.13.noahmisch@microsoft.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
security@ received a report about a regression in commit 2ebf25e. On
2026-09-12, I told the reporter that we handle defects in unreleased code as
non-vulnerabilities and asked them to report it to pgsql-hackers. I didn't
find that report, so I'm forwarding it here. From some searches of this
thread, I also don't think this repeats any of the followup fixes already
done. I'm attaching the reporter's materials. I'll file a v19 open item,
since v19 is projected to reach a GA release before the 2026-11 back branch
releases.
<reporter_message_body>
I am reporting an RLS confidentiality bypass introduced by the recent
jointree-rewrite self-join elimination change.
An ordinary authenticated role can join an RLS-protected table directly to
an existing default owner-executed, ID-only view of the same table.
The direct RTE carries the attacker's RLS securityQuals, while the
view-derived RTE is checked as the table-owning view owner and carries
none.
The new SJE implementation groups the RTEs by physical relation OID without
comparing their security qualifiers or permission identities. It removes
the lower relation ID and retains the later one; because a pulled-up view
RTE is appended after the parent RTEs, the owner-context entry is
deterministically retained in either SQL FROM order. Replanning produces
one scan without the RLS predicate.
I reproduced the leak on master 798bdcae89debabc59fa8afc6d690fec584db32f
and REL_18_STABLE c0b3980507f459c09b5324b6536c9e1c31fad378.
Exact PostgreSQL 18.6 is a negative control across the expanded matrix. The
relevant REL_18_STABLE rewrite was committed after 18.6 and no inspected
release tag contains it as of 2026-09-08, so I recommend pre-release P0
handling and High confidentiality severity if shipped. PostgreSQL 18.0
through 18.6 are not claimed as affected.
The hardened reproducer grants no table-level SELECT and no SELECT on the
policy column. It grants only the output columns plus SELECT on the
existing views. With SJE off, the attacker receives one authorized row;
with SJE on, it receives both the authorized and foreign-tenant rows. The
same leak occurs through IN (SELECT ...) and through an
invoker-view/owner-view pair with no direct table syntax when the attacker
chooses the unsafe view order. Owner-view predicates that survive SJE bound
the leaked row set. Removing the secret-column privilege still yields
permission denied, so this is an RLS bypass rather than a column-ACL bypass.
The attached package contains the detailed analysis, expanded standalone
SQL reproducer, validation evidence, and a conservative guard that excludes
RTEs carrying securityQuals from SJE. I applied that guard to the affected
master, rebuilt it, and verified that every demonstrated entry path retains
RLS.
Please confirm receipt. I will keep the details private while the affected
branches are triaged and corrected.
Regards, Yonghwa Lee, Xint by Theori
___
Yonghwa Lee 이용화
Senior Security Engineer
Xint
underdog(at)theori(dot)io
</reporter_message_body>
| Attachment | Content-Type | Size |
|---|---|---|
| report.md | text/plain | 10.4 KB |
| SJE-RLS-001-submit-ready-2026-09-07.zip | application/x-zip-compressed | 10.9 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tom Lane | 2026-09-26 18:05:06 | Re: remove_useless_joins vs. bug #19560 |
| Previous Message | Alexander Lakhin | 2026-09-26 17:00:00 | Re: Assert failure in try_nestloop_path() |