Playwrightのテストで、外部APIや第三者サービスのURLをそのまま開いていませんか。
動く時は動くのですが、相手の障害・仕様変更・広告・レート制限までテスト結果に混ざります。しかも、テストコードをAIに書かせると実在のURLへ接続する例が平気で生成されます。
GSCを見ると「playwright 脆弱性」という検索が続いていました。Playwrightそのものを怖がるより、テストがどこへ接続するかを先に確認した方がよいです。
第三者サイトをそのままテストすると何が起きるか
例えば、ログイン後に天気APIの結果を表示する画面をテストするとします。最初に思いつくコードはこれです。
test('天気を表示する', async ({ page }) => {
await page.goto('https://example.com/dashboard');
await expect(page.getByText('晴れ')).toBeVisible();
});
これだけなら簡単ですね。ただし、画面が呼び出す外部APIまで本物に接続すると、APIの応答が遅い、内容が変わる、停止する、という事情でテストが落ちます。
テストは自分たちが管理している動作を確認するものです。管理していない第三者の状態まで毎回確認するものではありません。
ではpage.route()で応答を固定してみましょう
Playwrightの公式Best Practicesでは、第三者依存を直接テストせず、Network APIで必要な応答を保証する方法が紹介されています。
では、天気APIを固定してみましょう。
test('天気を表示する', async ({ page }) => {
await page.route('**/api/weather', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ weather: 'sunny' }),
});
});
await page.goto('https://example.com/dashboard');
await expect(page.getByText('晴れ')).toBeVisible();
});
これでテスト中の`/api/weather`は、毎回同じJSONを返します。外部APIの機嫌に結果を預けず、画面が「晴れ」を表示できるかだけを確認できます。
モックは脆弱性対策だけではありません
外部サイトを直接開かないことは、テストを安定させるだけではありません。生成されたテストが知らない相手へデータを送っていないか、という確認もしやすくなります。
AIにテストを書かせたら、まず次を見てください。
- 管理していないドメインへ`goto()`していないか
- 外部APIへ送るリクエストに認証情報や個人情報が入っていないか
- 本物の応答を待つ代わりに`page.route()`で境界を固定できないか
テストコードに秘密情報を書かない話や、trace・video・HARに資格情報を残さない話とは別の境界です。今回は「どこへ接続するか」を管理します。
本番疎通までモックしてはいけない
もちろん、すべてをモックすればよいわけではありません。第三者APIとの接続自体を確認するテストは別に必要です。
私なら、普段のE2Eは`route.fulfill()`で固定し、少ない本番相当の疎通テストだけを別ジョブに分けます。外部サービスが落ちた時に、画面のテストまで全部失敗させないためです。
モックが現実を隠すこともあります。レスポンスの項目が増えた時や、認証方式が変わった時は、別の疎通テストで気づけるようにしておきましょう。
まとめ
Playwrightの「脆弱性」が気になった時、ブラウザ自動化の仕組みだけを疑う必要はありません。テストが管理外のサイトやAPIへ直接接続していないかを確認してください。
`page.route()`と`route.fulfill()`で第三者依存を固定すると、テストの再現性と接続先の見通しがよくなります。AIに生成させたテストにも、そのまま使える確認項目です。
私も生成されたテストは、まずURLとネットワーク境界から見ています。コードが短くても、外へ出ていく処理は短時間で確認した方が安全です。

コメント