0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pytest が失敗すると API キーがそのまま出る:-l(--showlocals)は比較と関係ない変数まで表示した(実機確認)

0
Posted at

先に結論

  • pytest は、失敗した assert の比較対象をそのまま表示します。ヘッダーの dict を比べると、Authorization: Bearer <キー> が失敗ログに出ました。
  • -l(--showlocals)を付けると、比較と関係ないローカル変数まで表示されます。assert status == 200 が失敗しただけで、同じ関数内の headers に入ったキーが出ました。
  • --junitxml で保存したレポートにも同じ内容が入りました(-l ありで5か所、なしで2か所)。
  • __repr__ を '***' にした入れ物に入れると、-l -vv でもキーは出ませんでした。--tb=no でも出ませんでした。

確認環境: Python 3.13.5 / pytest 9.2.0(Linux)。キーはダミー値 sk-DUMMY-1234567890abcdef です。

なぜ気にするか

AIエージェントにテストを回させると、失敗ログはそのままエージェントの会話に入り、CI ならログやアーティファクトとして残ります(どこまで残るかはサービスの設定によります)。テストが失敗したときのログに鍵が出ないかは、先に確かめておく価値があります。

試したテスト

test_api.py
import os
def build_headers():
    key = os.environ["DUMMY_API_KEY"]
    return {"Authorization": f"Bearer {key}"}

def test_status():
    headers = build_headers()
    status = 401  # 失敗を再現
    assert status == 200

def test_headers():
    headers = build_headers()
    assert headers == {"Authorization": "Bearer wrong"}

1. オプションなし:比べた dict はそのまま出る

$ export DUMMY_API_KEY=sk-DUMMY-1234567890abcdef
$ python3 -m pytest -q test_api.py
...
E         Differing items:
E         {'Authorization': 'Bearer sk-DUMMY-1234567890abcdef'} != {'Authorization': 'Bearer wrong'}

test_status(数値だけの比較)ではキーは出ませんでした。--tb=short と --tb=line でも、dict の比較ではキーが1か所出ました。

2. -l を付けると、比較と関係ない変数も出る

$ python3 -m pytest -q -l test_api.py
...
>       assert status == 200
E       assert 401 == 200

headers    = {'Authorization': 'Bearer sk-DUMMY-1234567890abcdef'}
status     = 401

-l は pytest --help で「Show locals in tracebacks (disabled by default)」と説明されています。既定では無効ですが、pytest.ini や pyproject.toml の addopts に入れていると毎回有効になります。

3. JUnit XML にも入る

$ python3 -m pytest -q -l test_api.py --junitxml=j.xml
$ grep -c sk-DUMMY j.xml
5

-l なしでも2か所入りました(dict 比較の分)。CI でレポートを保存しているなら、そこにも残ります。

4. 出さない方法(試した範囲)

  • 鍵を __repr__ で隠す入れ物に入れる:
class Secret(str):
    def __repr__(self): return "'***'"

-l -vv でも {'Authorization': '***'} と表示され、キーは0か所でした。ただし str() や f-string では元の値になります。

  • --tb=no:失敗の詳細を出さないので0か所。原因を追いにくくなります。
  • --no-showlocals:addopts の -l を打ち消します。dict 比較の1か所は残りました。

確かめるコマンド

grep -rnE -- '(-l\b|--showlocals)' pytest.ini pyproject.toml setup.cfg tox.ini 2>/dev/null

試してみる

コードとログの点検用に ai-secret-check を作っています。今回の pytest の設定はまだ点検対象ではありません。

まとめ

  • pytest の失敗ログには、比べた値がそのまま出る
  • -l は関係ない変数まで出す。addopts に入っていないか確かめる
  • 鍵は表示用に隠した入れ物に入れるか、ヘッダーそのものを比べるテストを避ける(ヘッダー名や長さを比べる、など)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?