1. フロントエンドのJavaScriptに埋め込まれたAPIキー
これは最も被害が大きく、最も起こしやすいミスです。AIツールに「Stripe決済を追加して」や「OpenAIに接続して」と頼むと、シークレットキーをそのままクライアントのコンポーネントに組み込んでしまいます。アプリは動きます——そしてあなたのシークレットキーは、いまやすべての訪問者のブラウザに配信され、DevToolsを開いたりJSバンドルをgrepしたりする人なら誰でも読めてしまいます。
NEXT_PUBLIC_(または VITE_、REACT_APP_)のプレフィックスが付いたものはすべて、ビルド時にクライアントのバンドルに埋め込まれます。シークレットキー——Stripeの sk_live_、OpenAIの sk-、データベースURL、service-role キー——は、必ずサーバーサイドのコード(API route、サーバーコンポーネント、edge function)でのみ読み取らなければなりません。
かんたんな確認方法:デプロイ済みのサイトを開き、ページのソースとバンドルされたJSを表示し、sk_live、sk-、そして .env にあるキーの先頭数文字を検索してください。いずれかが見つかったら、まずキーをローテーションし、それから呼び出しをサーバーサイドに移してください。
2. Webルートからそのまま配信される .env や .git
驚くほど多くのデプロイ済みアプリが、頼むだけで .env ファイル——あるいは .git ディレクトリ全体——を平気で返してしまいます。設定を誤った静的ファイルサーバーが1つ、あるいはすべてをpublicフォルダにコピーするフレームワークのテンプレートが1つあれば、それで十分です。
影響は全面的です。データベースの認証情報、認証用のシークレット、APIキーが、すべて1つのファイルに。露出した .git ディレクトリもほぼ同じくらい深刻で、攻撃者はコミットされて後から「削除された」シークレットも含め、あなたの完全なソース履歴を復元できてしまいます。
かんたんな確認は10秒で済みます:
curl -i https://yourapp.com/.env
curl -i https://yourapp.com/.git/config
# Both should return 404 (or 403) — never 200.露出した .env ファイル:完全ガイド3. Content-Security-Policyがない
AIツールはセキュリティヘッダーをほとんど追加せず、その中でも最も重要なのがCSPです。これがないと、アプリのどこかにあるたった1つのHTMLインジェクションやXSSのバグで、攻撃者はユーザーのブラウザで任意のJavaScriptを実行できます——セッションを盗み、データを持ち出します。
ほとんどのアプリにとって良い出発点となるポリシー:default-src 'self'、オブジェクトとフレーム化をブロックし、実際に使うサードパーティのスクリプトオリジンだけを許可します。厳格に始めて、意図的に緩める——決してその逆をしないでください。
// next.config.js
const csp = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"base-uri 'none'",
"frame-ancestors 'none'",
"object-src 'none'",
].join("; ");
module.exports = {
async headers() {
return [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: csp }] }];
},
};CSPを解説:ディレクティブ、nonce、よくある間違い4. Secure、HttpOnly、SameSite のないセッションCookie
認証ライブラリをAIツールが既定のオプションのまま組み込んだ場合、セッションCookieのフラグを確認する価値があります。HttpOnly のないCookieは、注入されたあらゆるスクリプトに読み取られ(小さなXSSが完全なアカウント乗っ取りに変わります)、Secure のないものはプレーンHTTPで漏れ、SameSite のないものはクロスサイトリクエストフォージェリをはるかに容易にします。
デプロイ済みのアプリで DevTools → Application → Cookies を開いてください。すべてのセッションまたは認証のCookieに、Secure、HttpOnly、SameSite=Lax(または Strict)の3つが表示されているはずです。
5. HTTPSにならないHTTP(そしてHSTSもない)
ほとんどのホスティングプラットフォームはHTTPSを自動で提供します——それでも多くのアプリは、リダイレクトせずにプレーンHTTPで平気に応答したり、リダイレクトはしても Strict-Transport-Security ヘッダーを一度も送らなかったりします。いずれにせよ、アドレスバーにあなたのドメインを入力したユーザーは、最初のリクエストを暗号化されないまま送ることになり、そのリクエストは、あなたのリダイレクトが起きる前に傍受またはダウングレードされる可能性があります。
対策は設定の2行です。HTTPからHTTPSへの恒久的な301リダイレクトと、ブラウザが二度とダウングレードを拒否するようにするHSTSヘッダー(max-age=31536000; includeSubDomains)です。
6. すべてを許可する設定のCORS
AIが生成したフロントエンドが、開発中に自分のAPIに到達できないとき、生成される「対策」はほぼ必ず Access-Control-Allow-Origin: * です——ときには認証情報の許可付きで。これは、インターネット上のすべてのWebサイトに、訪問者のブラウザからあなたのAPIを呼び出してよいと伝えているようなものです。
自分のフロントエンドに応えるAPIなら、許可するオリジンはあなた自身のドメインだけであるべきで、それ以外は不要です。ワイルドカードのCORSが許容されるのは、本当に公開されている、認証を伴わない、読み取り専用のAPIだけです。
7. ドメインにSPFもDMARCもない
これはアプリのコードの話ではまったくなく——あなたのドメインの話です。SPFとDMARCのDNSレコードがないと、誰でも [email protected] から来たと称するメールを送れてしまい、受信側のメールサーバーにはそれが偽造だと知る手立てがありません。これは、あなたのブランドをまとって、自分のユーザーに対して行われるフィッシングです。
2つのDNS TXTレコードで解決します。Resend、Postmark、SES のようなプロバイダー経由でメールを送っているなら、そのドキュメントに正確なSPFの値が載っています。それとあわせてDMARCポリシーを追加し、正当なメールが通ることを確認したら p=none から p=quarantine へと厳しくしてください。
7つすべてを一度に確認する
このリストの項目はすべて外部から検出できます。つまり、手作業で一つずつ確認する必要はありません。AppSafeは、これらのチェックすべてに加えて——SSL/TLS、サブドメイン乗っ取り、source map など——を1回のスキャンで実行し、結果をA〜Fで採点し、CursorやClaude Codeにそのまま貼り付けられるAI修正プロンプトを各指摘に用意します。
ホームページのかんたんスキャンは登録不要です。フルスキャン(流出したシークレットの検査を含む)は、所有権を確認済みのドメインでのみ実行されます——これは意図的な設計で、他人のJSバンドルをキー目当てにgrepすることはしないからです。