Search code examples
postgresqlpermissionsrolespostgresql-12

Why UPDATE permission does not work without SELECT permission in PostgreSQL?


What is the purpose of UPDATE permission if it does not allow to update without SELECT permission?

Generally, I understand that update internally causes select to find target rows, but this "internal select" does not leak to a user, so it is unclear if it is a bug or there is a "deeper meaning" of that.

Assume initially my_user has only USAGE on my_schema and no grants on my_table

Case 1:

GRANT UPDATE ON TABLE my_schema.my_table TO my_user;

UPDATE my_table
   SET my_col = 'X';

>> SQL Error [42501]: ERROR: permission denied for table my_table

Case 2:

GRANT SELECT ON TABLE my_schema.my_table TO my_user;
GRANT UPDATE ON TABLE my_schema.my_table TO my_user;

UPDATE my_table
   SET my_col = 'X';

>> SUCCESS

Solution

  • Your assumption about "internal select" does not leak to a user is erroneous.

    The returning keyword is very powerful and can be used to proxy a select statement:

    UPDATE my_table
    SET my_col = my_col
    RETURNING *;
    

    --> will show the same as select * from my_table

    However, the select privilege is required only because the value of my_col is read. If you were to use a constant instead, it would work with just the update privilege and it wouldn't let you return the row.

    REVOKE select ON my_table FROM my_user;
    
    update my_table set my_col =1;
    UPDATE 7
    update my_table set my_col =1 returning *;
    ERROR:  permission denied for table test