---
title: "Supabase「RLS disabled in public」とは？ 意味と直し方"
description: "SupabaseのAdvisorが出すrls_disabled_in_publicの意味、ローカルのテストで公開キーがそのテーブルに何をしたか、安全な直し方を紹介します。"
url: "https://madsalt.tech/ja/notes/supabase-rls-disabled-in-public/"
author: "Denys Zaichenko"
author_url: "https://madsalt.tech/ja/about/"
language: "ja"
published: 2026-10-28
---

# Supabase「RLS disabled in public」とは？ 意味と直し方

TL;DR

「RLS Disabled in Public」（lint `0013_rls_disabled_in_public`、レベルはERROR）は、公開されたスキーマのテーブルでrow level security（RLS）がオフなのに、`anon`または`authenticated`がselectできる状態を指します。私のローカルのテストでは、公開キーはそのようなテーブルの3行中3行すべてを読み、`201 Created`で新しい行も挿入しました。RLSを有効にし、操作ごとにポリシーを追加し、grantを確認する作業を、1つのマイグレーションで行ってください。

私は無料の[Supabaseセキュリティチェッカー](https://madsalt.tech/ja/tools/supabase-security-check/)を作りましたが、その最初のルール「公開されたテーブルで RLS が無効」は、SupabaseのSecurity Advisorがエラーとして報告するものと同じ指摘です。AIツールで作られたアプリで私が最もよく見つける穴なので、これが何を意味するかと、再現して何が可能だったかを説明します。

## 「RLS disabled in public」とは何か？

Security Advisorは、`rls_disabled_in_public`というlintを実行します。その[SQL](https://github.com/supabase/splinter/issues/82)は、次の3つが同時に成り立つときにテーブルを指摘します。

1. row level securityがオフの、通常のテーブルである。
2. `anon`または`authenticated`が、そのテーブルに`SELECT`を持っている。
3. スキーマが、Data APIのExposed schemasリストにある。デフォルトは`public`です。

[lintのページ](https://supabase.github.io/splinter/0013_rls_disabled_in_public/)は、これをERRORとし、インターネット経由での作成・読み取り・更新・削除がすべて可能な状態を「a critically unsafe configuration」（極めて危険な設定）と呼んでいます。名前の「public」はスキーマのことですが、lintは公開されているすべてのスキーマを対象にします。だから、そのリストにある余分なスキーマも確認する価値があります。これは[Supabase Exposed schemas](https://madsalt.tech/ja/notes/supabase-exposed-schemas/)に書きました。

## 公開キーはそのテーブルに何ができる？

ローカルのSupabaseスタック（CLI 2.109.1、Postgres 17.6、PostgREST 14.14）に、偽の顧客3人の`orders`テーブルを作りました。既存プロジェクトが新しいテーブルに付けるgrantを持たせ、RLSはオフです。そのうえで、ブラウザと同じようにpublishable keyでData APIを呼び出しました。

![1つのテーブル、公開キー、RLSオフとオン。ローカルのSupabase、偽の注文3行。RLSオフ、読み取り：Publishable key → orders、RLSオフ → 3行中3行、RLSオフ、挿入：Publishable key → orders、RLSオフ → 201 Created、RLSオン、ポリシーはまだなし：Publishable key → orders、RLSオン → 0行。](https://madsalt.tech/charts/ja/supabase-rls-disabled-in-public.svg)

*ローカルのSupabaseスタックでの私の再現、2026年10月23日。*

| publishable keyでのリクエスト    | RLSオフ                            | RLSオン、ポリシーなし                                     |
| -------------------------------- | ---------------------------------- | --------------------------------------------------------- |
| `GET /rest/v1/orders?select=*`   | `200`、名前とメールを含む3行すべて | `200`、`[]`                                               |
| 新しい行を`POST /rest/v1/orders` | `201 Created`                      | `401`、42501 "new row violates row-level security policy" |

アプリを開いた人は誰でも、ページからpublishable keyをコピーできます。RLSがオフなら、そのキーはこのテーブルへの読み書きの通行証になります。

## アプリを壊さずに直すには？

RLSを有効にするだけだと、まだポリシーがないので、テーブルはアプリに何も返さなくなります。この空の画面のときに、人も、AIツールも、`using (true)`のポリシーを足してしまいます。それは、すべての行を全員に返します。そのあと更新や削除が、何も変えないのに成功と報告する理由は[Supabase RLSを有効にする方法と結果](https://madsalt.tech/ja/blog/how-to-enable-rls-in-supabase/)にあります。本当のポリシーは、同じマイグレーションの中で書いてください。

```sql
alter table public.orders enable row level security;

revoke all on table public.orders from anon, authenticated;
grant select, insert on table public.orders to authenticated;

create policy "Customers read their orders"
on public.orders for select
to authenticated
using ((select auth.uid()) = user_id);

create policy "Customers create their orders"
on public.orders for insert
to authenticated
with check ((select auth.uid()) = user_id);
```

公開記事の一覧のように、テーブルを公開する場合でも、RLSはオンのままにして、`anon`向けの`select`ポリシーを1つ書き、書き込みのgrantは付けません。Data APIを使わず、サーバーからだけPostgresに接続するなら、Supabaseのメンテナーが[同じissue](https://github.com/supabase/splinter/issues/82)で提案したように、Exposed schemasから`public`を外してください。

新しいテーブルがRLSなしで始まらないようにするには、Supabaseの[event triggersのガイド](https://supabase.com/docs/guides/database/postgres/event-triggers)に、`public`に作られるすべてのテーブルでRLSを有効にするトリガーがあります。また、2026年10月30日からは、新しいテーブルにData APIのgrantがデフォルトで付かなくなり、grantするまで`42501`を返します。これは[Supabase 42501 permission denied](https://madsalt.tech/ja/notes/supabase-42501-permission-denied/)で扱いました。

## 問題なしという結果は、何を証明しない？

RLSがオンであることは、ポリシーが正しいかどうかについて何も教えてくれません。同じテストで、`using (true)`と書いたポリシーは、公開キーに再び3行すべてを返し、RLSがオンになるとこのlintは何も言わなくなります。チェッカーには、そのための別のルール「すべての行を許可するポリシー」があり、[Supabase RLSのテスト方法](https://madsalt.tech/ja/blog/how-to-test-supabase-rls/)では、実在のユーザーで各ポリシーを証明する方法を示しています。出発点にできるポリシーを、実在のユーザーでAPI経由で実行した結果とともに、[Supabase RLSポリシー例：APIで検証済み](https://madsalt.tech/ja/blog/supabase-rls-policy-examples/)にまとめました。
