-
-
Notifications
You must be signed in to change notification settings - Fork 81
feat: add lint to detect RLS policies that allow access to anonymous users #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kangmingtay
wants to merge
14
commits into
main
Choose a base branch
from
km/add-lint-for-anonymous-users
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
0cbd0a1
feat: add lint for anonymous users & docs
kangmingtay 172f6f2
fix: add tests
kangmingtay 1a3098b
update installcheck
kangmingtay 32a0738
update splinter
kangmingtay a22f13f
update installcheck
kangmingtay 54fbe31
Merge branch 'main' into km/add-lint-for-anonymous-users
olirice 20473e6
re-align test output
olirice 2f65dec
add true positive test case
olirice f1d1018
update anonymous login docs url
olirice 0a7d4b7
Merge branch 'main' into km/add-lint-for-anonymous-users
olirice 3bb4918
add test for case sensitivity
kangmingtay 6a5f390
update installcheck to output diff
kangmingtay fbf0ea8
update build artifacts
kangmingtay 42d6017
Update docs/0012_auth_allow_anonymous_sign_ins.md
kangmingtay File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| Level: INFO | ||
|
|
||
| ### Rationale | ||
|
|
||
| Anonymous users use the same `authenticated` Postgres role as permanent users when accessing the database. If you have enabled anonymous sign-in for your project, existing RLS policies may allow unintended access to an anonymous user's JWT. | ||
kangmingtay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### Difference between an anonymous user and a permanent user | ||
|
|
||
| An anonymous user is a user created through Supabase Auth. It is just like a permanent user, except the user can't access their account if they sign out, clear browsing data or use another device. An anonymous user can be differentiated from a permanent user by checking if the `is_anonymous` claim is true. These claims are returned by the `auth.jwt()` function. | ||
|
|
||
| ### How to Resolve | ||
|
|
||
| Determine if existing row level security (RLS) policies are meant to allow access to anonymous users. Affected policies include those that are associated to the `authenticated` or `public` roles, and members of those roles that inherit privileges. | ||
|
|
||
| For example, consider the policy: | ||
|
|
||
| ```sql | ||
| create policy "allow_access_to_authenticated" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using (true); | ||
| ``` | ||
|
|
||
| In this policy, any JWT that contains the authenticated role will be allowed to access the documents table. If we want to restrict access to permanent users only, we can modify the policy to: | ||
|
|
||
| ```sql | ||
| create policy "allow_access_to_permanent_users" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using ( (select (auth.jwt()->>'is_anonymous')::boolean) is false ); | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| create view lint."0012_auth_allow_anonymous_sign_ins" as | ||
|
|
||
| with recursive role_members as ( | ||
| select | ||
| roleid, | ||
| member | ||
| from pg_catalog.pg_auth_members | ||
| where roleid = (select oid from pg_roles where rolname = 'authenticated') | ||
| union | ||
| select | ||
| am.roleid, | ||
| am.member | ||
| from pg_catalog.pg_auth_members as am | ||
| inner join role_members as rm on am.roleid = rm.member | ||
| ), | ||
|
|
||
| member_names as ( | ||
| select r.rolname from pg_roles as r | ||
| inner join role_members as m on r.oid = m.member | ||
| ) | ||
|
|
||
| select | ||
| 'auth_allow_anonymous_sign_ins' as name, | ||
| 'INFO' as level, | ||
| 'EXTERNAL' as facing, | ||
| 'Detects row level security (RLS) policies that allow access to anonymous users.' as description, | ||
| 'https://supabase.github.io/splinter/0012_auth_allow_anonymous_sign_ins' as remediation, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you change this to a main docs site link please? Following the pattern here: https://supabase.com/docs/guides/database/database-advisors |
||
| format( | ||
| 'Table \`%s.%s\` has policies enforced on roles that allow access to anonymous users. Policies include \`%s\`', | ||
| n.nspname, | ||
| c.relname, | ||
| array_agg(p.policyname order by p.policyname) | ||
| ) as detail, | ||
| jsonb_build_object( | ||
| 'schema', n.nspname, | ||
| 'name', c.relname, | ||
| 'type', 'table' | ||
| ) as metadata, | ||
| format( | ||
| 'auth_allow_anonymous_sign_ins_%s_%s', | ||
| n.nspname, | ||
| c.relname | ||
| ) as cache_key | ||
| from pg_catalog.pg_policies as p | ||
| inner join pg_catalog.pg_class as c on p.tablename = c.relname | ||
| inner join pg_catalog.pg_namespace as n on c.relnamespace = n.oid | ||
| where | ||
| ( | ||
| p.roles = array['public'::name] -- public roles | ||
| or p.roles = array['authenticated'::name] -- authenticated roles | ||
| or exists ( | ||
| select rolname from member_names where rolname = any(roles) | ||
| ) -- roles that are members of authenticated | ||
| ) | ||
| and replace(p.qual, ' ', '') not like '%auth.jwt()%->>%is_anonymous%' | ||
| group by n.nspname, c.relname | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| begin; | ||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
kangmingtay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| name | level | facing | description | remediation | detail | metadata | cache_key | ||
| ------+-------+--------+-------------+-------------+--------+----------+----------- | ||
| (0 rows) | ||
|
|
||
| create table public.documents( id int primary key ); | ||
| -- Create a policy for the authenticated role that would allow access to anonymous login users | ||
| -- if that feature is enabled | ||
| create policy "allow_access_to_authenticated" on public.documents | ||
| as restrictive | ||
| to authenticated | ||
| using (true); | ||
| -- 1 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
| name | level | facing | description | remediation | detail | metadata | cache_key | ||
| -------------------------------+-------+----------+---------------------------------------------------------------------------------+------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+------------------------------------------------ | ||
| auth_allow_anonymous_sign_ins | INFO | EXTERNAL | Detects row level security (RLS) policies that allow access to anonymous users. | https://supabase.github.io/splinter/0012_auth_allow_anonymous_sign_ins | Table \`public.documents\` has policies enforced on roles that allow access to anonymous users. Policies include \`{allow_access_to_authenticated}\` | {"name": "documents", "type": "table", "schema": "public"} | auth_allow_anonymous_sign_ins_public_documents | ||
| (1 row) | ||
|
|
||
| drop policy "allow_access_to_authenticated" on public.documents; | ||
| -- Resolve the issue by excluding anonymous login users | ||
| create policy "allow_access_to_permanent_users" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using ( (select (auth.jwt() ->> 'is_anonymous')::boolean) is false ); | ||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
| name | level | facing | description | remediation | detail | metadata | cache_key | ||
| ------+-------+--------+-------------+-------------+--------+----------+----------- | ||
| (0 rows) | ||
|
|
||
| -- Check if policy definition passes with case sensitive characters | ||
| create policy "allow_access_to_permanent_users_case_senstive" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using ( (select (AUTH.JWT() ->> 'is_anonymous')::boolean) is false ); | ||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
| name | level | facing | description | remediation | detail | metadata | cache_key | ||
| ------+-------+--------+-------------+-------------+--------+----------+----------- | ||
| (0 rows) | ||
|
|
||
| rollback; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| begin; | ||
|
|
||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
|
|
||
| create table public.documents( id int primary key ); | ||
|
|
||
| -- Create a policy for the authenticated role that would allow access to anonymous login users | ||
| -- if that feature is enabled | ||
| create policy "allow_access_to_authenticated" on public.documents | ||
| as restrictive | ||
| to authenticated | ||
| using (true); | ||
|
|
||
| -- 1 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
|
|
||
| drop policy "allow_access_to_authenticated" on public.documents; | ||
|
|
||
| -- Resolve the issue by excluding anonymous login users | ||
| create policy "allow_access_to_permanent_users" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using ( (select (auth.jwt() ->> 'is_anonymous')::boolean) is false ); | ||
|
|
||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
|
|
||
| -- Check if policy definition passes with case sensitive characters | ||
| create policy "allow_access_to_permanent_users_case_senstive" on documents | ||
| as restrictive | ||
| to authenticated | ||
| using ( (select (AUTH.JWT() ->> 'is_anonymous')::boolean) is false ); | ||
|
|
||
| -- 0 issues | ||
| select * from lint."0012_auth_allow_anonymous_sign_ins"; | ||
|
|
||
| rollback; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.