mitmproxy / mitmproxy/mitmproxy
curl and httpie export change the body when it has % or a trailing newline
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 45.1k
- Forks
- 4.7k
- Avg merge
- 21h 12m
- Merged PRs (30d)
- 16
Description
Problem Description
The curl and httpie export changes the request body when the body has a control character (for example a newline) together with %, a backslash, or a newline at the end. The exported command sends different bytes than the original request.
The body is passed as "$(printf '...')". printf treats % as a format directive and \n, \t and other backslash sequences as escapes. $(...) also removes newlines at the end of the output.
I ran the exported commands in bash against a local server and compared the bytes:
| body in mitmproxy | exported | server received |
|---|---|---|
{"a":1}\n |
-d "$(printf '{"a":1}\x0a')" |
{"a":1} (newline lost) |
a=100%\nb=2 |
-d "$(printf 'a=100%\x0ab=2')" |
a=100 and printf: '\': invalid format character |
C:\new\temp\nx (two backslashes) |
-d "$(printf 'C:\new\temp\x0ax')" |
C:<LF>ew<TAB>emp<LF>x |
A JSON body that ends with a newline is very common, so the first case happens a lot.
Steps to reproduce the behavior:
- Capture a POST request whose body is
{"a":1}followed by a newline. - Run
export.clip curl @focus(or:export.clip curl @focusin the console) and paste the command into bash. - The server gets
{"a":1}without the newline. With a body likea=100%followed by a newline the server gets onlya=100.
Bodies without control characters are fine, they go through shlex.quote.
A fix is to use ANSI-C quoting ($'...') instead of printf. It expands \xNN byte for byte and does not touch %. I tested it in bash and zsh, all bodies above arrive unchanged. I will open a pull request.
System Information
Mitmproxy: 13.0.0.dev (+79, commit 2ac5b08)
Python: 3.14.6
OpenSSL: OpenSSL 3.5.5 27 Jan 2026
Platform: macOS-26.5.2-arm64-arm-64bit-Mach-O
The printf code is unchanged since 11.1.0 (#7520), so the latest release is affected too.
Checklist
- This bug affects the latest mitmproxy release.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the curl and httpie export paths invoked by export.clip curl @focus or :export.clip curl @focus in the console, then reproduce the examples against a local server and compare received bytes. Check the existing printf and shlex.quote handling; done means exported commands preserve percent signs, backslashes, control characters, and trailing newlines in bash and zsh.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, python, zsh
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100