Quartにおいて、デバッグ出力の記述ミスにより、リクエストの生データ(平文のパスワードを含む)が標準出力に出力される問題があります。
### 概要
Quart 0.23.0には、`quart/wrappers/request.py`の`Body.__await__`内に、意図しないデバッグ出力(`print(data)`)が含まれています。`await request.form`、`await request.get_data()`、WTFormsの`validate_on_submit()`など、リクエストのボディを待機するすべてのリクエストにおいて、生の、未パースされたデータが標準出力に出力されます。これには、パスワードやCSRFトークンなどの平文のフォームフィールドが含まれます。この問題は0.23.0で確認されており、0.22.0では確認されていません。
### 詳細
`src/quart/wrappers/request.py`の`Body.__await__`では、リクエストのボディがバイト配列に蓄積されます。
```python
data = bytearray()
while not self._queue.empty():
data.extend(self._queue.get_nowait())
print(data) # <-- 0.22.0には存在しない
if (
self._max_content_length is not None
and len(data) > self._max_content_length
):
raise RequestEntityTooLarge()
```
この処理は、リクエストのボディを待機するすべてのリクエストで実行されます。これは、典型的なQuartアプリケーションにおけるPOST/PUTリクエストの大部分(フォーム送信、`request.get_json()`によるJSON API、ファイルアップロードなど)に該当します。
### 動作確認方法
1. `pip install quart==0.23.0` (Python 3.13以降が必要です)
2. 最小限のルートを以下のように記述します。
```python
@app.route("/login", methods=["POST"])
async def login():
form_data = await request.form
...
```
3. フォームデータを含むPOSTリクエストを送信します。例えば、`staff_id`/`password`フィールドを持つログインフォームです。
4. 標準出力を確認します。生のボディ全体が`bytearray(b'csrf_token=...&staff_id=...&password=...')`のような形式で出力されます。
ソースコードの差分により確認した結果、0.22.0の`request.py`にはこの行は存在しませんでした。
### 影響
標準出力(stdout)をログに記録するアプリケーション(ターミナルのリダイレクト、systemd/journald、Dockerのログ、クラウドのログ収集など)では、送信されたフォームの内容(ログイン情報を含む)が、平文でログに記録されます。これは、Quart 0.23.0で認証機能や機密性の高いフォームデータを扱うすべてのアプリケーションに影響を与え、ユーザーがフォームを送信するだけで簡単にトリガーされる可能性があります(攻撃者が特別な操作を行う必要はありません)。
影響を受けるパッケージ:
- pip (Python) quart: 影響を受けるバージョン: 0.23.0、修正されたバージョン: 0.23.1