Skip to content

fix(_logs): redact sensitive headers interpolated into log message strings#3200

Open
Ghraven wants to merge 1 commit intoopenai:mainfrom
Ghraven:fix/sensitive-headers-filter-string-format
Open

fix(_logs): redact sensitive headers interpolated into log message strings#3200
Ghraven wants to merge 1 commit intoopenai:mainfrom
Ghraven:fix/sensitive-headers-filter-string-format

Conversation

@Ghraven
Copy link
Copy Markdown

@Ghraven Ghraven commented May 6, 2026

Fixes #1196

Problem

SensitiveHeadersFilter only redacts headers when they appear as a structured dict in record.args. When httpx logs at DEBUG level it interpolates headers directly into the message string — e.g. "headers={'authorization': 'Bearer sk-...'}" — bypassing the dict-path entirely and leaving the API key visible in plain text debug logs.

Fix

Add a second pass that inspects the fully-formatted log message for header: value patterns matching SENSITIVE_HEADERS and replaces the value with <redacted>. When a substitution is made, record.msg is replaced with the sanitised string and record.args is reset so Python's logging machinery does not re-interpolate the original.

Both paths now apply: dict-based structured logs (existing) and string-formatted messages (new).

… in log messages

Fixes openai#1196

The existing `SensitiveHeadersFilter` only redacts headers when they are
passed as a structured `dict` in `record.args`. However, when httpx logs
at `DEBUG` level it interpolates headers directly into the message string
(e.g. `"headers={'authorization': 'Bearer sk-...'}"`), bypassing the
dict-path entirely and leaving the API key visible in plain text.

Fix: add a second pass that inspects the fully-formatted log message for
`header: value` patterns matching `SENSITIVE_HEADERS` and replaces the
value with `<redacted>`. When a substitution is made, `record.msg` is
replaced with the sanitised string and `record.args` is reset so Python's
logging machinery does not re-interpolate the original value.
@Ghraven Ghraven requested a review from a team as a code owner May 6, 2026 00:22
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3266c284a2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +50 to +51
pattern = rf"(?i)({re.escape(header)}['"]?\s*:\s*['"]?)([^'"\s,}}]+)"
redacted = re.sub(pattern, r"\1<redacted>", msg)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Redact full sensitive value, including spaces

The new regex only replaces characters up to the first whitespace ([^'"\s,}}]+), so an Authorization value like Bearer sk-... becomes <redacted> sk-... and still leaks the token. This is the common HTTP auth format, so debug logs can continue exposing credentials even after this fix.

Useful? React with 👍 / 👎.

Comment on lines +52 to +55
if redacted != msg:
record.msg = redacted
record.args = ()
break
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact every sensitive header occurrence in a message

The loop stops at the first matched header (break), so if a single log line contains multiple sensitive headers (e.g., both authorization and api-key), only one is scrubbed and the other remains visible. This creates partial redaction and leaves secrets in logs for multi-header requests.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

At debug log level API requests to OpenAI get logged with all headers, including an API key, in plaintext

1 participant