Community程式設計與開發github.com

atokim4/supabase-rls-audit

審查儲存庫中的遷移檔案,檢查 Supabase 資料列層級安全(RLS)設定,找出常見安全性問題。

supabase-rls-audit 是什麼?

此技能會剖析專案中的 SQL 遷移檔案(Supabase 遷移、schema.sql),依序重建資料表、政策、檢視、函數、權限和儲存桶,並檢查 9 種常見的 RLS 問題,例如:公開資料表未啟用 RLS、使用寬鬆的 `using (true)` 或 `with check (true)` 政策、檢視繞過 RLS、以及 `auth.users` 資料表暴露等。它完全離線運作,不需連接資料庫,適合在啟動 Supabase 應用程式前、撰寫遷移檔案後,或審查 Lovable、Bolt、Cursor 等工具產生的專案時使用。支援 Claude Code、Cursor 等 AI 代理,透過執行本機 Node 腳本掃描 SQL 檔案來輸出結構化 JSON 結果,協助開發者快速定位並修正 RLS 設定缺陷。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/atokim4/vibe-preflight/tree/HEAD/skills/supabase-rls-audit

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Supabase RLS 審查

此技能會執行 vibe-preflight 掃描器的資料庫部分(位於此檔案旁的 scripts/preflight.mjs,需要 Node 20+,無相依套件,不須網路連線)。它會讀取專案中的 .sql 檔案(Supabase 遷移、schema.sql),依序重現資料表、政策、檢視、函數、權限和儲存桶,並回報 9 種問題。它不會連線到資料庫。

執行方式

從專案根目錄執行:

node ${CLAUDE_SKILL_DIR}/scripts/preflight.mjs . --only database --format json

Claude Code 會自動填入 ${CLAUDE_SKILL_DIR}。其他代理:請使用此技能的資料夾路徑,例如 .agents/skills/supabase-rls-audit 或 .claude/skills/supabase-rls-audit。

退出碼 1 表示至少有一個錯誤。加上 --fail-on warning 則連警告也會導致失敗。加上 --explain 可輸出文字格式的說明與修復建議。JSON 輸出格式:{ summary: { error, warning }, findings: [{ rule, severity, message, file, line }] }。

如果結果顯示 0 SQL files,表示政策可能只存在於 Dashboard 中。請要求使用者執行 supabase db pull(它會將遠端結構寫入遷移檔案)後再掃描一次。不要在空掃描的結果下回報專案為乾淨。

檢查項目

規則層級意義
rls-disabled錯誤public 資料表從未啟用「enable row level security」,因此任何擁有 anon 金鑰的人都可以透過 API 讀取和寫入它。
rls-permissive-policy寫入為錯誤,讀取為警告using (true) 或 with check (true)。在 insert/update/delete 時,任何使用者都可以更改其他使用者的資料列。在 select 時,所有資料列都會公開。
rls-no-policy警告RLS 已啟用,但無任何政策:API 會拒絕所有操作。這對僅供伺服器存取的資料表來說沒問題;但如果瀏覽器讀取它,則會得到空列表。
rls-update-privileged-column警告使用者可以更新自己的資料列,且該資料表包含 plan、role、is_admin、credits 等欄位。RLS 限制的是資料列,而不是欄位。
view-bypasses-rls錯誤檢視未設定 security_invoker = true,它會以擁有者的身分執行,並跳過其底層資料表的 RLS。
auth-users-exposed錯誤public 中的檢視選取了 auth.users 的資料。
definer-search-path警告security definer 函數未設定 set search_path。
definer-function-anon錯誤 / 警告public 中的 security definer 函數,且 anon 角色可以透過 /rest/v1/rpc/<name> 呼叫。如果明確授予 anon 權限則為錯誤,如果是 Supabase 的預設權限則為警告。
storage-public-bucket錯誤 / 警告公開的儲存桶。如果 storage.objects 上的 select 政策也允許任何人列出內容則為錯誤。

修復方式

請務必撰寫新的遷移檔案。切勿編輯已在資料庫上執行過的遷移檔案。

遺失或過於寬鬆的政策:詢問應用程式需要的存取權限,然後將每個政策限定到特定角色和資料擁有者。

alter table public.notes enable row level security;
create policy "notes: 讀取自己的" on public.notes
  for select to authenticated using ((select auth.uid()) = user_id);
create policy "notes: 新增自己的" on public.notes
  for insert to authenticated with check ((select auth.uid()) = user_id);

特權欄位:只允許更新使用者可以修改的欄位。

revoke update on public.profiles from authenticated;
grant update (display_name, avatar_url) on public.profiles to authenticated;

檢視:alter view public.<name> set (security_invoker = true);(需要 PostgreSQL 15+,目前所有 Supabase 專案都支援)。具體化檢視(materialized view)無法使用 RLS:請將其移出 public 結構,或撤銷 anon, authenticated 角色的 select 權限。針對 auth.users,請在註冊觸發器中將可分享的欄位複製到 public.profiles 表中。

SECURITY DEFINER 函數:加上 set search_path = '' 並完整寫出每個物件的結構名稱。然後限制誰可以呼叫它:

revoke execute on function public.admin_set_plan(uuid, text) from public, anon, authenticated;
grant execute on function public.admin_set_plan(uuid, text) to service_role;

在 Supabase 上,僅撤銷 public 角色的權限是不夠的,因為 anon 角色對新函數有其自己的權限。

儲存:將私有儲存桶設為私有,將讀取範圍限定為擁有者的資料夾((storage.foldername(name))[1] = (select auth.uid())::text),並提供簽署的 URL。產品圖片和標誌可以保持公開。

如果某個發現是預期中的行為(例如公開的目錄、僅供伺服器存取的資料表),可以在該行或其上一行加上 -- vibe-preflight-ignore <rule-id> 來忽略它。請在同一註解中說明原因。

回報方式

  1. 在進行任何變更前,逐一開啟被回報的程式行,並與 SQL 內容比對確認。掃描器是讀取 SQL 文字,可能會出錯;如果發現錯誤請明確指出。
  2. 依規則將摘要分組。先列出錯誤,再列出你與使用者確認過的警告。
  3. 修正後再次執行掃描,並報告新的結果。

限制

  • 僅檢查 .sql 檔案中的內容。Dashboard 中的變更、其他結構以及函數內部的邏輯都不在檢查範圍內。
  • 乾淨的結果僅表示未找到這 9 種模式,並不代表政策完全符合應用程式的規則。仍然建議以真實的 anon 和已登入使用者身分進行測試(使用附有 anon 金鑰的 Supabase 用戶端)。
  • 若要檢查瀏覽器和環境端(用戶端程式碼中的 service_role 金鑰、NEXT_PUBLIC_ 變數中的機密、已提交的 .env 檔案),請執行不含 --only 的完整掃描,或使用 vibe-preflight 技能。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能