viteのbreaking change (CORSがひっかかる場合)
- v5.4.12
- v6.0.9
で発生している
laravelの場合とその対処法
curl -s "https://laravel.build/example-app?with=mysql" | bash
cd example-app
./vendor/bin/sail up -d
とかして現状の最新を持ってきて起動の後
./vendor/bin/sail npm install
./vendor/bin/sail npm list
html@ /var/www/html
+-- autoprefixer@10.4.20
+-- axios@1.7.9
+-- concurrently@9.1.2
+-- laravel-vite-plugin@1.2.0
+-- postcss@8.5.1
+-- tailwindcss@3.4.17
`-- vite@6.0.11
とすると 6.0.11 が入る。つまりbreaking changeにひっかかっている。
breeze
あるいは
./vendor/bin/sail composer require laravel/breeze --dev
./vendor/bin/sail artisan breeze:install react
./vendor/bin/sail npm list
html@ /var/www/html
+-- @headlessui/react@2.2.0
+-- @inertiajs/react@2.0.3
+-- @tailwindcss/forms@0.5.10
+-- @vitejs/plugin-react@4.3.4
+-- autoprefixer@10.4.20
+-- axios@1.7.9
+-- concurrently@9.1.2
+-- laravel-vite-plugin@1.2.0
+-- postcss@8.5.1
+-- react-dom@18.3.1
+-- react@18.3.1
+-- tailwindcss@3.4.17
`-- vite@6.0.11
まあ根本的にviteは5系か6系か入るけどバージョンが引き上がってbreaking changesにひっかかってしまう。
従来動いていたhmrの書き方
まあリモートでhmrを仕掛けようって人もそうおらんと思うが
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
server: {
hmr: {
host: '35.77.5.224',
}
},
plugins: [
laravel({
input: 'resources/js/app.jsx',
refresh: true,
}),
react(),
],
});
これはダメになった。
以下のように変更する
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
server: {
cors: true,
origin: 'http://35.77.5.224:5173',
hmr: {
host: '35.77.5.224',
}
},
plugins: [
laravel({
input: 'resources/js/app.jsx',
refresh: true,
}),
react(),
],
});
loadEnv方式に変更する場合
VITE_APP_NAME="${APP_NAME}"
VITE_PORT=5173
VITE_HMR_HOST=35.77.5.224
こんな感じで仕込んでおく。VITE_PORT
もここでセットしておいた。
import { defineConfig, loadEnv } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
server: {
port: env.VITE_PORT || 5173,
origin: `http://${env.VITE_HMR_HOST}:${env.VITE_PORT || 5173}`,
cors: true,
hmr: {
host: env.VITE_HMR_HOST || 'localhost',
},
},
plugins: [
laravel({
input: 'resources/js/app.jsx',
refresh: true,
}),
react(),
],
};
});
urlをParseしてもいいかもしれないけど一応VITE_PORT
っていう値がlaravel sailのdocker-composeで定義されているので、そこに従うとこんな感じかなという気がします。
【補足】 セキュリティー修正ドキュメント
chatgptによる翻訳をバコっと貼り付けとく
Vite 5.4.12のBreaking Changesまとめ
概要
Vite 5.4.12では、デフォルトのCORS設定の緩さ や WebSocketのOriginヘッダ検証不足 により、開発サーバーが任意のウェブサイトからのリクエストを許可し、レスポンスを読み取れる脆弱性が報告されました。この問題を修正するため、いくつかの変更が加えられました。
アップグレードパス
次の条件のいずれにも該当しない場合、Viteの新しいバージョンに追加の設定なしでアップグレードできます:
- バックエンド統合機能 を使用している
- Viteの前にリバースプロキシを配置 している
-
localhost
や*.localhost
以外のドメインで開発サーバーにアクセス している - WebSocketをブラウザから直接利用するプラグインやフレームワークを使用 している
バックエンド統合機能を使用している場合
server.origin
を設定していない場合は、バックエンドサーバーのオリジンを server.cors.origin
に明示的に設定 する必要があります。
server: {
cors: {
origin: 'http://your-backend.example.com', // バックエンドのオリジンを指定
},
}
※ *
を設定すると、すべてのオリジンからアクセス可能になるため セキュリティリスク があります。
リバースプロキシを使用している場合
Viteに送信されるリクエストのホスト名が localhost
以外の場合、server.allowedHosts
に そのホスト名を追加 する必要があります。
server: {
allowedHosts: ['vite'], // 例: http://vite:5173 にリバースプロキシを設定している場合
}
localhost
以外のドメインで開発サーバーにアクセスする場合
開発サーバーを localhost
以外のドメイン(例: http://foo.example.com:8080
)で利用する場合、server.allowedHosts
に追加する必要があります。
server: {
allowedHosts: ['foo.example.com'],
}
WebSocketを直接利用するプラグインやフレームワークを使用している場合
Viteの新しいバージョンにアップグレードし、WebSocket接続が正しく動作するかを確認 してください。
もしWebSocketが動作しない場合、以下のどちらかを行うことが可能です:
- プラグインやフレームワークのコードを修正 し、新しいViteの仕様に適応させる。
- 一時的に
legacy.skipWebSocketTokenCheck: true
を設定して、WebSocketのOriginチェックをスキップする。
server: {
legacy: {
skipWebSocketTokenCheck: true
}
}
※ この設定はセキュリティリスクを伴う ため、慎重に使用する必要があります。
Viteをアップグレードせずに脆弱性を回避する方法
[1] デフォルトのCORS設定の緩さ
server.cors
を false
にする または server.cors.origin
を信頼できるオリジンのみに限定する。
server: {
cors: {
origin: 'http://trusted.example.com',
},
}
[2] WebSocketのOriginヘッダの検証不足
この問題の回避策は Viteのアップグレード しかありません。
[3] HTTPリクエストのHostヘッダ検証不足
- Chrome 94以降のブラウザを使用する
- 開発サーバーをHTTPSで動作させる
server: {
https: true,
}
技術的な詳細
Viteが脆弱だったのは、次の3つの理由によるものです。
[1] デフォルトのCORS設定の緩さ
- Viteは
server.cors
のデフォルト値をtrue
にしていた。 - その結果、
Access-Control-Allow-Origin: *
が設定され、任意のオリジンからリソースを取得できる状態 になっていた。
[2] WebSocketのOriginヘッダの検証不足
- Viteは HMR (Hot Module Replacement) のために WebSocket サーバー を使用。
- WebSocketの
Origin
ヘッダを 検証していなかった ため、クロスサイト WebSocket ハイジャック (CSWSH) 攻撃 が可能だった。
[3] HTTPリクエストのHostヘッダ検証不足
- Viteの開発サーバーは Hostヘッダの検証を行っていなかった。
- DNSリバインディング攻撃によって、攻撃者がVite開発サーバーに任意のリクエストを送信できる 状態だった。
影響
- ソースコードの流出
- HMR経由でプラグインの情報漏洩
- DNSリバインディングによる不正アクセス
Chrome 94+ では一部の攻撃がブロックされるが、HTTPS環境での開発が推奨される。
まとめ
Vite 5.4.12 以降では CORSやWebSocketのセキュリティ対策が強化 され、明示的な server.origin
や server.allowedHosts
の設定が必要になりました。セキュリティリスクを防ぐため、適切な設定を行いましょう。
Discussion