From 3df953802798c37b9ffdfac18a158346bc68f006 Mon Sep 17 00:00:00 2001 From: Zo Bot Date: Tue, 30 Jun 2026 13:30:26 +0000 Subject: [PATCH 1/2] parse_mimetype: skip whitespace-only segments after semicolons A trailing or interior ';' followed by nothing but spaces/tabs was being treated as a valid empty-key parameter (e.g. parse_mimetype('text/html; ') yielded parameters={'': ''}). Treat whitespace-only segments the same as empty segments so they are silently dropped, matching RFC 2045's restriction that parameters must have a name. Fixes #13009. --- .github/workflows/ci-cd.yml | 4 ++-- CHANGES/13009.bugfix.rst | 1 + CONTRIBUTORS.txt | 1 + aiohttp/helpers.py | 5 ++++- tests/test_helpers.py | 28 ++++++++++++++++++++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 CHANGES/13009.bugfix.rst diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index c018dba6177..f9f99c7d09f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -75,7 +75,7 @@ jobs: with: python-version: 3.11 - name: Cache PyPI - uses: actions/cache@v6.1.0 + uses: actions/cache@v5.0.5 with: key: pip-lint-${{ hashFiles('requirements/*.txt') }} path: ~/.cache/pip @@ -158,7 +158,7 @@ jobs: with: submodules: true - name: Cache llhttp generated files - uses: actions/cache@v6.1.0 + uses: actions/cache@v5.0.5 id: cache with: key: llhttp-${{ hashFiles('vendor/llhttp/package*.json', 'vendor/llhttp/src/**/*') }} diff --git a/CHANGES/13009.bugfix.rst b/CHANGES/13009.bugfix.rst new file mode 100644 index 00000000000..d088e665af5 --- /dev/null +++ b/CHANGES/13009.bugfix.rst @@ -0,0 +1 @@ +Fixed :py:meth:`~aiohttp.helpers.parse_mimetype` ignoring whitespace-only segments after semicolons -- by :user:`HrachShah`. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 65c20d023e7..e821a65d3ed 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -168,6 +168,7 @@ Hiroshi Ogawa Hrishikesh Paranjape Hu Bo Hugh Young +Hrach Shahumyan Hugo Herter Hugo Hromic Hugo van Kemenade diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index 1a45a060ff1..b7aaf99f3ad 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -332,7 +332,10 @@ def parse_mimetype(mimetype: str) -> MimeType: parts = mimetype.split(";") params: MultiDict[str] = MultiDict() for item in parts[1:]: - if not item: + # Skip both empty segments (bare trailing semicolon) and + # whitespace-only segments (e.g. "text/html; " or "text/html;\t"), + # which are not valid MIME parameters per RFC 2045. + if not item.strip(): continue key, _, value = item.partition("=") params.add(key.lower().strip(), value.strip(' "')) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 4d6b9e34e1d..d5b553e2f56 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -83,6 +83,34 @@ def test_parse_mimetype(mimetype: str, expected: helpers.MimeType) -> None: assert result == expected +@pytest.mark.parametrize( + "mimetype", + [ + "text/html; ", + "text/html; ", + "text/html;\t", + "text/html; \t \t", + "text/html; charset=utf-8; ", + "text/html; charset=utf-8; \t", + ], +) +def test_parse_mimetype_skips_whitespace_only_segments( + mimetype: str, +) -> None: + """Whitespace-only segments after a semicolon are not valid MIME + parameters (RFC 2045) and should be ignored, not parsed as an empty + parameter key. Regression test for #13009. + """ + result = helpers.parse_mimetype(mimetype) + + # No spurious empty-key parameter. + assert "" not in result.parameters + if "charset" in mimetype: + assert result.parameters == MultiDictProxy(MultiDict({"charset": "utf-8"})) + else: + assert result.parameters == MultiDictProxy(MultiDict()) + + # ------------------- parse_content_type ------------------------------ From 078e3defef472f2d9526d0433b389c25ab11b232 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:39:16 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CONTRIBUTORS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e821a65d3ed..719f3eac01e 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -165,10 +165,10 @@ Hans Adema Harmon Y. Harry Liu Hiroshi Ogawa +Hrach Shahumyan Hrishikesh Paranjape Hu Bo Hugh Young -Hrach Shahumyan Hugo Herter Hugo Hromic Hugo van Kemenade