GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [3.14] gh-119452: Fix a potential virtual memory allocation denial of service in http.server by serhiy-storchaka · Pull Request #119455 · python/cpython

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented May 23, 2024 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

The CGI server on Windows could consume the amount of memory specified in the Content-Length header of the request even if the client does not send such much data. Now it reads the POST request body by chunks, therefore the memory consumption is proportional to the amount of sent data.

  • Issue: OOM a potential denial of service in the CGI server on Windows #119452

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka serhiy-storchaka added type-security A security issue needs backport to 3.8 needs backport to 3.11 only security fixes needs backport to 3.12 only security fixes needs backport to 3.13 only security fixes labels May 23, 2024
@bedevere-app bedevere-app Bot added the awaiting core review label May 23, 2024
@bedevere-app bedevere-app Bot mentioned this pull request May 23, 2024
OOM a potential denial of service in the CGI server on Windows #119452
Closed
@gpshead
gpshead marked this pull request as draft May 24, 2024 19:58
@bedevere-app bedevere-app Bot removed the awaiting core review label May 24, 2024
@gpshead

gpshead commented May 24, 2024

Copy link
Copy Markdown
Member

I've marked this Draft for now as discussion on this on the security response team list is not complete. (we'll summarize that in a public issue once it has settled)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk hugovk removed the needs backport to 3.8 label Oct 9, 2024
@gpshead gpshead mentioned this pull request Jan 20, 2025
gh-119511: Fix a potential denial of service in imaplib #119514
Merged
@encukou

encukou commented Jan 27, 2025

Copy link
Copy Markdown
Member

See #119514 (comment) for results of the PSRT discussion.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@serhiy-storchaka serhiy-storchaka added the needs backport to 3.14 bugs and security fixes label May 8, 2025
@ambv ambv removed the needs backport to 3.9 label Oct 31, 2025
serhiy-storchaka added 2 commits November 18, 2025 15:49
@serhiy-storchaka
pythongh-119452: Fix OOM vulnerability in http.server
0f35918
The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
therefore the momory consumption is proportional to the amont of sent
data.
@serhiy-storchaka
Update the NEWS entry.
64620ea
@serhiy-storchaka
serhiy-storchaka force-pushed the http-server branch from 8d16f15 to 64620ea Compare November 18, 2025 13:52
@serhiy-storchaka
serhiy-storchaka changed the base branch from main to 3.14 November 18, 2025 13:53
@serhiy-storchaka
serhiy-storchaka marked this pull request as ready for review November 18, 2025 13:53
@bedevere-app bedevere-app Bot added the awaiting core review label Nov 18, 2025
@serhiy-storchaka
serhiy-storchaka requested a review from gpshead November 18, 2025 13:54
@serhiy-storchaka serhiy-storchaka changed the title gh-119452: Fix OOM vulnerability in http.server [3.14] gh-119452: Fix OOM vulnerability in http.server Nov 18, 2025
@serhiy-storchaka serhiy-storchaka removed the needs backport to 3.14 bugs and security fixes label Nov 18, 2025
gpshead
gpshead approved these changes Nov 24, 2025
View reviewed changes
Comment thread Lib/http/server.py
while (len(data) < nbytes and len(data) != cursize and
select.select([self.rfile._sock], [], [], 0)[0]):
cursize = len(data)
delta = min(cursize, nbytes - cursize)

@gpshead gpshead Nov 24, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

a comment that this is a geometric increase in read size (never more than doubling our current the length of data per loop iteration) could be good. otherwise it takes some staring at the code to understand what it is doing with the delta.

not a big deal though given CGIHTTPRequestHandler is gone in 3.15 onwards. :)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

serhiy-storchaka reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Nov 24, 2025
@hugovk
Merge branch '3.14' into http-server
9f06e71
@miss-islington-app

miss-islington-app Bot commented Dec 1, 2025

Copy link
Copy Markdown

Thanks @serhiy-storchaka for the PR 🌮🎉.. I'm working now to backport this PR to: 3.10, 3.11, 3.12, 3.13.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label Dec 1, 2025
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Dec 1, 2025
@serhiy-storchaka @miss-islington
[3.14] pythongh-119452: Fix a potential virtual memory allocation den…
3ed5bde
…ial of service in http.server (pythonGH-119455)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a)

Co-authored-by: Serhiy Storchaka <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Dec 1, 2025
@serhiy-storchaka @miss-islington
[3.14] pythongh-119452: Fix a potential virtual memory allocation den…
861bded
…ial of service in http.server (pythonGH-119455)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a)

Co-authored-by: Serhiy Storchaka <[email protected]>
@bedevere-app

bedevere-app Bot commented Dec 1, 2025

Copy link
Copy Markdown

GH-142130 is a backport of this pull request to the 3.13 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.13 only security fixes label Dec 1, 2025
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Dec 1, 2025
@serhiy-storchaka @miss-islington
[3.14] pythongh-119452: Fix a potential virtual memory allocation den…
d08d5ee
…ial of service in http.server (pythonGH-119455)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a)

Co-authored-by: Serhiy Storchaka <[email protected]>
@bedevere-app

bedevere-app Bot commented Dec 1, 2025

Copy link
Copy Markdown

GH-142131 is a backport of this pull request to the 3.12 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.12 only security fixes label Dec 1, 2025
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Dec 1, 2025
@serhiy-storchaka @miss-islington
[3.14] pythongh-119452: Fix a potential virtual memory allocation den…
fd940db
…ial of service in http.server (pythonGH-119455)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a)

Co-authored-by: Serhiy Storchaka <[email protected]>
@bedevere-app

bedevere-app Bot commented Dec 1, 2025

Copy link
Copy Markdown

GH-142132 is a backport of this pull request to the 3.11 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.11 only security fixes label Dec 1, 2025
@bedevere-app

bedevere-app Bot commented Dec 1, 2025

Copy link
Copy Markdown

GH-142133 is a backport of this pull request to the 3.10 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the needs backport to 3.10 label Dec 1, 2025
serhiy-storchaka added a commit that referenced this pull request Dec 1, 2025
@miss-islington @serhiy-storchaka
[3.13] gh-119452: Fix a potential virtual memory allocation denial of…
6c922bb
… service in http.server (GH-119455) (GH-142130)

The CGI server on Windows could consume the amount of memory specified
in the Content-Length header of the request even if the client does not
send such much data. Now it reads the POST request body by chunks,
so that the memory consumption is proportional to the amount of sent
data.
(cherry picked from commit 29c657a)

Co-authored-by: Serhiy Storchaka <[email protected]>
@serhiy-storchaka
serhiy-storchaka deleted the http-server branch December 1, 2025 15:26
@bedevere-bot

bedevere-bot commented Dec 1, 2025

Copy link
Copy Markdown

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot ARM64 MacOS M1 Refleaks NoGIL 3.13 (tier-2) has failed when building commit 6c922bb.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1396/builds/1823) and take a look at the build logs.
  4. Check if the failure is related to this commit (6c922bb) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1396/builds/1823

Failed tests:

  • test.test_multiprocessing_forkserver.test_processes

Failed subtests:

  • test_repr_rlock - test.test_multiprocessing_forkserver.test_processes.WithProcessesTestLock.test_repr_rlock
  • test_remote_shutdown_receives_trailing_data_on_slow_socket - test.test_asyncio.test_ssl.TestSSL.test_remote_shutdown_receives_trailing_data_on_slow_socket

Summary of the results of the build (if available):

==

Click to see traceback logs
Traceback (most recent call last):
  File "/Users/buildbot/buildarea/3.13.itamaro-macos-arm64-aws.macos-with-brew.refleak.nogil/build/Lib/test/_test_multiprocessing.py", line 1493, in test_repr_rlock
    self.assertEqual('<RLock(SomeOtherThread, nonzero)>', repr(lock))
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: '<RLock(SomeOtherThread, nonzero)>' != '<RLock(None, 0)>'
- <RLock(SomeOtherThread, nonzero)>
+ <RLock(None, 0)>


Traceback (most recent call last):
  File "/Users/buildbot/buildarea/3.13.itamaro-macos-arm64-aws.macos-with-brew.refleak.nogil/build/Lib/test/test_asyncio/test_ssl.py", line 1595, in test_remote_shutdown_receives_trailing_data_on_slow_socket
    self.loop.run_until_complete(client(srv.addr))
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/Users/buildbot/buildarea/3.13.itamaro-macos-arm64-aws.macos-with-brew.refleak.nogil/build/Lib/asyncio/base_events.py", line 725, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/Users/buildbot/buildarea/3.13.itamaro-macos-arm64-aws.macos-with-brew.refleak.nogil/build/Lib/test/test_asyncio/test_ssl.py", line 1573, in client
    wraps=socket_transport.write,
          ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'write'
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@colesbury

colesbury commented Dec 2, 2025 •
edited by hugovk
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

The 3.14 buildbot failure looks related to this change, but I don't see it reported on this PR: https://buildbot.python.org/#/builders/1684/builds/326

======================================================================
FAIL: test_large_content_length (test.test_httpservers.CGIHTTPServerTestCase.test_large_content_length)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\test_httpservers.py", line 1132, in test_large_content_length
    self.assertEqual(res.read(), b'%d %d' % (size, size) + self.linesep)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: b'4194304 2226830\r\n' != b'4194304 4194304\r\n'

----------------------------------------------------------------------
Ran 1 test in 0.336s
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Dec 2, 2025
[3.10] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) #142133
Closed
[3.11] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) #142132
Closed
[3.12] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) #142131
Closed
gpshead
gpshead reviewed Dec 2, 2025
View reviewed changes
Comment thread Lib/http/server.py
cursize = 0
data = self.rfile.read(min(nbytes, _MIN_READ_BUF_SIZE))
while (len(data) < nbytes and len(data) != cursize and
select.select([self.rfile._sock], [], [], 0)[0]):

@gpshead gpshead Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

the timeout=0 fourth arg here makes this non-blocking. the loop won't wait for further data to arrive. so we wind up not processing all of the data.

(Claude Code Opus 4.5 looking at the buildbot failure, issue, pr & branch triaged this FWIW)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@gpshead gpshead Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

why select at all here given we just want to block on reading another chunk? if the socket closes or errors, that'd return anyways.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

gpshead reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@hugovk hugovk Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Quick PR to make it blocking: #142176

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@encukou encukou Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

What should this do if the data doesn't arrive?
Wait forever, as in did before the fix?
Or doses this PR also meant fix the DoS? (I don't see how, is there a timeout setting or an implicit one?)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Dec 2, 2025

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

It was so long ago that I don't remember my train of thought, but playing around with the code I think I've recreated it.

I tested this code on Linux with have_fork = False. The tests failed because the underlying file object is unbuffered and read(n) can return less than n bytes. So the loop differs from loops in other fixes -- it continues until it reads 0 bytes. select() is needed to avoid blocking. Until now all worked on Linux and Windows on my computer and in CI tests. Perhaps this depends on the system load or on non-debug build (I only tested with the debug build).

Perhaps we need to use non-zero timeout (self.timeout?) and set it to non-None for tests.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@chris-eibl chris-eibl Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

xmlrpc/server.py has a similar code path

cpython/Lib/xmlrpc/server.py

Lines 483 to 493 in d3c888b

max_chunk_size = 10*1024*1024
size_remaining = int(self.headers["content-length"])
L = []
while size_remaining:
chunk_size = min(size_remaining, max_chunk_size)
chunk = self.rfile.read(chunk_size)
if not chunk:
break
L.append(chunk)
size_remaining -= len(L[-1])
data = b''.join(L)

but without a select. The last change there was ec1712a in 2012 adding the break if no data was read. So without a timeout it will suffer the same problem if content-length lies and less data is sent?

OTOH, does anybody out there operate a server without a timeout?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@gpshead gpshead Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Wait forever, as in did before the fix?

yes. this is intentionally a blocking read until sufficient data arrives or the connection dies. :)

fwiw, i missed this myself in the first code review. cursed unnamed parameters and presumptions about what 0 means. 😁

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@gpshead gpshead Dec 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

we do not need to add timeout logic here. just remove the select. this path was always intended to block until it got enough data or the socket is closed. the issue being protected against has nothing to do with blocking by holding a connection open, it's just about memory allocation.

This 1990s era server code was never meant to provide a robust server. There's a reason we got rid of it in 3.15.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

chris-eibl reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@serhiy-storchaka serhiy-storchaka Dec 3, 2025

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

We need timeout logic here to be able to test this change.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@hugovk hugovk mentioned this pull request Dec 2, 2025
[3.14] gh-119452: Block until data is read #142176
Closed
hugovk added a commit to hugovk/cpython that referenced this pull request Dec 2, 2025
@hugovk
Revert "[3.14] pythongh-119452: Fix a potential virtual memory alloca…
0ff45a8
…tion denial of service in http.server (pythonGH-119455)"

This reverts commit 29c657a.
@bedevere-app

bedevere-app Bot commented Dec 2, 2025

Copy link
Copy Markdown

GH-142184 is a backport of this pull request to the 3.14 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

hugovk added a commit to hugovk/cpython that referenced this pull request Dec 2, 2025
@hugovk
Revert "[3.13] pythongh-119452: Fix a potential virtual memory alloca…
ed03c6b
…tion denial of service in http.server (pythonGH-119455) (pythonGH-142130)"

This reverts commit 6c922bb.
Yhg1s pushed a commit that referenced this pull request Dec 2, 2025
@hugovk
[3.13] Revert "gh-119452: Fix a potential virtual memory allocation d…
a62caed
…enial of service in http.server (GH-119455) (GH-142130)" (#142185)

Revert "[3.13] gh-119452: Fix a potential virtual memory allocation denial of service in http.server (GH-119455) (GH-142130)"

This reverts commit 6c922bb.
hugovk added a commit that referenced this pull request Dec 2, 2025
@hugovk
[3.14] Revert "gh-119452: Fix a potential virtual memory allocation d…
49fe757
…enial of service in http.server (GH-119455)" (#142184)

Fix a potential virtual memory allocation denial of service in http.server (GH-119455)"
@serhiy-storchaka serhiy-storchaka mentioned this pull request Dec 2, 2025
[3.14] Try to fix the fix for gh-119452 #142180
Closed
@gpshead gpshead mentioned this pull request Dec 2, 2025
[3.14] gh-119452: Read/write CGI data using worker threads #142181
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@gpshead gpshead gpshead approved these changes
@encukou encukou encukou left review comments
@hugovk hugovk hugovk left review comments
@chris-eibl chris-eibl chris-eibl left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

type-security A security issue

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@serhiy-storchaka @gpshead @encukou @hugovk @bedevere-bot @colesbury @chris-eibl @ambv
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.