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?

Python requests のデバッグで API キーがそのまま出る:logging DEBUG では出ず debuglevel=1 で Authorization が丸見え(実機確認)

0
Posted at

結論

  • Python の requests で通信をデバッグするとき、logging を DEBUG にしただけなら Authorization ヘッダーの値は出ませんでした。出たのは "GET / HTTP/1.1" 200 のような1行だけです(2026-11-09、Python 3.13.5・requests 2.34.2・urllib3 2.8.0、ダミー値で実機確認)。
  • ところが http.client.HTTPConnection.debuglevel = 1 を足すと、send: の行に Authorization: Bearer ... がそのまま出ました。
  • auth=(user, key) の Basic 認証も同じ行に出ます。Base64 なので、そのまま元の文字列に戻せます。
  • 逆に、params={"api_key": ...} のように キーを URL に入れると、debuglevel なしでも urllib3 の DEBUG ログに URL ごと出ました。
  • send: の行は logging ではなく print() で標準出力に出ます。ログの設定でマスクしたつもりでも効きません。

この記事は「AIエージェントと秘密情報」の検証シリーズです。新しい検証は X(@supportapp3_lab)でもお知らせしています。

試してみる(デバッグ設定が残っていないか)

コードに debuglevel を上げる行が残っていないかを探します。

grep -rnE --include='*.py' 'debuglevel|set_debuglevel' .

キーを URL のクエリに入れている箇所も探せます(見つかっても、そのAPIがヘッダーでの指定に対応しているかは各APIの仕様を確認してください)。

grep -rnE --include='*.py' "params=.*(api_?key|token)|[?&](api_?key|token)=" .

何が問題か

401 エラーなどを調べるとき、「通信の中身を全部見たい」と debuglevel = 1 を入れる書き方はよく見かけます。この出力には、送ったヘッダーがそのまま入ります。

ターミナルに出た出力は、ログファイルや CI のログ、画面共有、AI エージェントに渡すエラー全文などに、そのまま混ざることがあります。Codex や Claude Code のようにコマンドを実行して出力を読むツールでは、その出力も会話に入ります。

再現手順

ローカルに小さな HTTP サーバーを立てて、ダミーのキーを送りました(外部には送っていません)。

import logging, sys, http.client, requests
URL = "http://127.0.0.1:18081/"
HDR = {"Authorization": "Bearer sk-dummy-0000"}

logging.basicConfig(level=logging.DEBUG, stream=sys.stdout,
                    format="%(name)s %(levelname)s %(message)s")
requests.get(URL, headers=HDR)          # 1. DEBUG だけ

http.client.HTTPConnection.debuglevel = 1
requests.get(URL, headers=HDR)          # 2. debuglevel=1
requests.get(URL, auth=("user", "sk-dummy-1111"))  # 3. Basic 認証

(サーバー部分は省略しています。全体は http.server で 200 を返すだけのものです。)

1. logging を DEBUG にしただけ

urllib3.connectionpool DEBUG Starting new HTTP connection (1): 127.0.0.1:18081
urllib3.connectionpool DEBUG http://127.0.0.1:18081 "GET / HTTP/1.1" 200 None

ヘッダーは出ていません。

2. debuglevel = 1 を足す

send: b'GET / HTTP/1.1\r\nHost: 127.0.0.1:18081\r\nUser-Agent: python-requests/2.34.2\r\nAccept-Encoding: gzip, deflate, br, zstd\r\nAccept: */*\r\nConnection: keep-alive\r\nAuthorization: Bearer sk-dummy-0000\r\n\r\n'
reply: 'HTTP/1.0 200 OK\r\n'

Authorization: Bearer sk-dummy-0000 がそのまま出ました。

3. Basic 認証(auth=)

send: b'GET / HTTP/1.1\r\n...\r\nAuthorization: Basic dXNlcjpzay1kdW1teS0xMTEx\r\n\r\n'
$ echo -n 'user:sk-dummy-1111' | base64
dXNlcjpzay1kdW1teS0xMTEx

Base64 は暗号ではないので、出力からそのまま user:sk-dummy-1111 に戻せます。

4. キーを URL のクエリに入れた場合(debuglevel = 0)

requests.get(URL, params={"api_key": "sk-dummy-2222"})
urllib3.connectionpool http://127.0.0.1:18082 "GET /?api_key=sk-dummy-2222 HTTP/1.1" 200 None

debuglevel を上げていなくても、DEBUG ログの1行に URL ごと出ました。

5. send: は標準出力、ログは標準エラー

ログの出力先を標準エラーにして、標準出力と分けて実行しました。send: 以下の行は標準出力側に出ました。

[stdout] send: b'GET / HTTP/1.1\r\n...Authorization: Bearer sk-dummy-3333\r\n\r\n'
[stderr] urllib3.connectionpool http://127.0.0.1:18082 "GET / HTTP/1.1" 200 None

手元の Python 3.13.5 の http/client.py でも、print("send:", repr(data)) と書かれていました。logging の Filter でマスクしても、この行には効きません。

対策

  1. debuglevel = 1 は調べ終わったら必ず消す。コミット前に上の grep で確認する。
  2. どうしても通信を見たいときは、ダミーのキーか、すぐ無効にできる一時的なキーで試す。
  3. キーは URL のクエリではなく、ヘッダーで渡す(API が対応している場合)。クエリは DEBUG ログに URL ごと出ました。
  4. デバッグ出力を AI に貼ったりログとして保存したりする前に、Authorization や api_key の行がないか見る。
  5. AI にデバッグを頼むときは「debuglevel は使わない」「キーをログに出さない」と条件を付ける。

ai-secret-check について

ai-secret-check scan は、AIが読めそうな場所にある .env 系のファイル名を探します(中身は表示しません)。ログやコードの中のキーまでは見ないので、上の grep とセットで使ってください。

npx github:supportapp3-lab/ai-secret-check scan

リポジトリ: https://github.com/supportapp3-lab/ai-secret-check (Node.js 20以上、MIT)

参考

※ 2026-11-09 に、Debian 13・Python 3.13.5・requests 2.34.2・urllib3 2.8.0、ダミー値・ローカルサーバーで確かめました。

更新情報やちょっとしたTipsは X(@supportapp3_lab)で発信しています。

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?