python / python/cpython

wsgiref.headers.Headers control-character validation is skipped under -O

オープン
#150,726 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

stdlib type-bug
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

wsgiref.headers.Headers.__init__ checks header names and values for control characters only inside an if __debug__: block:

self._headers = headers
if __debug__:
    for k, v in headers:
        self._convert_string_type(k, name=True)
        self._convert_string_type(v, name=False)

Running with -O/-OO sets __debug__ to False, so the loop is skipped and the constructor stores the headers without validation. wsgiref.handlers.BaseHandler.start_response builds its response headers exactly this way (self.headers = self.headers_class(headers)), and those headers are later written to the wire unchanged. A value carrying CR/LF therefore passes through and can split the response or inject headers when an application reflects untrusted input into a header.

$ python -O -c "from wsgiref.headers import Headers; print(bytes(Headers([('Foo','bar\r\nSet-Cookie: evil=1')])))"
b'Foo: bar\r\nSet-Cookie: evil=1\r\n\r\n'

Under a normal build the same call raises ValueError. Every other Headers mutator (__setitem__, add_header, setdefault) validates unconditionally; only the constructor gates the check on __debug__.

Linked PRs
  • gh-150727

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

wsgiref.headers.Headers.init と wsgiref.handlers.BaseHandler.start_response を読み、次に python -O で CR/LF のケースを再現してください。完了とは、-O でもヘッダー検証が引き続き適用され、関連するリグレッションテストがパスすることです。リンク先の PR gh-150727 は、すでに作業が進行中であることを示しています。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
backend, security
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。