Skip to content

return 415 for undecodable multipart field charset in post - #13462

Merged
Dreamsorcerer merged 4 commits into
aio-libs:masterfrom
dxbjavid:multipart-charset-415
Aug 31, 2026
Merged

return 415 for undecodable multipart field charset in post#13462
Dreamsorcerer merged 4 commits into
aio-libs:masterfrom
dxbjavid:multipart-charset-415

Conversation

@dxbjavid

Copy link
Copy Markdown
Contributor

What do these changes do?

BaseRequest.post() decodes a plain multipart/form-data text field with value.decode(charset), where charset comes from that part's own Content-Type header and is fully attacker controlled. An unknown codec name (charset=not-a-real-codec) raises LookupError and undecodable bytes raise UnicodeDecodeError, and neither is caught, so a malformed part turns into an uncaught 500. The sibling urlencoded branch a few lines below, and BaseRequest.text(), already wrap the same decode in except (LookupError, UnicodeDecodeError) and raise HTTPUnsupportedMediaType. This brings the multipart branch in line with those two, so a bad part charset now yields a 415 like the other body-parsing paths rather than a server error.

Are there changes in behavior for the user?

A multipart field whose charset is unknown or whose bytes do not decode now surfaces as HTTPUnsupportedMediaType (415) instead of an unhandled exception. Valid fields are unaffected.

Is it a substantial burden for the maintainers to support this?

No. It is a two-line guard that mirrors existing code in the same function.

Related issue number

N/A

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
  • Add a new news fragment into the CHANGES/ folder

@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided There is a change note present in this PR label Aug 17, 2026
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.02%. Comparing base (7dc43ae) to head (7be9bc9).
⚠️ Report is 59 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #13462      +/-   ##
==========================================
+ Coverage   98.42%   99.02%   +0.60%     
==========================================
  Files         133      135       +2     
  Lines       49747    50518     +771     
  Branches     2628     2652      +24     
==========================================
+ Hits        48961    50025    +1064     
+ Misses        662      370     -292     
+ Partials      124      123       -1     
Flag Coverage Δ
Autobahn 22.03% <15.38%> (+0.07%) ⬆️
CI-GHA 98.91% <100.00%> (+0.59%) ⬆️
OS-Linux 98.69% <100.00%> (+0.58%) ⬆️
OS-Windows 97.09% <100.00%> (+0.63%) ⬆️
OS-macOS 97.97% <100.00%> (+0.62%) ⬆️
Py-3.10 98.11% <100.00%> (+0.56%) ⬆️
Py-3.11 98.34% <100.00%> (+0.54%) ⬆️
Py-3.12 98.43% <100.00%> (+0.54%) ⬆️
Py-3.13 98.42% <100.00%> (+0.54%) ⬆️
Py-3.14 98.45% <100.00%> (+0.55%) ⬆️
Py-3.14t 97.61% <100.00%> (+0.62%) ⬆️
Py-pypy-3.11 97.39% <100.00%> (+0.53%) ⬆️
VM-macos 97.97% <100.00%> (+0.62%) ⬆️
VM-ubuntu 98.69% <100.00%> (+0.58%) ⬆️
VM-windows 97.09% <100.00%> (+0.63%) ⬆️
cython-coverage 83.07% <100.00%> (+0.88%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@codspeed-hq

codspeed-hq Bot commented Aug 17, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 96 untouched benchmarks
⏩ 83 skipped benchmarks1


Comparing dxbjavid:multipart-charset-415 (7be9bc9) with master (9452d57)

Open in CodSpeed

Footnotes

  1. 83 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Comment thread tests/test_web_request.py Outdated
Signed-off-by: Javid Khan <dxbjavid@gmail.com>
Comment thread CHANGES/13462.bugfix.rst Outdated
Comment thread tests/test_web_request.py Outdated
Co-authored-by: Sam Bull <aa6bs0@sambull.org>
@Dreamsorcerer Dreamsorcerer added backport-3.14 Trigger automatic backporting to the 3.14 release branch by Patchback robot backport-3.15 Trigger automatic backporting to the 3.15 release branch by Patchback robot labels Aug 31, 2026
@Dreamsorcerer
Dreamsorcerer marked this pull request as ready for review August 31, 2026 03:19
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

The PR appears safe to merge, with focused error translation and coverage for both affected decoding failures.

The guarded decode operation now maps unsupported codec names and invalid encoded bytes to the same HTTP 415 behavior already used by sibling request-decoding paths, and no blocking or non-blocking defect remains.

Reviews (1): Last reviewed commit: "Apply batched suggestions from code revi..." | Re-trigger Greptile

@Dreamsorcerer
Dreamsorcerer merged commit 6b97ebd into aio-libs:master Aug 31, 2026
56 checks passed
@patchback

patchback Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Backport to 3.15: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 6b97ebd on top of patchback/backports/3.15/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462

Backporting merged PR #13462 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https://github.com/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.15/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462 upstream/3.15
  4. Now, cherry-pick PR return 415 for undecodable multipart field charset in post #13462 contents into that branch:
    $ git cherry-pick -x 6b97ebd612e24507324e37d8bab6f8b91ba30abd
    If it'll yell at you with something like fatal: Commit 6b97ebd612e24507324e37d8bab6f8b91ba30abd is a merge but no -m option was given., add -m 1 as follows instead:
    $ git cherry-pick -m1 -x 6b97ebd612e24507324e37d8bab6f8b91ba30abd
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR return 415 for undecodable multipart field charset in post #13462 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.15/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https://github.com/sanitizers/patchback-github-app.

@patchback

patchback Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Backport to 3.14: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 6b97ebd on top of patchback/backports/3.14/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462

Backporting merged PR #13462 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https://github.com/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.14/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462 upstream/3.14
  4. Now, cherry-pick PR return 415 for undecodable multipart field charset in post #13462 contents into that branch:
    $ git cherry-pick -x 6b97ebd612e24507324e37d8bab6f8b91ba30abd
    If it'll yell at you with something like fatal: Commit 6b97ebd612e24507324e37d8bab6f8b91ba30abd is a merge but no -m option was given., add -m 1 as follows instead:
    $ git cherry-pick -m1 -x 6b97ebd612e24507324e37d8bab6f8b91ba30abd
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR return 415 for undecodable multipart field charset in post #13462 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.14/6b97ebd612e24507324e37d8bab6f8b91ba30abd/pr-13462
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https://github.com/sanitizers/patchback-github-app.

@Dreamsorcerer

Copy link
Copy Markdown
Member

Please create backports with the above instructions.

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

Labels

backport-3.14 Trigger automatic backporting to the 3.14 release branch by Patchback robot backport-3.15 Trigger automatic backporting to the 3.15 release branch by Patchback robot bot:chronographer:provided There is a change note present in this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants