Skip to content

Reject NUL bytes in HTTP request lines#832

Open
andrewkernel wants to merge 1 commit into
cherrypy:mainfrom
andrewkernel:fix-null-byte-request-line
Open

Reject NUL bytes in HTTP request lines#832
andrewkernel wants to merge 1 commit into
cherrypy:mainfrom
andrewkernel:fix-null-byte-request-line

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 #)

Related to #201.

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

HTTP request lines containing embedded NUL bytes could reach the request-line parser instead of being rejected explicitly as malformed input.

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

Cheroot now rejects request lines containing NUL bytes with 400 Bad Request before splitting the request line. The malformed request-line test matrix covers the NUL-byte case.

📋 Other information:

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

Testing:

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

📋 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 #33486556 | 📁 Comparing 9525cd8 against latest (3937fe1)

  🔍 Preview build  

2 files changed
± history/index.html
± pkg/cheroot.server/index.html

@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 77.77%. Comparing base (3937fe1) to head (9525cd8).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #832      +/-   ##
==========================================
- Coverage   78.19%   77.77%   -0.43%     
==========================================
  Files          41       41              
  Lines        4788     4791       +3     
  Branches      547      483      -64     
==========================================
- Hits         3744     3726      -18     
- Misses        905      922      +17     
- Partials      139      143       +4     

@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.

Thanks for this PR. Looks useful but see inline comments. Also in the PR description you did not use the standard template that makes clear what you have and have not addressed.

Your commit also needs a body message and we need a docs/changelog-fragments.d/832.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 Outdated

def test_null_byte_in_request_line(test_client):
"""Check that NUL bytes in the request line return Bad Request."""
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.

Let's use descriptive vars rather than single characters. conn would be better here.

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.

Technically, this follows the existing style, which could be okay in such cases. This, however, mainly copies the same test and should've just parametrized it instead of adding another almost-identical test function.

Comment thread cheroot/server.py Outdated

try:
method, uri, req_protocol = request_line.strip().split(SPACE, 2)
if b'\x00' in request_line:

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.

Better to check for null bytes before doing any parsing. Suggest moving this above request_line.strip().split(SPACE, 2)

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.

Even above the try-block. But also, it's probably a good idea to have a list of allowed chars.

In general, though, it'd be better to focus on implementing #201 (and resurrect #262).

@julianz- julianz- self-assigned this Jul 1, 2026
@andrewkernel andrewkernel force-pushed the fix-null-byte-request-line branch from 0f32bcb to 9525cd8 Compare July 7, 2026 21:53
@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
Reject request lines containing NUL bytes before parsing the request target and protocol. This keeps malformed request-line handling consistent with the existing bad request path and covers the case in the malformed request-line test matrix.
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.

3 participants