Skip to content

plan generates destructive ALTER POLICY when USING expression contains dot in string literal #371

@dilame

Description

@dilame

Summary

pgschema plan produces a false-positive ALTER POLICY that silently truncates string literals containing dots in USING/WITH CHECK expressions. Applying this plan would break RLS policies.

Environment

Minimal repro

CREATE SCHEMA s;
CREATE SCHEMA auth;

CREATE FUNCTION auth.has_scope(p_scope text) RETURNS boolean
LANGUAGE sql STABLE AS $$ SELECT p_scope IS NOT NULL $$;

CREATE ROLE test_role;

CREATE TABLE s.items(id int);
ALTER TABLE s.items ENABLE ROW LEVEL SECURITY;

CREATE POLICY manage_items ON s.items
    FOR UPDATE TO test_role
    USING (auth.has_scope('s.manage'))
    WITH CHECK (auth.has_scope('s.manage'));
# 1. Dump
pgschema dump --schema s --db <db> --user <user> > /tmp/s_dump.sql

# 2. Verify dump is correct — should contain 's.manage'
grep has_scope /tmp/s_dump.sql
# Expected: auth.has_scope('s.manage')

# 3. Plan (expect empty — no changes)
pgschema plan --schema s --db <db> --user <user> \
  --file /tmp/s_dump.sql \
  --plan-host localhost --plan-db <db> --plan-user <user> \
  --output-sql /dev/stdout

Expected

Empty plan (dump matches current state).

Actual

ALTER POLICY manage_items ON items USING (auth.has_scope('manage')) WITH CHECK (auth.has_scope('manage'));

The string literal 's.manage' is truncated to 'manage' — the s. prefix (which matches the schema name) is stripped.

Impact

  • Destructive: applying this plan silently breaks RLS policies by corrupting function arguments
  • Silent data corruption: no error or warning, the plan looks valid
  • Affects any policy where a string literal happens to contain <schema_name>. as a prefix

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions