SESSION 04 / 06

F12を押せば
全部見える

F12・6つの防御線・セキュリティ監査・account.md

Jee Jun Young

非情報系(経営学科)→ 記者・海外営業 → 開発者に転向
iOS・Android・フロントエンド 約5年半(6年目)
大企業向けコラボレーションツールのiOS/macOSアプリ開発
2026年〜 バイブコーディングでWeb・サーバーを一人で開発・事業化

PART 1 — 第3回の復習

今日は少し
怖い話をします。

WHY WEB IS WILD

Webとサーバーは野生の世界です

私もセキュリティ担当者は怖いです。私はセキュリティの専門家ではありません。

モバイルとWebでは、開発者が責任を持つ範囲が違います

iOS · Android
AppleとGoogleが半分は防いでくれる

Sandbox・Code Signing・ATS・Keychain・アプリストア審査 — OSとプラットフォームによる基本的な保護

Web・サーバー
すべて開発者の責任

HTTPS・CORS・CSRF・XSS・SQL Injection・DDoS・サーバーOS・認証と認可 — すべて自分で

WebはAIが最も多く学習した分野

AI
平均的なものは本当にうまく作ります

ログイン・掲示板・ダッシュボード — 学習分布の平均値。機能を動かすのは得意です。

ハッカー・ボット
平均の外側を突いてきます

エッジケース、異常な入力、特殊な条件。学術用語ではadversarial robustness

気を配ればうまく動きます。放置すれば破綻します。
今日の6つの防御線は最低限押さえること。

EDGE CASE・決済

平均から完全に外れる代表例 — 決済の導入

「5分でできる?チュートリアルどおりにしたら動いた?」

やってみてください。売上がなければ気付かず、廃業してそのまま終わるかもしれません。
売上が増え、標的になってから知ることになります。

決済は無数の手順と分岐が何層にも積み重なる、最も複雑な機能です。
層どうしに矛盾があってはいけません。AIの平均的なコードがほとんど扱わないエッジケースが爆発的に増えます。

冪等性 原子性 並行性 Webhook検証 金額検証

なぜ怖いのか — 身近な2つの例

• iOSアプリ内課金 — かつてゲーム会社を苦しめた領域。Appleの30%手数料・自動更新・返金・レシート検証……
• 中小企業の顧客対応 — 決済事故では怒りが直撃します。「俺の金はどこへ行った」という暴言、星1つの評価が殺到し、1か月で評判が崩れます。

講師自身の悩み

決済 — 今、私が一番悩んでいる部分

講義で小説を投稿するサービスを何度かお見せしましたよね。

今、一番悩んでいるのがこれです。
決済機能の攻撃ポイントを守ること。

F12 · DEVTOOLS

F12はブラウザーのX線です。

Chromeなら、どのページでも右クリック→検証。
またはClaudeに「私のパソコンはWindows?Mac?Web開発者ツールはどう開くの?」と聞いてください。

Networkタブに見えるもの

APIの呼出し先・リクエスト内容・レスポンス内容
使用中のAIモデル・環境変数・localStorage・Cookie
すべて公開状態です。

病院のX線で骨が見えるのは正常です。
自分のパソコンで確認するのもハッキングではありません。

問題は誰でも開けることです。
ブラウザーは開発者とハッカーを区別しません。

TWO RISKS

F12で見えることが危険な2つの理由

危険①
利用者が被害に遭う
メール・決済・個人情報が漏れる。
セキュリティとお金に直結します。
このあと3件の事故で示します。
危険②
自分が被害に遭う
AIモデル・プロンプト・ロジック
核となるレシピが全部露出。
競合が週末のコピペで複製します。

F12は利用者を守る問題であり、同時に
自分のアイデアを守る問題です。

ANALOGY

本当のセキュリティは「持ち去れるか」

部屋の引き出しのたとえ

自分の部屋で日記を取り出すのは事故ではありません。
本当の事故は泥棒が窓を割って盗めるままに放置することです。

遊園地のリストバンド — どこに保管するかがすべて

A. 共用テーブル
localStorage
外に出してはいけないキーや認証情報を全部置くと、泥棒がすぐ持ち去る
B. 銀行の金庫
HttpOnly Cookie
X線では見えるが、取り出せない

同じリストバンドでもどこに置くかで変わります。

「泥棒」の正体はXSS攻撃者

ページに悪意あるJavaScriptが埋め込まれた状態(Cross-Site Scripting)。
localStorageは同一ドメインのJSからすべて読める→悪意あるスクリプトがトークンを盗む。
HttpOnly CookieはJSからそもそも見えない→盗めない。HttpOnlyの役目は、XSSが起きてもトークンを盗ませないこと。

PART 2

10秒の攻撃
実際の事故3件

ハッカーが個人開発者のサイトを荒らすのに
10秒もかかりません。

INCIDENT 01

EnrichLead — 2日間の攻撃、1週間で廃業

問題 — 4つの基本防御がすべて欠如

創業者が「1行も書いていない」と自慢したB2BリードSaaS。
APIキーがフロントに露出、認証なし、DB無防備、レート制限なし。

攻撃経路

ブラウザーコンソールで決済を回避→有料機能を無料利用→APIキーの利用枠を消費。
Cursorで修正を試みる→「別の部分を壊し続けた」→断念して廃業。

KEY TYPES・2種類を区別

公開キー(Public)
アプリやブラウザーに埋め込んでよい
Firebase apiKey・Google Maps・Stripe pk_*・Supabase anon
→ ただし制限とポリシー(Security Rules・App Check・Restrictions)は必ず有効にする。
シークレットキー(Secret)
クライアントには絶対に置かない
Anthropic sk-ant-*・OpenAI sk-*・Stripe sk_*・Supabase service_role
→ 必ずバックエンドの環境変数に置く。

自己診断:「このキーが漏れたら、誰でも呼び出して課金や権限取得ができるか?」YES→シークレット。NO→公開。

教訓:シークレットキーは安全な場所へ。
Web・サーバー構成ならバックエンド環境変数に隔離。iOS・Androidアプリは自前のバックエンドを経由して呼び出す。公開キーは埋め込んでよいが、ポリシーは必須。

INCIDENT 02

Moltbook — APIキー150万件が流出

事故の経緯 — 二重のミス

創業者Matt Schlichtが「1行も書いていない」と宣言したAIエージェントのSNS。
Supabaseを使用し、RLS無効+権限付きキーがクライアントJSに露出。
→ anonキー自体は公開してよい。RLS無効とシークレットキー露出の組合せが事故の原因。

結果:APIキー150万件・メール3.5万件・エージェントの個人会話すべてが流出。
セキュリティ企業Wiz Researchが調査結果を公開。

教訓:Supabase RLS・Firebase Security Rulesは必ず有効にする。
毎回Claudeに確認させる。

INCIDENT 03

Teaアプリ — 画像7.2万件+メッセージ110万件

1回目の流出(2025年7月)

女性専用アプリ。登録時に運転免許証とセルフィーを収集。
Firebase Storageを誰でもアクセスできる権限のまま放置。
画像7.2万件が流出。運転免許証を含むセルフィー約1.3万件。

2回目の流出(数日後)

さらに個人メッセージ110万件が流出。
中絶の相談や不倫の悩みなど、極めて機微な会話も含まれていた。

教訓:ファイルアップロード機能があるなら
Storageの権限を必ず確認する。

KBS「窓」第540回・見るべき2つの場面

番組は完成した結果だけを見せます

「私の完璧な秘書・AIエージェントの時代」・youtu.be/QQJpyIO014A

場面①・動画の導入部 — ドキュメンタリーの主人公

セキュリティ系スタートアップCEO・バリ在住・1日30分勤務・エージェントの結果だけを承認

その人がそこに至るまで、推測するしかない4つのこと —

Q1
どれほどの研究開発?
Q2
どれほど学んできた人?
Q3
どれほどの試行錯誤?
Q4
月のトークン代は数千万ウォン?

(参考までに、Palantir Enterpriseに月2千万ウォン以上払う会社もあります。)

場面②・28~32分

ホテル予約エージェントに「50万ウォンだけ使え」と指示した結果、76万ウォンに。

KAISTの研究者とKBSスタッフが作った管理下の攻撃実験。外部Webページに埋めた攻撃用コードとプロンプトでエージェントを誤作動させるシナリオです。実際の被害者ではありません。

講師の前職は雑誌記者(第1回に紹介)。メディアの見せ方は編集部の意図の結果です。

家で動画を見ながら2つ確認してください。
① CEOの努力・勉強・試行錯誤・費用は画面に出ていますか?
② 攻撃の仕組み(アテンション・ツール呼出し・判断・IDPI)は明確に説明されていますか?

出ていなければ編集で切られたもの。それがメディアの本質です。

決定的な問いは
「自分が作るサービスは、その攻撃を防ぐ準備ができているか?」

PART 3

基本の防御線
6つ

覚える必要はありません。写真を撮ってください。
Claudeに「これも一緒に」と一言添えるのがポイントです。

TODAY · 6 BASIC DEFENSES

基本の防御線6つを一覧で

① データベース
RLS(Row Level Security)を有効にする

DBの1行ごとに誰のものかを示す→自分の行だけ読み書き。
例:「自分の投稿は自分だけ、他人の投稿は見えない」
Supabase・FirebaseはデフォルトOFF。有効にしなければ誰でも全行にアクセスできます。

② キー管理
APIキーをコードに埋め込まない

埋め込んだキーはGitHubに上がった瞬間に全世界へ露出。.envに分けます。

③ 環境変数の露出
NEXT_PUBLIC_に注意

NEXT_PUBLIC_・VITE_・REACT_APP_が付いたキーはバンドルに埋め込まれブラウザーに露出します。

④ AIを呼び出す場所
AIはサーバーから呼ぶ

OpenAI・Anthropicのキーをクライアント(ブラウザー・アプリ)に置いて呼ぶと即座に盗まれます。BFF/API Proxyパターン。

⑤ ビルド成果物
Source Mapを無効にする

本番で.mapが露出すると難読化コードから原本を復元できます。productionBrowserSourceMaps: false

⑥ Gitの管理
.gitignoreに.env

誤って.envをコミットすると、push後30分以内にボットがキーを自動収集します。

この6つを1つずつ見ていきます。

IF YOU SKIP — WORST CASE

6つともやらなければ何が起こるか

💰 お金
「数千万ウォン飛ぶのは珍しくありません」

APIキー露出→ボットが30分以内に収集→OpenAI・AWSの請求が急増。
1か月で数千万~数億ウォンもあり得ます。

📋 法的責任
「顧客情報が盗まれたら訴えられる」

韓国の個人情報保護法違反→売上の最大3%の課徴金+被害者1人ごとの損害賠償。
集団訴訟では零細事業者の経営者個人も破産し得ます。

🔒 人質
「DBが破られたらデータが人質」

ランサムウェアがDBを暗号化→ビットコインの身代金を要求。
バックアップがなければ事業終了。世界の平均身代金は80万~150万ドル。

📉 評判
「評判崩壊→売上ゼロ」

星1つの評価が殺到し、X(Twitter)で晒される→1か月では信頼を取り戻せない。
「あのサイトで決済事故があったらしい」の一言で売上ゼロ。

この4つは6つの防御線のうち1つ欠けるだけでも起こります。
身の破滅。大げさではありません。実例は毎週出ます。

DEFENSE 01
Supabase RLS・Firebase Security Rulesを有効にする
ダッシュボードに警告⚠️が出たらすぐ有効にします。
# Claudeに一言追加 「テーブルを作って、RLSポリシーも一緒に作って」

テーブルごとのRLSポリシーと実際のアクセス権限を一緒に確認します。

RLSを簡単に

RLSとは? — マンションの郵便受け

たとえ

マンションの1階に100世帯分の郵便受けがあります。
「自分の郵便受けは自分だけが開けられる」のが正常。
→ RLS有効=正常

有効にしなければ?

住民なら誰でも100世帯分の郵便受けを開けられる。
隣人の通帳、カード請求書、書留郵便まで読めます。
→ Supabase・FirebaseはデフォルトOFF。有効にしなければ誰でも全利用者のデータを読み書きできます。

RLS=「このデータの1行は所有者だけが開けられる」
一言でいうと、郵便受けごとに鍵を付けること。

DEFENSE 02
APIキーをコードに埋め込まない
基本は.envファイルとホスティング管理画面の環境変数。
# .env(Gitには上げない) OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-... # コードでは変数を使う process.env.OPENAI_API_KEY

Vercel・Netlifyでは管理画面の「環境変数」欄に入れれば大丈夫です。

APIキーを簡単に

シークレットAPIキーとは? — ホテルのマスターキー

たとえ(シークレットキーのみ)

ホテル従業員のマスターキーは全客室を開けられます。
OpenAI・Anthropic・AWSのシークレットキーも同じ。「このキーさえあれば、その会社のサービスを自由に使える」
→ 利用料はキーの持ち主である自分に請求。公開キーは別種です。S10の分類を参照。

コードに埋め込むと?

ホテルの正面玄関にマスターキーを鍵もかけず掛けておく状態。
通行人が外して全客室を開け、ミニバーや金庫を荒らせます。
→ GitHubにキーが上がると30分以内にボットが収集→OpenAIの請求が急増し、1か月で数千万~数億ウォン。

コードに埋め込まず、.envという別ファイルに分けます。
.envは絶対にGitに上げないこと(次のスライドで)。

DEFENSE 03
NEXT_PUBLIC_という接頭辞に注意
この接頭辞は「世界に公開」の意味です。
❌ 危険
NEXT_PUBLIC_OPENAI_KEY
ブラウザーにそのまま露出
✓ 安全
OPENAI_KEY
サーバーにのみ存在

EnrichLeadの事故は、まさにこのミスでした。

他のフレームワークも同じです。VITE_(Vite)・REACT_APP_(CRA)。名前が違っても「クライアントに露出」は同じ。

公開キーには付けてよい

Firebase apiKey、Stripe pk_*、Supabase anonなどの公開キーにはNEXT_PUBLIC_*・VITE_*を付けてよいです。もともと公開を想定したキーだからです。
→ シークレットキーには絶対に付けない。S10参照。

NEXT_PUBLIC_を簡単に

NEXT_PUBLIC_とは? — 店の看板と店主の金庫

たとえ

店には2種類の文字があります。
看板は通行人も読める(電話番号・住所・メニュー)。
店主の金庫の中は従業員も見られない(現金・印鑑・通帳)。
→ NEXT_PUBLIC_付きのキーは看板の文字。ビルド時にそのままブラウザーへ出ます。

誤ってシークレットキーに付けたら?

金庫の暗証番号を看板に書くようなもの。
OpenAI sk-*・Supabase service_roleなどのシークレットキーにNEXT_PUBLIC_を付けると、F12一発で泥棒の手に。
→ VITE_・REACT_APP_も同じ原理。他のフレームワークにも同じ罠。

規則:接頭辞は「クライアントへ出る」という印。
→ ここには公開キーだけ(Firebase apiKey、Supabase anon、Stripe pk_*)。シークレットキーは不可。金庫の暗証番号を看板に書くことになります。

DEFENSE 04
AIはサーバーから呼ぶ
BFFプロキシパターン — 自分のサーバーが中継します。
ブラウザー→自分のサーバー(API Route)→OpenAI API ↑ APIキーはここだけで使用

Claudeに「サーバー側のAPI Routeから呼んで」と必ず添える

PLATFORM・プラットフォーム別の適用

Web
Next.js · Vite · Nuxt
→ サーバー側API Route(Next.jsの/api/*、Viteは別途Express・Hono・Vercel Functions)からのみ呼ぶ。キーはバックエンド環境変数へ。
iOS
Swift · SwiftUI
アプリにキーを埋め込まない(IPAの逆コンパイルで抽出される)。自前のバックエンド経由で呼ぶ。Keychainにはユーザートークンだけを保存。
Android
Kotlin · Jetpack
アプリにキーを埋め込まない(APKの逆コンパイルで抽出される)。自前のバックエンド経由で呼ぶ。Keystoreにはユーザートークンだけを保存。

→ 共通原則:シークレットキー(OpenAI・Anthropic・Stripe `sk_*`・Supabase service_roleなど)は必ず自前のバックエンドだけで使う。ユーザー認証トークン(JWT・OAuth)はOSのKeychain/Keystoreへ。この3つは別の種類です。

よくある混同:「FirebaseはInfo.plistにキーを入れるように言っていたけど?」

そのとおり。FirebaseのapiKeyは公開キーで、それ自体に権限はありません。だからアプリに入れてよいのです。
本当の防御はFirebase Security Rules+App Check。Google Mapsキー・Stripe `pk_*`・Supabase `anon`も同様です。

→ S10の公開キーとシークレットキーの表を思い出してください。シークレットはバックエンド、公開キーはアプリでよいがポリシーの有効化は必須。

BFFを簡単に

BFFとは? — 客/従業員/店主

たとえ — 飲食店

客=利用者(ブラウザー)
従業員=自分のサーバー(BFF・Backend For Frontend)
店主=外部API(OpenAI・銀行・決済)
→ 客が店主の事務所に入り金庫に触れてはいけません。従業員が客の依頼を店主に伝えます。

客が店主に直接会うと?

客が金庫の暗証番号(APIキー)を知ってしまいます。
その客は別の客のふりをして毎日来店し、金庫を荒らします。
→ クライアントからOpenAI・銀行を直接呼ぶとAPIキーが露出。ボットが収集して請求が急増します。

規則:客は従業員だけに会う。従業員が店主へ伝えます。
つまりAI・決済・DBの呼出しは必ず自分のサーバー(BFF)から。クライアントは不可。

DEFENSE 05
本番のSource Mapを無効にする
有効だとF12で元のコードがそのまま見えます。コメントまで。

Source Mapとは?

自分のコード(TS・JSX・最新JS)→ビルドツールが圧縮・変換・1つにまとめる4段階の処理→ブラウザーへ送ります。変換後のコードは人には読めません。

デバッグのため、ビルドが原本と圧縮版の対応表を別途作ります。それが.mapファイル、Source Mapです。

たとえ:韓国語の本の英訳版に付く対照表。英訳に誤字があったとき、原文のどこかを探す辞書です。

同じ関数:原本とビルド後(人が書いたものとブラウザーに届くもの)

// 原本 function calculatePriceWithVAT( basePrice, additionalFee) { // VAT 10%を適用 return basePrice*1.1+additionalFee }
// ビルド後(圧縮) function n(a,b){return a*1.1+b} // 1行、変数名は1文字。 // コメントはすべて消える。

Source Mapを有効にして公開すると、F12に左側の原本がそのまま表示されます。関数の役割、業務ロジック、コメントまで露出します。

DEFENSE 05・設定と公開される理由

Source Map — 1行の設定と、他社では?

// next.config.js — 1行 module.exports = { productionBrowserSourceMaps: false } // Viteはbuild.sourcemap: false

Source Mapが公開される場合

①

ビルド設定を確認していない場合

②

クライアントコードの公開を許可した場合

③

本番エラーを原本コードで追跡する場合

④

オープンソースとしてコードを公開した場合

⑤

主要なロジックをサーバーに置いた場合

自分のプロジェクトで原本コード・コメント・主要ロジックが公開されていないか確認してください。

Claudeに:「このプロジェクトの本番ビルドでSource Mapが公開されていないか確認して」

ADVANCED・高度な選択肢

hidden-source-map — 安全性とデバッグを両立する標準パターン

2つの選択肢

① 完全に無効化(`sourcemap: false`):最も安全ですが、本番エラーの追跡は難しくなります。
② hidden-source-map:生成はするがsourceMappingURLコメントを付けない。一般利用者のF12には見えません。

hidden-source-mapの仕組み

生成された.mapをサーバー配信に含めず、Sentry・Datadogなどのエラー追跡サービスへ別途アップロード。
→ 本番エラーをSentryの画面で原本の行まで追跡できますが、F12からは見えません。

フレームワーク別の設定

Next.js — productionBrowserSourceMaps: false+Sentry連携
Vite — build.sourcemap: 'hidden'
Webpack — devtool: 'hidden-source-map'
CRA — GENERATE_SOURCEMAP=false(CRAはhidden非対応)

一言で:完全無効化が最も安全。hiddenは安全性とデバッグを両立します。
規模が大きくなりSentry・Datadogを使うときにhiddenへ移行します。

Source Mapを簡単に

Source Mapとは? — 建物の設計図

たとえ

完成した建物を外から見るだけでは、換気口・秘密通路・金庫の場所は分かりません。
設計図があれば、どこに何があるか分かります。
→ Source Mapは圧縮コードと原本の対応表。あればF12で原本が見えます。

設計図を外部に公開すると?

泥棒が建物中の換気口・秘密通路・金庫の場所を知ります。
外観は同じでも侵入経路が無数になります。
→ 本番で.mapを公開すると業務ロジック・安全性の検証コード・コメントがすべて見え、弱点がすぐ見つかります。

規則:建物が完成したら設計図は会社の金庫へ。外部公開しない。
productionBrowserSourceMaps: falseの1行です。

DEFENSE 06
.gitignoreに.envを入れる
Gitに上がると1分以内にハッカーボットが検知します。
# .gitignore .env .env.local .env.*.local

誤ってコミットした場合、Git履歴に残ります。
すぐキーを再発行してください。

Git・.gitignore・.envを簡単に

Gitとは? — 日記のバックアップ

たとえ

Git=日記の自動バックアップ(毎日写真を撮りクラウドに保存)
.env=秘密の日記(パスワード・口座の暗証番号・誰かの悪口)
.gitignore=「これはバックアップしない」一覧
→ Gitは全ファイルを自動でクラウドへ上げます。秘密の日記は.gitignoreに書いておかないと上がってしまいます。

.gitignoreに書かなければ?

秘密の日記までクラウドに自動保存されます。しかも履歴に永久に残ります。一度上がったパスワードはすぐキーを再発行。
→ GitHubに.envを誤コミットすると30分以内にボットがキーを収集。AWS・OpenAIの請求が急増。あとから削除しても履歴に残ります。

規則:.gitignoreに.env・.env.local・.env.*.localを必ず追加。
新規プロジェクトで最初に行うこと。

6 DEFENSES — CHECKLIST

01
RLSを有効にする
02
APIキーをコードに埋め込まない
03
NEXT_PUBLIC_に注意
04
AIはサーバーから呼ぶ
05
Source Mapを無効にする
06
.gitignoreに.env

この6項目で
キーの露出・DB権限・ファイルへのアクセス権限を確認します。

KEY MANAGEMENT・まとめ

サービスを動かすたくさんのキーをどう区別し管理するか?

1つのサービスにSupabase anon・Firebase apiKey・OpenAI sk-・Stripe pk_/sk_・Google Maps・Anthropic sk-ant-……キーだけで5~10個は普通です。

① 比較的公開された場所に書いてよい
公開キー(Public)

Firebase apiKey・Google Maps・Stripe pk_*・Supabase anon
→ 識別用。それ自体に権限や課金はありません。

② 絶対に公開してはいけないキー
シークレットキー(Secret)

Anthropic sk-ant-*・OpenAI sk-*・Stripe sk_*・Supabase service_role
→ バックエンド環境変数だけに置く。

簡単な自己診断:「盗まれたら自分に請求が来るか?DBに侵入されるか?」

YES→シークレット。バックエンドのみ。 |  NO→公開。クライアントでよいが追加防御は必須。

公開キーを安全に使う追加防御

① ポリシー(RLS/Security Rules)

DBの行・文書ごとに「この利用者は自分のデータだけ」。Supabase RLS・Firebase Security Rules。

② ドメイン・バンドル制限

Application Restrictions:Google Mapsキーを自分のドメイン・バンドルIDからだけ使えるようにし、他からの利用は拒否。

③ App Check/呼出し元の確認

Firebase App Checkで本当に自分のアプリからの呼出しか検証。ボット・スクレイピングを遮断。

シークレットキーは必ず.envに分け、.gitignoreに登録し、バックエンド環境変数だけに置く。

一言で:公開キー+ポリシー=安全。公開キーだけでポリシーなし=大惨事。
キーを置いて終わりではありません。ポリシーを有効にすることが安全対策の半分です。

☕

10分休憩

戻ってきたら
「Claudeは忘れる」という話をします。

PART 4

Claudeは忘れる
+AIでAIを監視する

TODAY・10原則に2つ追加

後半で10原則のうち2つを追加します。

07
基礎知識は追及の武器だ
08
自分で作って初めて限界が見える

この2つは後半で解説します。

まずはClaudeの「記録しました」という嘘と、account.mdでの対処から。

PART 4 — CLAUDE FORGETS

「記録しました」を信じるな。

講師の実体験

Claudeに「これを記録しておいて」と指示。
「はい、記録しました」と返答。
次のセッションで聞くと知らない。実際は記録していないことが頻繁にあります。

Claudeはセッションごとに最初から始まります。
記憶がありません。第3回で話しましたね。

さらにひどい場合

ひどいと同じセッション内でも2時間前の話を覚えていません。
→ コンテキストが長いほど前半が曖昧になります。第3回のContext Rotそのものです。

Claudeが「記録した」と言ったら必ず確認。
大切なことは自分で書いておきます。

解決策:人間が自分でメモする

account.md(.gitignoreに追加)

キーの発行元・クラウドのアカウントメール・インフラ設定値・コンテナー名
パスワードは絶対に入れない

# CLAUDE.mdに追加するセキュリティ欄 ## セキュリティ規則 - .envは絶対にGitへコミットしない - APIキーはサーバー側でのみ使う - SupabaseテーブルのRLSを有効に保つ - この規則に違反したらすぐ知らせること

規則が増えたら別ファイルへ

セキュリティ規則が長くなったらSECURITY.mdに移し、CLAUDE.mdには参照だけを置いてもよいです。
→ 第3回の正本と参照のパターン。CLAUDE.mdは短く、詳細は別ファイルへ。

第3回の正本の考え方をセキュリティに適用。Claudeが毎セッション規則を読み、認識します。

PART 5

AIに
セキュリティ監査をさせる

第2回の原則は文書化・監視・追及。
セキュリティでは特に監視が中心です。

AUDIT PROMPT

監査プロンプト:そのままコピペ

このプロジェクト全体をセキュリティの観点で監査して。 次を確認: 1. RLSが無効なSupabaseテーブルや空のFirebase Security Rulesがないか 2. .envがGitにコミットされていないか 3. クライアントコードにシークレットキー(sk-/sk_/service_role)が埋め込まれていないか 4. 機密値にNEXT_PUBLIC_が付いていないか 5. 有料AI APIをサーバーでなくクライアントから呼んでいないか 6. 本番ビルドでSource Mapが公開されていないか

Claudeの監査結果をGemini・Codexへ再度渡す。
同じAIが自分のコードを監査すると「問題ありません」となります。Geminiが報告書に意見を出し、次の手順をうまく示すことも多いです。
要点は相互検証。

これで終わりではありません

Webとバックエンドが守るべき項目は膨大です。
この6つは出発点。OWASP Top 10・トークン保存場所・CSP・CORS・Rate Limit・SQL Injection・CSRF・SSRF・Race Conditionと際限なく続きます。
→ 今日の6つはバイブコーダーが最もよく忘れる項目です。

REAL・講義直前の外部点検

さらに一歩:外側から点検した結果です

S36は自分のコードの静的解析用。これは別です。サイト1ページだけを見た外部からの実行時点検(トークン保存場所・レスポンスヘッダー・公開経路)。

対象:韓国のAI文章作成SaaS・ツール:Claude Chrome MCP・指示は「セキュリティ監査して」の一言・匿名化済み

① 認証トークン:localStorageに保存

キーは*_token、JWT形式、120文字。
→ 第4回の中心的なアンチパターン。F12一発で誰でもトークンを確認できます。

② トークンをデコード:有効期間24時間

HS256、payloadはsubとexpのみ(iat・jti・iss・audなし)、24時間後に失効。
→ 標準的なaccessは15分~1時間。24時間+jtiなしは盗難時に強制失効できず24時間使い放題。

③ セキュリティレスポンスヘッダー:5つ欠落

CSP・X-Frame-Options・X-Content-Type-Options・Referrer-Policy・Permissions-Policyがすべてなし。
→ HSTSだけ有効。CSPが1行あればXSSのインラインスクリプトを止められたはずですが、防御層ゼロ。

④ 多数の外部サービス+CSPなし=供給網攻撃の範囲が拡大

GTM・GA・複数の外部CDNを読み込み。CSPがないため、そのドメインが侵害されるとサイトの全利用者へ悪意あるコードが広がり得ます。

決済を受ける正式サービスが第4回のアンチパターンをほぼ全部備えた状態で運用中。
まだ被害に遭っていないだけで、侵入されやすい状態です。

PRECISELY・正確に言うと

① トークンをlocalStorageに置くことだけなら議論の余地がある

トークンの保存場所とCSP・XSS対策を一緒に検討する必要があります。

② 組合せ(localStorage+CSPなし+24h+jtiなし) — 一緒に確認する項目

CSP・トークンの有効期限・再利用防止を一緒に確認する必要があります。

③ 一言で

localStorageに危険な値(認証・決済・個人識別情報)は絶対に置かない。
ダークモード・言語・UI状態はよい。機密は不可。

④ このサービスは

後者の②の組合せに近い。
localStorageだけを見て批判しているのではなく、組合せが危険です。

SO — 最低限だけでも

だから最低限のセキュリティは必要です

1つ目:できないのではなく、やっていない

Vite+React+Vercelできれいに作った人たちです。頭のよい人たちです。
認証トークンをHttpOnly Cookieに入れる5分の作業をしていなかった。

2つ目:1兆ウォン企業もやっていない

EnrichLead・Moltbook・Teaはすべて決済を受けていた会社です。
最低限も押さえず、1度の事故で1週間で廃業(EnrichLead)。

3つ目:皆さんも同じ脅威の中にいる

バイブコーディングで決済を付け、利用者を受け入れた瞬間、F12一発ですべて見えます。

最低限=6つの防御線+account.md+監査プロンプト。
この3つは必須。再起不能の事故は1度で終わりです。

最後に一言

私の指示は韓国語で「セキュリティ監査して」の一言でした。
Claudeはその一言でここまで見つけました。

では攻撃に長けた人が同じサイトを狙ったらどうなるでしょう?

TEST

テスト:機械が機械を監視する

ユニットテスト・E2Eテスト・UIテストは今覚えなくて大丈夫です。
簡単にいうと自動検証プログラムです。

従来の開発では開発者が書きます。
バイブコーディングではClaudeに頼めばよい。

一言:「この機能のテストファイルも一緒に作って」

MARTIN FOWLER · 1999

「どんな愚か者でも
コンピューターが理解できるコードは書ける。
優れたプログラマーは
人間が理解できるコードを書く。」

— Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.
『Refactoring: Improving the Design of Existing Code』 (1999)

27年前の言葉です。

第1回の話:「本だ/専門家を見下すな/Anthropicも本で学んだ」
この人がその例。ソフトウェア業界の神です。

もちろんダイクストラ法のDijkstraやリスコフの置換原則のLiskovもいます。
正確には理論の神ではなく企業向け開発実務の神。
分野は違いますが、千年前からコーディングを学んでも追い付けない神です。

2023~2025年 — 今も現役

martinfowler.comでExploring Generative AIシリーズを公開中。
27年前の本の著者が、AI時代のコーディングについても書き続けています。

つまり皆さんのClaudeも、この人の文章を学習しているはずです。

バイブコーディングの時代に置き換えると —

「どんなAIでもコンピューターが理解するコードは書く。
よい利用者は、AIと人間の両方が理解できるコードと文書を書く。」

その出発点が基礎であり、
開発者が考えるアーキテクチャ・デザインパターン・コードの複雑さといった技術用語です。

PRINCIPLE 07
基礎は捨てる知識ではなく、AIを追及する武器
自分でコードを書くためではありません。AIを追及するために知るのです。

F12・RLS・NEXT_PUBLIC_・Source Map・BFFプロキシ・権限確認。
この言葉を知らなければ、AIのコードを追及できません。

Claudeが「安全です」と言ったら:
「RLSは有効にした?このキーはクライアントに出ない?」

第5回の用語も武器になります。
Clean Architecture・MVVM・FSD・冪等性・原子性・デザインパターン……

PRINCIPLE 08
自分で作って初めて限界が見える
公開してF12を押した人だけが、セキュリティの感覚をつかめます。

第2回・第3回の宿題をした人は、
今日F12を押せば「こんなに見えるのか」と実感できます。

一度も公開したことがなければ頭で知っているだけ。
自分の目で見た人だけが感覚を得ます。

PRINCIPLE 08・実践

感覚を育てる近道:絵を磨いてみる

コードより単純。誰でもできます。

画像生成AIでイラスト・風景画・油絵・水彩画を全部試す。

講師の例:Geminiアプリ初登場から100枚以上を調整。所属するバイク仲間のエンブレムも自作。

AI比較は自分で磨いた人にしか分からない

画像
Nano Banana(Gemini)↔Duct Tape(OpenAI)

「Duct TapeがNano Bananaを超えるかも?」自分で比較する。

コード
Codex↔Claude(開発者も比較中)

「Codexへ移る?Codexはレビューだけ?作業はClaude?」

講師が両モデルを使った上でのたとえ

Gemini
哲学科と美大を首席で卒業したボヘミアン

発想は得意。長文では飛躍しすぎることがある。

Claude
法学部を首席で卒業した弁護士

具体化・話の構成・論理の整合性が得意。賢いが要領よくサボるので、絶えず追及が必要。

AIを追及する方法を開発者が活発に研究中

• ハーネスエンジニアリング:大きな枠組み。AIの作業環境自体をどう設計するか。
• エージェント:その中で自律的に動く単位。AIがツールを選び、計画・実行する(Claude Code、Cursor Composer)。

同じ研究の流れにあります。第6回でまた扱います。

10 PRINCIPLES — 10/10完成

01
誇大広告を警戒しろ
02
機械は怠けるし、嘘もつく
03
文書化・監視・追及
04
自分で勉強しようとするな
05
機械で機械を監視しろ
06
勉強ではなく委任だ
07
基礎知識は追及の武器だ
08
自分で作って初めて限界が見える
09
検証が作業より長ければ失敗
10
あなたは広告主、機械は代理店だ

10原則すべてを扱いました。
この10個が全6回の骨格です。

PART 6 — HOMEWORK

今日の宿題

TASK 1
自分のサイトでF12を押す
Network・Sources・Applicationタブで、何が公開されているか目で確認。
TASK 2
Claudeにセキュリティ監査をさせる
S22の6項目のプロンプトをそのまま貼る。
TASK 3
account.md+CLAUDE.mdのセキュリティ欄
今日の6つの防御線をそのままCLAUDE.mdに追加。

SESSION 04 / 06

今日も、
お疲れさまでした。

次回は第5回。
「適当にやって」は通じない — 技術用語の力。

オープンチャットQRコード

質問はKakaoTalkのオープンチャットへ。