---
title: "Supabase Exposed schemas：公開リストで何が開くのか"
description: "SupabaseのExposed schemasの意味、私のチェッカーが追加スキーマをどう評価するか、RLSなしのテーブルを見つけるSQLを紹介します。"
url: "https://madsalt.tech/ja/notes/supabase-exposed-schemas/"
author: "Denys Zaichenko"
language: "ja"
published: 2026-10-22
---

# Supabase Exposed schemas：公開リストで何が開くのか

TL;DR

SupabaseのExposed schemasリストは、公開キーを持つ誰に対してData APIがどのスキーマを提供するかを決めます。デフォルトは`public`と`graphql_public`です。リストにあるスキーマのテーブル、ビュー、関数は、それぞれ独自のgrantとRLSを持つ必要があるため、スキーマを1つ足すごとに守る面が増えます。リストは短く保ち、最初に確認してください。

私は無料の[Supabaseセキュリティチェッカー](https://madsalt.tech/ja/tools/supabase-security-check/)を作りましたが、Exposed schemasリストはそれが最初に読む項目の1つです。Supabaseプロジェクトの安全性を聞かれたとき、私が最初に見るのがこの設定です。

## Supabaseで「公開（exposed）」とは何か？

SupabaseはPostgRESTを使って、データベースをRESTで提供します。PostgRESTは`db_schema`リストにあるスキーマにしか応答しません。このリストはダッシュボードのProject Settings → Data API → Exposed schemasで編集します。私が見たプロジェクト設定では値は`public,graphql_public`で、Supabaseの[カスタムスキーマのガイド](https://supabase.com/docs/guides/api/using-custom-schemas)には、`public`はデフォルトで公開されると書かれています。リストにないスキーマへのリクエストは拒否され、[PostgREST](https://docs.postgrest.org/en/stable/references/api/schemas.html)は`pg_catalog`と`information_schema`をリストに入れることを決して許可しません。

## このリストはSupabaseのセキュリティでなぜ重要なのか？

公開されたスキーマの中身は、テーブル、ビュー、関数のすべてが公開キーで到達できます。Supabaseの[RLSガイド](https://supabase.com/docs/guides/database/postgres/row-level-security)ははっきり書いています。公開スキーマにあるRLSなしのテーブルは、grantを持つどのロールでも読み書きできます。リストにないスキーマには、APIからまったく到達できません。

つまり、スキーマを1つ追加するのは中立的な変更ではありません。リストに`storage`や`vault`を加えれば、内部テーブルをData APIの届く範囲に置くことになります。自分のスキーマを加えれば、その中のすべてのテーブルに`public`と同じ注意が必要です。

![余分な公開スキーマが開くもの。anonのリクエスト1件、リストを絞る前と後。前：余分なスキーマが公開されている：anonリクエスト → Data API → 余分なスキーマ → RLSなしテーブルが読める、後：publicとgraphql_publicのみ：anonリクエスト → Data API → デフォルトのスキーマのみ → 全テーブルでRLS有効。](https://madsalt.tech/charts/ja/supabase-exposed-schemas.svg)

*Supabaseセキュリティチェッカーのルールと、SupabaseのData APIドキュメントより、2026年10月22日。*

## チェッカーはこのリストをどう評価するのか？

チェック名は`extra_exposed_schemas`です。`public`と`graphql_public`以外はすべて追加扱いで、そのうえで次のように判定します。

- リストにSupabaseの内部スキーマ（`auth`、`storage`、`realtime`、`vault`、`extensions`など）がある場合は、**失敗、重大度は高**です。
- たとえば`api`のようなカスタムスキーマだけなら、**警告、重大度は中**です。
- 追加がなければ合格です。

同じリストは他のチェックにも使われます。RLSが無効なテーブル、anonへの書き込みgrant、常に真になるポリシー、`security_invoker`のないビュー、anonが呼び出せる`SECURITY DEFINER`関数は、公開スキーマについてだけ報告されます。公開キーが届くのはそこだからです。

## カスタムスキーマを安全に使うには？

カスタムスキーマは正当なパターンです。Supabaseの[Securing your API](https://supabase.com/docs/guides/api/securing-your-api)ガイドは、`api`のような専用スキーマを、公開される面を見分けやすく監査しやすくする方法として説明しています。内部テーブルは公開しないスキーマに置きます。成立させる手順は2つで、[カスタムスキーマのガイド](https://supabase.com/docs/guides/api/using-custom-schemas)に両方が載っています。スキーマをExposed schemasに追加し、そのスキーマの`usage`を`anon`、`authenticated`、`service_role`に付与し、さらにそのオブジェクトへの権限を付与します。

ガイドの例はすべてのテーブルに`ALL`を付与しています。私ならその行をそのままコピーしません。Securing your APIガイドは、各ロールに必要最小限だけを与え、公開するすべてのテーブルでRLSを有効にするよう述べています。grantはロールがテーブルに触れるかどうかを決め、ポリシーはどの行かを決めます。

別の変更もあります。Supabaseは[`public`の新しいテーブルをData APIに自動で付与しなくなります](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically)。新規プロジェクトでは2026年5月30日からデフォルトになり、既存プロジェクトには2026年10月30日に適用されます。既存のテーブルのgrantは維持されます。これはgrantの層の話で、リストにどのスキーマがあるかは変わりません。

## 自分のプロジェクトをどう確認する？

Project Settings → Data APIを開き、Exposed schemasを読んでください。`public`と`graphql_public`以外があれば、追加スキーマそれぞれが何のためのものかを確認します。

次に、それらのスキーマでRLSが無効なテーブルと、`anon`がすでに読めるかどうかを一覧にします。

```sql
select n.nspname as schema,
       c.relname as "table",
       has_table_privilege('anon', c.oid, 'select') as anon_can_select
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname in ('public', 'api')  -- your Exposed schemas
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1, 2;
```

私は、使い捨てのPostgres 17でこれを実行しました。`api`スキーマにはRLSありのテーブルとなしのテーブルを1つずつ、`public`にはRLSなしのテーブルを1つ置きました。結果は、RLSなしの2つだけでした。

```text
 schema | table  | anon_can_select
--------+--------+-----------------
 api    | orders | t
 public | logs   | t
```

`anon_can_select`が真の行はすべて、公開キーを持つ誰でも読めるテーブルです。RLSを有効にするか、grantを取り消すまでそのままです。このクエリが対象にするのはテーブルだけです。ビューと関数は別に確認する必要があり、それは私の[Lovableアプリのセキュリティチェックリスト](https://madsalt.tech/ja/blog/lovable-app-security-checklist/)で順に見ています。また、[Supabase RLSのテスト方法](https://madsalt.tech/ja/blog/how-to-test-supabase-rls/)では、ポリシーが機能することをどう証明するかを示しています。
