PostgreSQL中RLS策略运行时是否受search_path参数影响?
PostgreSQL RLS策略标识符绑定规则说明
你此前给出的添加schema限定避免RLS策略search_path注入的建议是不准确的,RLS策略不存在这类运行时注入风险,具体解析规则如下:
核心结论
RLS策略中的标识符(包括函数、表字段等)采用早绑定规则,所有引用会在策略定义阶段完成解析绑定,运行求值阶段不受当前会话的search_path影响,用户无法通过篡改search_path注入自定义函数绕过RLS限制。
你之前的混淆来自于SECURITY DEFINER函数的安全逻辑:SECURITY DEFINER函数运行时会使用调用者的search_path解析未限定标识符,才会存在注入风险,该逻辑不适用于RLS策略。
验证方法
你可以通过以下步骤自行验证:
- 创建测试环境与不带schema限定的RLS策略
-- 创建测试表并开启RLS CREATE TABLE test_rls ( id INT, user_id INT ); ALTER TABLE test_rls ENABLE ROW LEVEL SECURITY; -- 在public schema下创建测试用session_user_id函数 CREATE FUNCTION public.session_user_id() RETURNS INT AS $$ SELECT 1; $$ LANGUAGE sql STABLE; -- 创建不带schema限定的RLS策略 CREATE POLICY test_policy ON test_rls FOR ALL TO PUBLIC USING ( user_id = session_user_id() );
- 模拟普通用户构造同名函数并修改search_path
-- 假设普通用户拥有专属schema test_user CREATE FUNCTION test_user.session_user_id() RETURNS INT AS $$ SELECT 2; $$ LANGUAGE sql STABLE; -- 调整当前会话search_path优先匹配用户专属schema SET search_path TO test_user, public;
- 验证策略执行逻辑
-- 插入测试数据 INSERT INTO test_rls VALUES (1,1), (2,2); -- 执行查询,仅能返回user_id=1的行,说明策略调用的仍是定义时绑定的public.session_user_id(),不受当前search_path影响 SELECT * FROM test_rls;
你也可以直接查询系统表pg_policy的polqual字段,查看存储的策略条件会发现未限定的session_user_id()已经被解析为全限定的public.session_user_id()存储。
唯一注意事项
仅在策略创建阶段存在风险:如果创建策略时的search_path不可信,刚好存在恶意同名函数,策略会绑定错误的函数,但这是创建阶段的操作风险,和运行时用户篡改search_path无关。
内容的提问来源于stack exchange,提问作者Bergi
相关产品推荐
相关产品推荐

