Функция с SECURITY DEFINER сделала не то, что ожидали
Функция с SECURITY DEFINER сделала не то, что ожидали Функция для отчёта доступна, но сумма получена из другой таблицы. На ревью проверьте, какой объект она нашла по имени. SECURITY DEFINER означает выполнение с правами владельца функции. В показанном SQL-теле AS $$…$$ неквалифицированное имя orders разрешается по действующему search_path при выполнении. Учебный пример для PostgreSQL 18: две схемы с таблицами orders и одна функция. Все объекты создаёт и вызывает одна роль в отдельной учебной базе, где этих схем ещё нет. CREATE SCHEMA sales; CREATE TABLE sales.orders (id bigint, amount numeric); INSERT INTO sales.orders VALUES (1, 1000); CREATE SCHEMA staging; CREATE TABLE staging.orders (id bigint, amount numeric); INSERT INTO staging.orders VALUES (1, 5); SET search_path = sales, pg_temp; CREATE FUNCTION sales.report_total() RETURNS numeric LANGUAGE sql SECURITY DEFINER -- SET у функции отсутствует AS $$ SELECT sum(amount) FROM orders; $$; -- имя без схемы SET перед CREATE FUNCTION задаёт путь сессии для проверки тела, но не закрепляет его у функции. Диагностическая развилка. Сначала владелец и настройки: SELECT r.rolname AS owner, p.prosecdef, p.proconfig FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_roles r ON r.oid = p.proowner WHERE p.oid = 'sales.report_total()'::regprocedure; prosecdef подтверждает режим. В proconfig ищите элемент search_path=…. Его отсутствие означает, что локальной настройки пути нет. Пустое значение пути — тоже настройка. Затем сравните вызовы: SET search_path = sales, pg_temp; SELECT sales.report_total(); -- ожидается 1000 SET search_path = staging, pg_temp; SELECT sales.report_total(); -- ожидается 5 При приведённых данных ожидаются 1000 и 5. Пример не исполнялся; это ожидаемые результаты. Меняется путь сессии, права и код остаются прежними. Типичная ошибка — считать SECURITY DEFINER достаточной защитой и не проверять выбранный объект. Права и видимость объектов — разные вещи. Практический вывод: используйте sales.orders; в определении функции закрепите SET search_path = pg_catalog, sales, pg_temp. Схема sales должна быть закрыта для создания объектов недоверенными ролями. pg_temp ставьте последним. Для системного изучения прав и безопасности PostgreSQL обсудите направление обучения с УЦ ФОРС. #PostgreSQL #БезопасностьБД #search_path #УЦФОРС