Skip to content

Swap every header that carries a placeholder - #45

Merged
czpython merged 1 commit into
mainfrom
dru-470-every-placeholder
Sep 7, 2026
Merged

Swap every header that carries a placeholder#45
czpython merged 1 commit into
mainfrom
dru-470-every-placeholder

Conversation

@czpython

@czpython czpython commented Sep 7, 2026

Copy link
Copy Markdown
Owner

What changes

  • Swap.requestheaders collects every header whose value carries a placeholder, once, from the original headers. Swap.swap authorizes each placeholder for the CONNECT host, then deletes the carrying headers and writes the headers the exchange names, all at once.
  • One refused placeholder answers 403 and leaves the request untouched and unsent. An exchange that falls silent partway answers 503 the same way. Two placeholders that resolve to the same destination header answer 403.
  • A credential the exchange returns is never scanned as a placeholder, since the scan happens before any write.
  • Tests: bearer plus a custom header, the same in reverse order, a conflict on one header with and without case, a repeated field with a placeholder in each, a refused second placeholder, an exchange down after one answer, and a credential that looks like a placeholder. The single-header, Basic, host, and streaming tests are unchanged and pass.
  • docs/security.md and docs/architecture.md say the proxy swaps every header that carries a placeholder and that one refusal refuses the whole request.

Where this differs from the ticket

  • Nothing. URL and body substitution stay out, and one entry still holds one value.

Names

None new. Swap.swap takes the placeholders it found, a map from header name to placeholder, instead of one pair.

Gates

uv run ruff check, uv run ruff format --check, uv run pyright, and uv run pytest are green.

Review

Pending.

@czpython
czpython force-pushed the dru-470-every-placeholder branch from 512ce1f to 4c2ca17 Compare September 7, 2026 11:02
The proxy stopped at the first placeholder it found, so a request with
two secret headers sent the second placeholder to its destination as it
was. The addon now collects every placeholder from the original headers,
authorizes each one for the host, and replaces them all at once. One
refusal refuses the whole request, an exchange that gives no answer gets
a 503 before anything is sent, and two placeholders that resolve to the
same header refuse the request. A credential the exchange returns is
never scanned as a placeholder. The security and architecture docs say
so.

Header names compare without case, as mitmproxy keeps them, and the
placeholders come from every field of a repeated name, not from the
folded value.
@czpython
czpython force-pushed the dru-470-every-placeholder branch from 4c2ca17 to 7805fb7 Compare September 7, 2026 11:04
@czpython
czpython merged commit 99d467f into main Sep 7, 2026
6 checks passed
@czpython
czpython deleted the dru-470-every-placeholder branch September 7, 2026 13:02
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.

1 participant