Zum Hauptinhalt springen
友田 陽大
Application-layer security
Supabase
RLS
Next.js
セキュリティ
TypeScript
アーキテクチャ設計
生成AI

Supabaseで「他人のデータが見える」IDOR脆弱性はこう生まれる — AI生成のNext.jsコードに潜む認可欠陥を発見・修正する実践ガイド

AIで量産したNext.js × SupabaseアプリがOWASP API1:2023 BOLA(IDOR)で他人のデータを露出させる仕組みを、CVE-2025-48757とservice_roleキーによるRLSバイパスを軸に解説。WAFやセキュリティヘッダーでは防げない理由と、taint解析・RLS検証・実行時確認の3層で体系的に発見・修正する方法を、脆弱→修正の実コードで示します。

Published
Reading time
20 min read
Author
友田 陽大
Teilen

最初に結論を述べます。AIで素早く作ったNext.js × Supabaseアプリが「他人のデータを見せてしまう」のは、ほとんどの場合 IDOR(オブジェクト単位の認可欠陥)が原因で、それは行レベルセキュリティ(RLS)の「中」ではなく「外側」——コードとSQLの継ぎ目——に空きます。 そしてこの穴は、WAFやセキュリティヘッダーといった「横の対策」では構造的に塞げません。攻撃リクエストが、認証も書式も完全に正しい「正規のリクエスト」だからです。

これは「AIを使うな」「Supabaseは危ない」という話ではありません。RLSは強力で、Supabaseは堅牢です。問題は、認可(authorization)という"縦のリスク"を、AIも開発者も「動いたから大丈夫」で見落としやすいことにあります。本記事は、その見落としがどう生まれ、なぜ自動の防御では防ぎきれず、どうすれば体系的に発見・修正できるのかを、実コードと公開された一次情報に基づいて解説します。


1. IDOR/BOLAとは何か——「認証は通っているのに、認可で漏れる」

まず用語を正確に押さえます。

  • 認証(Authentication)=「あなたは誰か」を確かめること。ログインがこれです。
  • 認可(Authorization)=「あなたはこの操作・このデータに対して権限を持つか」を確かめること。

IDOR(Insecure Direct Object Reference)は、後者の失敗です。OWASPの最新版API Security Top 10では API1:2023 Broken Object Level Authorization(BOLA) という名前で、最も深刻なAPIリスクの第1位に位置づけられています(OWASP API Security Top 10)。しかも2019年の初版以来、一度も首位を譲っていません。「めったに起きない高度な攻撃」ではなく、「最も普通に、最も頻繁に起きる漏洩」です。

仕組みは拍子抜けするほど単純です。

GET /api/invoices/1024   ← 自分の請求書(正規アクセス)
GET /api/invoices/1025   ← IDを1つ増やすだけ。これが他人の請求書を返したらIDOR

ユーザーは正しくログインしており、リクエストの形式も正しい。違うのは、URLに含まれる オブジェクトID(1025)が、そのユーザーの所有物かどうかをサーバーが確かめていない という一点だけです。OWAPSの例では、車両のVIN(車台番号)をAPIに渡すと、それが本当にログイン中のユーザーの車かを検証せずにデータを返してしまう、というケースが挙げられています。

ここで重要なのは、この「正規ユーザーが意図的に境界を踏み越える」性質です。後述するとおり、これが「自動の防御では防げない」ことの根本原因になります。


2. なぜAIが書いたSupabaseコードはIDORを量産するのか

AI生成コードのセキュリティについては、推測ではなく実測データがあります。Veracodeが100以上のLLMに対して4言語・80のコーディングタスクを課した2025年の調査では、AIが生成したコードの45%が既知のセキュリティ欠陥を含み、安全だったのは55%にとどまりましたVeracode 2025 GenAI Code Security Report)。さらに重要なのは、モデルが大きく賢くなっても、セキュリティの成績は横ばいだったという点です。コードは「より動く」ようになったが、「より安全」にはなっていない。

なぜか。AIは、プロンプトで指示された「やりたいこと(=デモで動くこと)」を最短距離で実現するコードを書きます。「他人のデータを見せない」は、明示的に要求されない限りハッピーパスの外側にあり、デモでは絶対に顕在化しない。自分のアカウントで触っている限り、IDを書き換えて他人を覗く操作は誰もしないからです。

Supabaseという組み合わせでは、この一般的傾向が2つの決まった失敗モードに収束します。

失敗モード何が起きるかRLSとの関係
① RLS未設定の露出テーブルにRLSを有効化し忘れ、公開APIから anon キーで全件読めるRLSが「無い」
② service_role でのバイパスサーバー側で service_role キーを使い、所有権チェックなしでIDを受け取るRLSを「無視している」

この2つは、現実の重大インシデントとして公開されています。2025年に登録された CVE-2025-48757 は、その典型です。NVDの公式記述はこうです——「Lovable(2025-04-15まで)の不十分なRow-Level Securityポリシーにより、リモートの未認証攻撃者が、生成されたサイトの任意のDBテーブルを読み書きできる」。分類は CWE-863(Incorrect Authorization、不正な認可)、CVSS基本値は 9.3 CRITICAL です。

注目すべきは、このCVEがベンダーから 「disputed(係争中)」 とされている点です。プラットフォーム側の主張は「アプリのデータ保護は利用者の責任である」。この主張の是非はともかく、事実として、IDOR/認可はプラットフォームが肩代わりしてくれない"あなたの責任範囲"だということを、このCVEは雄弁に物語っています。買って済ませられないからこそ、設計と検証で自衛するしかありません。

以降で、2つの失敗モードを実コードで分解します。


3. 失敗モード①:RLSが有効化されないまま公開APIに露出する

Supabaseは、PostgreSQLのテーブルを PostgREST 経由で自動的にREST APIとして公開します。便利な反面、これは「RLSを有効化していないテーブルは、anon キーを知っていれば誰でも読める」ことを意味します。anon キーはブラウザに配られる公開鍵で、秘密ではありません。

-- 危険:RLSを有効化していないテーブル
create table profiles (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users,
  full_name text,
  phone text,
  stripe_customer_id text
);
-- ↑ enable row level security を書き忘れると…
--   curl "https://<project>.supabase.co/rest/v1/profiles?select=*" \
--        -H "apikey: <anon-key>"
--   が、全ユーザーの氏名・電話番号・Stripe顧客IDを返してしまう

これがCVE-2025-48757で起きたことの本質です。テーブルを作るSQLは生成できても、「公開APIに晒される前提でRLSを必ず張る」という運用規律は、AIのデフォルト出力には含まれていません。

修正は単純ですが、2段階であることが重要です。

-- ステップ1:RLSを有効化する(これ自体が fail-secure =デフォルト全拒否)
alter table profiles enable row level security;

-- ステップ2:必要なアクセスだけを明示的に許可する
--   有効化しただけでポリシーが無い状態は「誰も読めない」。
--   そこから、自分の行だけ読める許可を足す。
create policy "users read own profile"
on profiles for select
to authenticated
using ( (select auth.uid()) = user_id );

ポイントは2つあります。

  1. RLSの有効化は fail-secure。ポリシーが1つも無ければ、デフォルトは「全拒否」です。「とりあえず有効化」しておけば、少なくとも無防備な全件公開は止まります。
  2. auth.uid()(select auth.uid()) で包む。これはSupabase公式が推奨する書き方で、行ごとに関数を再評価せず初期計画でキャッシュさせるため、大きなテーブルで性能が桁違いに変わります。素の auth.uid() = user_id と書くと、正しく動くのに遅い、という罠にはまります。

ただし——「全テーブルにRLSを張れば終わり」ではありません。 ここが本記事の核心です。次の失敗モード②は、RLSが完璧に張られていても、それを丸ごと無効化してしまいます。


4. 失敗モード②:service_roleキーでRLSを「回避」したまま所有権チェックを忘れる

Supabaseには2種類のサーバー鍵があります。RLSを尊重する anon キー と、RLSを完全に無視する service_role キー です。後者は、PostgreSQLの BYPASSRLS 属性を持つ service_role として認証されます。Supabase公式ドキュメントは明確にこう述べています——「service_role キーは Row Level Security を完全にバイパスする。サーバー側でのみ使うこと」「RLSポリシーに service_role を足しても何の効果もない。なぜなら service_role はRLSの中で動くのではなく、RLSそのものを飛び越えるからだ」(Supabase: Row Level Security)。

ここで何が起きるか。AIエージェント(や急いでいる開発者)は、サーバー側のRoute Handlerで「RLSのポリシー設定に悩むより、管理者クライアントを使えば確実に動く」という誘惑に負けます。そして service_role でRLSを回避したまま、所有権チェックを書き忘れる

脆弱なコード:service_roleキー × 所有権チェックなし

// app/api/invoices/[id]/route.ts — 脆弱(IDOR)
import { createClient } from "@supabase/supabase-js";

// service_role キー:RLS を完全にバイパスする“管理者”クライアント
const supabaseAdmin = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!,
);

export async function GET(
  _req: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params; // ← クライアントが自由に変えられる値(汚染された入力)

  const { data, error } = await supabaseAdmin
    .from("invoices")
    .select("*")
    .eq("id", id) // ← 所有権の条件が一切ない=IDOR
    .single();

  if (error) return Response.json({ error: error.message }, { status: 404 });
  return Response.json(data); // 他人の請求書もそのまま返る
}

このコードの恐ろしさは、invoices テーブルに完璧なRLSポリシーが張ってあっても、まったく効かないことです。service_role がRLSを飛び越えるからです。失敗モード①の対策(RLSを張る)を完璧にやり遂げた現場でも、このルートが1本あれば全部漏れます。攻撃は前述のとおり、/api/invoices/1024/api/invoices/1025 に書き換えるだけです。

この「クライアントが操作できる入力(params.id)が、所有権で絞られないまま危険なシンク(DBクエリ)に到達する」という流れを、私は 汚染スコープ型IDOR(tainted-scope IDOR) と呼んで、後述の静的解析ルールで検出対象にしています。

修正案A(推奨):認可をDBに任せる——ユーザーのRLSを効かせる

最も堅牢なのは、そもそも service_role を使わず、ユーザーのセッションで動く anon キーのクライアントを使うことです。こうすれば、認可はDBのRLSが強制し、コードが所有権チェックを書き忘れても安全側に倒れます(多層防御の"最後の砦"がDBになる)。

// app/api/invoices/[id]/route.ts — 修正案A:RLSに認可を任せる
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";

export async function GET(
  _req: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params;
  const cookieStore = await cookies();

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, // ← anon キー=RLSが効く
    {
      cookies: {
        getAll: () => cookieStore.getAll(),
        setAll: () => {}, // 読み取り専用ルートなので省略
      },
    },
  );

  // RLS が「自分の行」しか返さないため、IDを書き換えても他人の行は0件になる
  const { data, error } = await supabase
    .from("invoices")
    .select("*")
    .eq("id", id)
    .single();

  if (error) return Response.json({ error: "not found" }, { status: 404 });
  return Response.json(data);
}

対応するRLSポリシー:

alter table invoices enable row level security;

create policy "owners read their invoices"
on invoices for select
to authenticated
using ( (select auth.uid()) = user_id );

この設計の強みは 「認可をコードから消せる」 ことです。所有権の判定がDBに一元化され、開発者やAIが新しいルートを足すたびに .eq("user_id", ...) を書き忘れるリスクが消えます。ETC(Easy To Change)の観点でも、認可ロジックが1か所に集約され、変更が局所化されます。

修正案B:service_roleが必要なら、所有権をコードで"必ず"強制する

管理画面やバッチなど、本当にRLSを越える必要がある経路もあります。その場合は、「誰なのか」をサーバーで確定し、所有権をWHERE句で必ず縛る——この2点を規律として徹底します。

// 修正案B:service_role を使うなら、所有権をコードで強制する
import { createClient } from "@supabase/supabase-js";

const supabaseAdmin = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!,
);

export async function GET(
  req: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params;

  // 1) 誰なのかをサーバーで確定する(クライアントの自己申告を信じない)
  const user = await getAuthenticatedUser(req);
  if (!user) return Response.json({ error: "unauthorized" }, { status: 401 });

  // 2) service_role でも、所有権を必ず WHERE で縛る
  const { data, error } = await supabaseAdmin
    .from("invoices")
    .select("*")
    .eq("id", id)
    .eq("user_id", user.id) // ← この1行が無いと IDOR
    .single();

  if (error || !data) return Response.json({ error: "not found" }, { status: 404 });
  return Response.json(data);
}

修正案Bは正しく動きますが、脆いことを理解しておくべきです。.eq("user_id", user.id) を書き忘れた瞬間に穴が開き、コンパイラもRLSも助けてくれません。だから原則は A(DBに認可を寄せる)、Bは「越える理由がある経路だけ、レビューで重点監視する例外」という位置づけにします。

Server Actions も同じ穴に落ちます。 "use server" のアクションは実質POSTエンドポイントで、formData.get("id") や引数で受け取るIDは等しくクライアント操作可能です。「画面に出していないIDだから安全」は成立しません。HTTPで叩けば誰でも任意の値を送れます。同じ所有権ルールを必ず適用してください。


5. なぜWAF・セキュリティヘッダー・「RLSさえあれば」では防ぎきれないのか

ここまでで、IDORが「コードとSQLの継ぎ目」に空くこと、RLSを張っても service_role 経路で抜けることを見ました。では、なぜ世の中の"セキュリティ製品"で自動的に塞げないのか。セキュリティ対策には、自動化できる"横"と、自動化できない"縦"があるからです。

横の対策(自動化できる)縦のリスク(検出・警告しかできない)
セキュリティヘッダー/CSP、レート制限、CSRF、入力検証、秘密情報の漏洩防止認可(IDOR/BOLA)、業務ロジックの欠陥、権限昇格
性質アプリ横断で一律に効くアプリ固有の「誰が何を所有するか」に依存
自動化ライブラリ/設定で塞げるライブラリには塞げない(あなたのデータモデルを知らない)

WAFがIDORを防げない理由は、この表に尽きます。GET /api/invoices/1025 というリクエストは、HTTPとして完全に正常です。認証ヘッダーも正しく、SQLインジェクションのような不正な文字列も含まれない。WAFから見れば、これは「正規ユーザーの正規リクエスト」です。それが攻撃になるのは、「1025番の請求書が、このユーザーの所有物ではない」という、アプリ固有の業務的事実による——そしてWAFはあなたのデータモデルを知りません。

同様に、セキュリティヘッダーやCSPはXSSやクリックジャッキングには効きますが、認可とは無関係です。RLSは必要不可欠ですが、第4節で見たとおり service_role 経路では飛び越えられ、さらにRLSが効かない領域(SECURITY DEFINER 関数、RPC、Storage、外部結合先のテーブル)も残ります。

結論はこうです。「何かを導入すれば認可が守られる」という製品は存在しないし、存在すると謳う製品はむしろ危険です。「入れたから大丈夫」という油断こそが、最悪のセキュリティ結果を生みます。認可は、セキュアな設計(RLS+コードの所有権チェック)と、それを裏付ける検証の両輪でしか守れません。自動化できるのは、設計の正しさを"検出・警告"するところまでです。


6. IDORを体系的に「発見」する——3層の検証

設計で塞ぐと決めたら、次は「塞げているか」をどう確かめるか。検証ファーストの原則に従い、3つの層で体系化します。1つの手段に頼らず、静的・構造的・動的を重ねるのがポイントです。

層1:静的解析(SAST)——コードのデータフローを追う

「クライアントが操作できる入力(route params、検索クエリ、リクエストボディ、Cookie)が、所有権で絞られないままDBクエリに到達していないか」を、関数内のデータフロー(taint解析)で追います。第4節の脆弱コードでいえば、「params.id.eq("id", ...) に渡るのに、.eq("user_id", ...)auth.uid() も経由していない」というパターンを機械的に拾います。

これは正規表現では構造的に書けません。"入力がどこから来てどこへ流れるか"を追う必要があるからです。私は自作のOSSスキャナ Aegis にこの検出を authz/idor-tainted-scope というルールとして実装しています。

# インストール不要・設定不要でスキャン
npx @aegiskit/cli scan

層2:SQL/RLSの検証——認可が"DBに"正しく宿っているか

コードと別に、supabase/migrations/**.sql を読んで認可の設計そのものを検証します。具体的には——RLSが無効のテーブル、WITH CHECK が無い書き込みポリシー、using (true) のような無条件許可、anon ロールへの過剰な権限、search_path を固定しない SECURITY DEFINER 関数(権限昇格の温床)。そして SQLとコードを突き合わせ、「RLSの弱いテーブルを、非管理クライアントから実際にクエリしている箇所」を確定した露出として指摘します。Aegisはこれも supabase/migrations を解析して行います。

層3:動的確認(DAST)——実際に"他人になって"叩く

静的解析は"疑う"ところまで。最後は自分が所有するアプリに対して、実際にIDORを再現して確定させます。やり方はシンプルです。

  1. テスト用に2つのアイデンティティ(ユーザーAとユーザーB)を用意する
  2. AでログインしてAのリソースID(例:請求書1024)を取得する
  3. Aのセッションのまま、Bのリソースを指すIDを叩く
  4. 200が返って他人のデータが見えたら、IDORが実行時に確定
# 自分のアプリに対する安全・非破壊なプローブ(所有権の食い違いを実行時に確認)
aegis probe http://localhost:3000 --correlate

静的解析の"疑い"と、動的の"再現"が一致したものは、**確定済み(confirmed-exploitable)**として最優先で直す。これがSAST↔DASTの相関です。加えて、RLSの退行を防ぐなら pgTAP でポリシーの回帰テストを書き、CIで「他人の行が見えないこと」を継続的に証明します。

正直なスコープ——ツールは"発見"を助けるが、"正しさ"は証明しない

ここは強調させてください。いかなる静的・動的ツールも、あなたの認可が正しいことを証明はできません。 ツールが見ているのはポリシーや実装の"形"であって、あなたの事業ルールやデータモデルの意味ではありません。クリーンな結果は「よくある罠は踏んでいない」であって、「認可が正しい」ではない。だからこの3層は、人間によるレビューと脅威モデリングを置き換えるものではなく、補完するものです。それでも、最頻出の穴を機械的に潰せる価値は計り知れません。検出が"歯"を持ち、ノイズを増やさず、人間が本当に難しい判断に集中できるようになります。


7. 発注者・チームのためのIDORチェックリスト

外注したコードでも、AIに書かせたコードでも、本番投入の前に最低限これだけは確かめてください。専門家でなくても判断できるよう、観点と確認方法をまとめます。

観点確認すること危険信号
RLSの有効化全テーブルでRLSが有効かenable row level security の無いテーブルがある
service_roleの所在service_role キーがクライアント/ブラウザに渡っていないかフロントのコードやネットワークタブに service_role が見える
service_role経路の所有権service_role を使うAPIで user_id 等の所有権条件があるかIDを受け取って .eq("id", ...) だけで返している
IDの差し替えテスト2アカウントで、他人のIDを叩いて弾かれるか別ユーザーのデータが200で返る
RLSが効かない領域RPC / SECURITY DEFINER 関数 / Storage / 結合先に穴が無いか「RLS張ったから安全」で思考停止している
検証の自動化スキャン・RLS検証・回帰テストがCIにあるか「手元で動いた」以外の検証根拠が無い

発注者の視点で最も効くのは、**「他人のIDを叩いたらどうなりますか?」「service_roleキーはどこで使っていますか?」**の2問です。明確に答えられないなら、認可の検証が設計に組み込まれていない可能性が高い。良い開発者は、これらに即答できます。


よくある質問(FAQ)

Q. 全テーブルでRLSを有効化すれば、IDORは防げますか? A. 多くは防げますが、不十分です。第4節のとおり service_role 経路はRLSを飛び越えますし、SECURITY DEFINER 関数・RPC・Storage・外部結合先など、RLSが直接効かない領域も残ります。RLSは"最後の砦"として必須ですが、コード側の所有権チェックと二層で守るのが正解です。

Q. service_roleキーは絶対に使ってはいけませんか? A. いいえ。管理処理やバッチでは正当な用途があります。鉄則は2つ——(1) サーバー側だけで使う(絶対にブラウザに出さない)、(2) 所有権をコードで必ず強制する。この2つを守れない経路では使わないでください。

Q. WAFやセキュリティヘッダーを入れれば足りますか? A. IDOR対策にはなりません。第5節のとおり、IDORは認証も書式も正しい"正規リクエスト"なので、WAFには攻撃と判別できません。それらはXSSやインジェクション等の"横"のリスクには有効で、認可とは別レイヤーの話です。両方必要ですが、片方がもう片方を代替することはありません。

Q. AIに「セキュアに書いて」と頼めば直りますか? A. 期待しすぎないでください。Veracodeの調査では、モデルが賢くなってもセキュリティの成績は横ばいでした。AIは"動くコード"の生成には強いが、"壊れない構造"を保証はしません。AIの速さを活かしつつ、検証ゲート(スキャン・テスト・レビュー)を通して初めて本番品質になります。

Q. 個人開発や小規模でも、ここまでやるべきですか? A. むしろAIで素早く作ったアプリこそ露出例が多い、というのがCVE-2025-48757などの示す現実です。最小構成でも 「全テーブルにRLS」+「service_role経路の所有権チェック」+「2アカウントでのID差し替えテスト1本」 の3点だけは必ずやってください。コストはわずかで、防げる事故の大きさは桁違いです。


まとめ:守りの境界は「RLSの有無」から「鍵と所有権の置き場所」へ

要点を整理します。

  • IDOR(OWASP API1:2023 BOLA)は、最頻出かつ最も深刻なAPIリスク。正規ユーザーがIDを書き換えて他人のデータに触れる、認可の失敗です。
  • AI製のNext.js × Supabaseコードでこれが量産されるのは、(1) RLS未設定の露出(2) service_roleキーによるRLSバイパス+所有権チェック忘れの2つの決まった失敗モードによります。CVE-2025-48757はその現実です。
  • service_role はRLSを完全に飛び越えるため、守りの境界は「RLSがあるか」ではなく、**「service_roleキーをどこに置き、所有権をどこで強制するか」**に移ります。
  • WAFやヘッダーでは防げません。 IDORは正規リクエストで、攻撃か否かはあなたのデータモデルだけが決める"縦のリスク"だからです。買って済ませることはできません。
  • 発見は3層で——コードのtaint解析、SQL/RLSの検証、実行時の確認。ただしツールは"発見"を助けるだけで、認可の正しさは設計と人間のレビューでしか守れない

この「RLSの外側に空くIDOR」は、私が自作のセキュリティツール Aegisnpx @aegiskit/cli scan)で検出対象にしているまさにそのクラスの欠陥であり、受託・自社開発の両方で実際に塞いできた領域です。AIで速く作ること自体は正しい。速く作ったものを、漏らさず安全に固める——その検証の仕組みづくりや、既存のNext.js × Supabaseアプリの認可レビューが必要であれば、お気軽にご相談ください。


参考資料

友田

友田 陽大

Entwickler eines mit dem METI-Ministerpreis ausgezeichneten Produkts. Mit TypeScript + Python + AWS liefere ich SaaS, Industrie-Digitalisierung und produktionsreife generative KI (RAG) durchgängig — von der Anforderung über die Infrastruktur bis zum Betrieb, allein.

The vulnerabilities in this article — is your app safe from them?

An expert audit of your Next.js × Supabase authorization & RLS

The IDOR, RLS misconfigurations, and tenant-boundary crossing covered here are vertical risks a library can't fix. I take it on as a security audit — from authorization review through fix design and implementation. You're welcome to visualize the current state with the free OSS first.

Verfügbar für Projektarbeit (Werkvertrag) und als technischer Berater. Beginnen Sie mit einem kostenlosen 30-minütigen Gespräch.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

Ebenfalls lesenswert