Nested Inherited Roles Bypassing Column Select Permissions
Version Information
Server Version: v2.46.0-cloud.1
Environment
Hasura Cloud
What is the current behaviour?
When querying a table using a role that inherits from another inherited role (i.e., a "nested inherited role"), the permissions are not applied as expected. Specifically, the row-level and column-level restrictions defined in the base inherited role are ignored, and the nested inherited role gains unrestricted access to all columns and rows, even when it should inherit the more restrictive permissions.
For example:
- A base inherited role (
base_role) combines permissions from multiple roles, including a role (reader_role) with a row filter (e.g.,{"id": "X-Hasura-User-Id"}) and limited column access (e.g., includes an additional columnrestricted_field). - When querying directly with
base_role, the permissions work as expected: only the row matching the session variable is returned with therestricted_fieldcolumn, and other rows exclude this column. - However, when querying with a nested inherited role (
nested_role) that inheritsbase_roleand another role with no additional permissions on the table, the row filter and column restrictions are bypassed, and all rows include therestricted_fieldcolumn.
This behavior contradicts the expected permission inheritance logic outlined in the Hasura documentation for inherited roles.
What is the expected behaviour?
The nested inherited role (nested_role) should inherit the permissions of the base inherited role (base_role) correctly, including all row filters and column restrictions. Based on the documentation under "How the permissions of the inherited role are interpreted," the nested role should:
- Apply the row filter (e.g.,
{"id": "X-Hasura-User-Id"}) fromreader_roleviabase_role. - Restrict access to the
restricted_fieldcolumn to only the rows where the filter evaluates totrue, returningnullfor that column in all other rows, as described in the "Accessibility of a field for an inherited role" section.
In short, querying with nested_role should yield the same restricted results as querying with base_role, unless explicitly overridden.
How to reproduce the issue?
-
Set up a table and roles:
- Create a table
userswith columns:id(Int, PK),name(Text),restricted_field(Text). - Define a
publicrole with select permissions:- Columns:
id,name - No row filter (all rows accessible).
- Columns:
- Define a
reader_rolewith select permissions:- Columns:
id,name,restricted_field - Row filter:
{"id": "X-Hasura-User-Id"}.
- Columns:
- Create an inherited role
base_rolethat inherits frompublicandreader_role. - Create a nested inherited role
nested_rolethat inherits frombase_roleand another role (e.g.,writer_role) with no permissions defined on theuserstable.
- Create a table
-
Test with
base_role:- Query the
userstable with:POST /v1/graphql HTTP/1.1 Content-Type: application/json X-Hasura-Role: base_role X-Hasura-User-Id: 1query { users { id name restricted_field } } - Expected and observed result: Row with
id: 1includesrestricted_field, other rows exclude it (or shownull).
- Query the
-
Test with
nested_role:- Query the
userstable with:POST /v1/graphql HTTP/1.1 Content-Type: application/json X-Hasura-Role: nested_role X-Hasura-User-Id: 1query { users { id name restricted_field } } - Expected result: Same as
base_role(rowid: 1showsrestricted_field, others shownull). - Observed result: All rows include
restricted_field, ignoring the row filter.
- Query the
Screenshots or Screencast
https://github.com/user-attachments/assets/0931271c-c621-442b-8464-65447dcdcb9b
Keywords
- Inherited roles
- Nested inherited roles
- Permission inheritance
- Row filter bypass
- Column access restriction
- Hasura role permissions
Thanks for raising this issue @yoshiwarab . We are reviewing this with priority.
@rakeshkky has identified the issue and has a fix in-progress.
Awesome, thanks for the quick work!
Hey @manasag, any progress on this issue?
@yoshiwarab the issue was fixed in v2.47.0