Skip to content

Reject invalid HTTP method token characters#833

Open
andrewkernel wants to merge 1 commit into
cherrypy:mainfrom
andrewkernel:fix-header-name-trailing-space
Open

Reject invalid HTTP method token characters#833
andrewkernel wants to merge 1 commit into
cherrypy:mainfrom
andrewkernel:fix-header-name-trailing-space

Conversation

@andrewkernel

@andrewkernel andrewkernel commented Jun 27, 2026

Copy link
Copy Markdown

What kind of change does this PR introduce?

  • 🐞 bug fix
  • 🐣 feature
  • 📋 docs update
  • 📋 tests/coverage improvement
  • 📋 refactoring
  • 💥 other

📋 What is the related issue number (starting with #)

Closes #715.

What is the current behavior? (You can also link to an open issue here)

HTTP request methods containing characters outside the HTTP token grammar could be accepted after parsing the request line.

What is the new behavior (if this is a feature change)?

Cheroot now validates parsed HTTP methods against the HTTP token character set and rejects methods containing invalid token characters with 400 Bad Request.

📋 Other information:

Added docs/changelog-fragments.d/833.bugfix.rst.

Testing:

  • .venv\Scripts\python.exe -m pytest --no-cov -n 0 cheroot/test/test_core.py -k "malformed_http_method or invalid_character_in_http_method"

📋 Contribution checklist:

  • I wrote descriptive pull request text above
  • I think the code is well written
  • I wrote good commit messages
  • I have squashed related commits together after the changes have been approved
  • Unit tests for the changes exist
  • Integration tests for the changes exist (if applicable)
  • I used the same coding conventions as the rest of the project
  • The new code doesn't generate linter offenses
  • Documentation reflects the changes
  • The PR relates to only one subject with a clear title and description in grammatically correct, complete sentences

@read-the-docs-community

read-the-docs-community Bot commented Jun 27, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cheroot | 🛠️ Build #33486590 | 📁 Comparing 0446800 against latest (3937fe1)

  🔍 Preview build  

6 files changed · ± 6 modified

± Modified

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.16%. Comparing base (3937fe1) to head (0446800).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #833      +/-   ##
==========================================
- Coverage   78.19%   78.16%   -0.03%     
==========================================
  Files          41       41              
  Lines        4788     4800      +12     
  Branches      547      548       +1     
==========================================
+ Hits         3744     3752       +8     
- Misses        905      907       +2     
- Partials      139      141       +2     

@julianz- julianz- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Useful like #832 but can you use the original template in the PR description?

Your commit also needs a body message which can expand on the commit message. The CI log mentions this:

Commit ede37bd316:
3: B6 Body message is missing
Error: Process completed with exit code 1.

You also need to add a docs/changelog-fragments.d/833.bugfix.rst describing the bug fix in the appropriate towncrier style - see docs/changelog-fragments.d/README.rst.

Comment thread cheroot/test/test_core.py

def test_invalid_character_in_http_method(test_client):
"""Check that methods with invalid token characters are rejected."""
c = test_client.get_connection()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use a descriptive variable name such as conn.

Comment thread cheroot/server.py
return False

if not HTTP_TOKEN_RE.match(method):
self.simple_response('400 Bad Request', 'Malformed method name')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's make the message more informative e.g.: Malformed method name: invalid token (see RFC 9110 section 9.1). See, for example, line 834. References older (obsoleted) RFCs but you get the idea.

resp = (
                'Malformed method name: According to RFC 2616 '
                '(section 5.1.1) and its successors '
                'RFC 7230 (section 3.1.1) and RFC 7231 (section 4.1) '
                'method names are case-sensitive and uppercase.'
            )

@julianz- julianz- self-assigned this Jul 1, 2026
@andrewkernel andrewkernel force-pushed the fix-header-name-trailing-space branch from 25e9292 to 53f4fbf Compare July 7, 2026 21:55
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided A mark meaning that a new change log entry is present within the patch. label Jul 7, 2026
@andrewkernel andrewkernel force-pushed the fix-header-name-trailing-space branch from 53f4fbf to 0446800 Compare July 7, 2026 21:56
Validate parsed HTTP methods against the RFC token character set before accepting the request line. This rejects methods containing invalid token characters with a 400 Bad Request response and covers the behavior with a focused regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided A mark meaning that a new change log entry is present within the patch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cheroot's HTTP method parsing is too permissive

2 participants