2026年7月25日、Redditユーザーが「site:claude.ai/share」でGoogle検索をかけると、他人が「共有」設定にしたClaudeのチャットやArtifactsが大量にヒットすることに気づいた。職務経歴書、財務スプレッドシート、患者名を含む医療相談、法律相談まで、本人が「リンクを知っている人だけに見せたつもり」だったやり取りが検索結果に並んでいた。Anthropicは7月28日までに大半の結果を検索エンジンから消したが、原因は特定の脆弱性ではなく、「robots.txtのDisallow」と「noindex」を混同した設計ミスだった。
この記事では事件の経緯そのものより、自分たちのプロダクトで同じ穴を作らないための実装に絞って解説する。共有リンク・招待リンク・プレビューURLなど「認証なしでアクセスできるがログインユーザー以外には見せたくないURL」を持つAIプロダクトを開発・運用しているエンジニア・PM向けの内容だ。事件の経緯や企業側のチェックリストは姉妹サイトUravationで別途扱っているので、詳しい時系列を知りたい人はそちらも参照してほしい。
0. まず結論: この3行をコピペして自分のプロダクトに当てはめる
共有URLを持つ機能を作るなら、最低限この3つを今すぐ確認する。
1. 共有ページの <head> に <meta name="robots" content="noindex"> があるか
2. HTTPレスポンスヘッダーに X-Robots-Tag: noindex があるか(HTML以外のファイルも含む)
3. robots.txt の Disallow と noindex を同じパスに「両方」設定していないか(併用すると noindex が読まれず無効化される)
3番が今回のClaude事件の核心であり、意外と見落とされがちなポイントなので、以降で仕組みから説明する。
1. 何が起きたか(最小限のまとめ)
報道されている技術的な問題点は次の通りだ。
- Claudeの共有チャット・Artifactsページ(
claude.ai/share/*)は、robots.txtでDisallowが設定されていた - しかし、そのページ自体には
noindexの指定がなかった、あるいはrobots.txtのDisallowと競合する形になっていた - ユーザーがSNSやフォーラム、社内Wikiなどに共有URLを貼ると、Googleは「そのURLへのリンクが外部に存在する」という事実だけを根拠にURLをインデックスできてしまう
- その結果、本文の中身までは読めなくても、URLと(外部サイトのアンカーテキストなどに基づく)断片情報が検索結果に表示されるケースが発生した
TechCrunchやFortuneの報道によれば、履歴書や財務データ、患者情報、子どもの氏名・電話番号を含むチャットまで見つかったとされている。Anthropicは「共有リンクは仕様上パブリックである」としつつ、noindexタグの追加とrobots.txtの見直しを急ぎ、Googleは7月28日までにインデックスから大半を除去したと報じられている。
2. なぜrobots.txtのDisallowだけでは守れないのか
ここが最も誤解されやすい部分だ。robots.txtの Disallow とHTMLの noindex は、似ているようでまったく別の役割を持つ。
| 指定方法 | 制御対象 | クロールとの関係 | 外部リンクがある場合 |
|---|---|---|---|
| robots.txt の Disallow | クローラーのアクセス(クロール) | クロールを止める | URLだけがインデックスされる可能性が残る |
| <meta name=”robots” content=”noindex”> | 検索結果への掲載(インデックス) | クロールできることが前提 | クロールさえ許せば確実に除外できる |
| X-Robots-Tag: noindex(HTTPヘッダー) | 検索結果への掲載(インデックス) | クロールできることが前提 | PDF・画像などHTML以外にも使える |
Google Search Central公式ドキュメントは、この関係を次のように明記している。
If the page is blocked by a robots.txt file or the crawler can’t access the page, the crawler will never see the noindex rule, and the page can still appear in search results, for example if other pages link to it.
つまりnoindexタグはクローラーがページを「読める」ことが前提で機能する仕組みだ。robots.txtでクロール自体をブロックしてしまうと、Googleはそのページの中にnoindexタグが書いてあることに気づけない。その状態で外部サイトからリンクされると、Googleは「本文は読んでいないが、このURLは存在する」という扱いでインデックス欄に載せてしまう。中身が読めないぶん、通常は表示されるはずのタイトルやディスクリプションが欠けた素っ気ない検索結果になるが、URLと外部の文脈情報だけは検索結果に出てしまう。
Search Engine Journalの分析でも、Claudeの事例は「robots.txtのDisallowとX-Robots-Tag: noneの両方を同じパスに設定し、ルール同士が競合していた」パターンだと指摘されている。Google側のSearch Advocateであるマーティン・スプリット氏も、この2つを同じページに重ねて設定することを避けるよう繰り返し呼びかけている。
3. noindexを正しく実装する4つの方法
共有ページを検索結果から確実に除外するには、「クロールは許可したまま、noindexで止める」のが正しい順序になる。フレームワーク・インフラ別に実装例を示す。
3-1. 素のHTML(<meta>タグ)
<!-- 共有ページの <head> に入れる。全ての検索エンジンに対して有効 -->
<meta name="robots" content="noindex, nofollow">
<!-- Googlebotだけを個別制御したい場合 -->
<meta name="googlebot" content="noindex">
3-2. Next.js(App Router)のMetadata API
// app/share/[id]/page.tsx
import type { Metadata } from 'next';
export async function generateMetadata(): Promise<Metadata> {
return {
robots: {
index: false,
follow: false,
},
};
}
App Routerのgenerate Metadata関数でrobotsフィールドを返すと、Next.jsが自動的に<meta name="robots">を生成する。動的ルートなら、共有トークンが「無効化済み」「期限切れ」の場合だけこのメタデータを返す、といった条件分岐も可能だ。
3-3. Node.js/Express(HTTPヘッダーで制御)
// 共有ページ配下すべてにX-Robots-Tagを付与するミドルウェア
app.use('/share', (req, res, next) => {
res.setHeader('X-Robots-Tag', 'noindex, nofollow');
next();
});
3-4. Nginx(HTMLとPDF等の非HTMLファイルを両方カバー)
location /share/ {
add_header X-Robots-Tag "noindex, nofollow" always;
}
X-Robots-Tagヘッダーの利点は、Google公式ドキュメントにもある通り「PDFや動画、画像ファイルなどHTMLの<head>を持たないリソースにも適用できる」点だ。共有機能がPDFエクスポートやスクリーンショット画像を生成する場合は、HTMLページだけでなくそれらのファイルにもX-Robots-Tagを付ける必要がある。
4. 「unlisted」と「private」は別物という設計原則
共有リンク機能を設計するとき、多くのチームが暗黙のうちに「URLを知っている人しかアクセスできない=安全」だと考えてしまう。これはYouTubeの「限定公開」に近い発想だが、限定公開動画ですら検索エンジンには出ないよう別途noindex相当の制御がされている。以下の3段階を区別して設計するのが安全だ。
- private(非公開):ログイン・認可トークンなしにはアクセス不可。検索エンジンにも一般ユーザーにも到達できない
- unlisted(限定公開):URLを知っていればアクセス可能だが、サイト内の一覧・サイトマップ・検索結果には出さない。noindexは必須
- public(公開):一覧にも検索結果にも出てよい。意図的な公開コンテンツ
Claudeの共有リンクは設計思想としては「unlisted」だったはずだが、実装上noindexが機能していなかったために「public」相当の露出が発生した。これは実装バグというより、「unlistedだからnoindexは省略していい」という思い込みが根本原因に近い。unlistedを名乗るなら、noindexの実装は機能要件のチェックリストに必ず含めるべきだ。
5. 共有トークンURLの設計チェックリスト
noindex以外にも、共有URL設計で見落とされがちな項目をまとめる。
| 項目 | 確認内容 |
|---|---|
| トークンの推測困難性 | 連番IDやUUID v1(時刻ベース)ではなく、UUID v4やCSPRNGベースのランダムトークンを使う |
| Referrerポリシー | 共有ページからの外部リンククリックでトークン付きURLがReferrerとして漏れないようReferrer-Policy: no-referrerを設定する |
| ログ出力 | アクセスログやAPMツールにトークン付きURLをフルで記録しない(末尾をマスクする) |
| 失効・無効化 | 共有者側が任意のタイミングでリンクを無効化できるUIを用意する |
| サイトマップからの除外 | 共有ページ用のURLパターンをsitemap.xml生成ロジックから明示的に除外する |
| キャッシュ・CDN | CDN側でX-Robots-Tagヘッダーが削られていないか(一部CDN設定でカスタムヘッダーが除去されることがある)を確認する |
6. 【要注意】ありがちな失敗パターン
- robots.txtのDisallowだけで満足してしまう:クロールを止めただけではインデックスを防げない。noindexとセットで初めて機能する
- DisallowとX-Robots-Tag: noindexを同じパスに両方設定する:クローラーがページを読めないためnoindex指定に気づけず、結果的にDisallowだけが効いてURLが露出したままになる
- HTML以外のファイル(PDF、画像、CSV出力)にnoindexを付け忘れる:metaタグはHTML専用なので、非HTMLリソースにはX-Robots-Tagヘッダーが必須
- CDNやリバースプロキシでヘッダーが上書き・削除される:アプリ側で正しく設定していても、CDN設定やキャッシュルールでX-Robots-Tagが消えていることに気づかないケースがある
- 「まだインデックスされていないから大丈夫」という判断:外部リンクが増えた瞬間にインデックスされる可能性があるため、公開直後の一時的な無事故は保証にならない
7. 自社プロダクトの共有リンクを今すぐ監査する方法
共有URLを持つ機能があるなら、以下のコマンドで自分のプロダクトの状態を今すぐ確認できる。
#!/bin/bash
# 共有ページのURL一覧を share_urls.txt に1行ずつ書いて実行
# X-Robots-Tagヘッダーとmeta robotsタグの両方をチェックする
while read -r url; do
header=$(curl -sI "$url" | grep -i "x-robots-tag")
meta=$(curl -s "$url" | grep -io '<meta[^>]*name="robots"[^>]*>')
echo "URL: $url"
echo " X-Robots-Tag header: ${header:-'(なし)'}"
echo " meta robots tag : ${meta:-'(なし)'}"
echo "---"
done < share_urls.txt
さらに、Google Search Consoleの「URL検査」ツールで共有ページのサンプルURLを1件検査し、「インデックス登録されていません」の理由が「noindexタグ」または「未検出(Discovered – currently not indexed)」になっているかを確認する。「robots.txtにより除外」と出ている場合は、この記事の2章で説明した競合状態が起きている可能性が高い。
すでにインデックスされてしまった場合は、noindexの実装後にSearch Consoleの「削除」ツールで一時的な非表示リクエストを出しつつ、正式な除外はGoogleがページを再クロールしてnoindexを認識するまで待つ必要がある(Disallowを外してクロールを許可しないと、noindexにすら気づいてもらえない点に注意)。
よくある質問
Q. noindexタグだけ入れておけば、robots.txtのDisallowは不要ですか?
A. 共有ページを「検索結果に出したくないが、ログイン外の第三者はURLを知っていればアクセスできる」状態にしたいなら、robots.txtでのDisallowは設定せず、noindexタグ(またはX-Robots-Tagヘッダー)だけを使うのが正しい。Disallowを併用するとクローラーがページ内容を読めなくなり、noindexの指定自体が無視されてしまう。
Q. すでにGoogleにインデックスされてしまった共有ページはどう対処すればいいですか?
A. まずrobots.txtでDisallowされていないか確認し、されていれば解除してクロールを許可する。その上でnoindexタグ・X-Robots-Tagヘッダーを設定し、Google Search Consoleでの再クロールを待つ。緊急性が高い場合は、Search Consoleの「削除」ツールで一時的に検索結果から除外するリクエストを併用する。
Q. Bing など Google 以外の検索エンジンにも同じ対策で効きますか?
A. <meta name="robots" content="noindex">とX-Robots-Tagヘッダーは検索エンジン共通の標準的な指定方法で、Bingを含む主要な検索エンジンが尊重する。Googleだけを個別制御したい場合に限りname="googlebot"を使う。
参考・出典
- Google Search Central「Block Search indexing with noindex」公式ドキュメント
- Search Engine Journal「Indexed Claude Chats Show Why Disallow Is Not Noindex」
- Search Engine Land「Google indexed Claude chats because Anthropic didn’t block your private chats from search engines」
- TechCrunch「PSA: Your Claude shared chats and Artifacts may have ended up on Google」
- Fortune「Users’ seemingly private conversations with Anthropic’s Claude showed up in Google search results」
- Next.js公式ドキュメント「generateMetadata」
※本文中の統計・引用は2026年7月30日時点の各社報道・公式ドキュメントに基づく。
著者プロフィール
佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。早稲田大学法学部在学中に生成AIの可能性に魅了され、X(旧Twitter)で活用法を発信(@SuguruKun_ai、フォロワー10万人超)。100社以上の企業向けAI研修・導入支援を展開。著書累計3万部突破。
共有リンクの設計だけでなく、AIエージェント導入全体のセキュリティ設計・権限設計を見直したい方へ。
関連記事: AIエージェントを守るプロンプトインジェクション対策 / RAGのデータセキュリティ実装ガイド(PII・アクセス制御)
UravationではAIエージェント導入の研修・コンサルを行っています。今回のようなプロダクト設計上の見落としを防ぎたい開発チーム・PMの方はお気軽にご相談ください。
