-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Summary
A potential Denial of Service (DoS) vulnerability exists in Reflex's backend file upload handling. The current implementation reads the entire content of uploaded files into memory (io.BytesIO) without enforcement of size limits, which can lead to rapid memory exhaustion and server crashes.
Technical Analysis
In reflex/app.py (L1767), the code iterates through incoming files and performs a full read into a BytesIO object:
# reflex/app.py
file_copies = []
for file in files:
content_copy = io.BytesIO()
content_copy.write(await file.read()) # <--- Critical Point
content_copy.seek(0)
# ...Impact
An attacker can exploit this by sending multiple concurrent requests with large files. Since await file.read() loads the full payload into RAM, it will quickly consume all available system memory, potentially triggering the OOM killer or rendering the server unresponsive.
Proof of Concept (Isolated Test)
The following script replicates the vulnerable logic and demonstrates the linear memory spike:
import asyncio
import io
import os
import psutil
class MockUploadFile:
def __init__(self, size):
self.size = size
async def read(self):
return b"A" * self.size
async def simulate_reflex_upload():
process = psutil.Process(os.getpid())
print(f"[*] Initial Memory Usage: {process.memory_info().rss / 1024 / 1024:.2f} MB")
FILE_SIZE = 500 * 1024 * 1024 # 500MB
file = MockUploadFile(FILE_SIZE)
print(f"[*] Executing Reflex logic: io.BytesIO().write(await file.read())...")
content_copy = io.BytesIO()
content_copy.write(await file.read())
print(f"[*] Post-Execution Memory Usage: {process.memory_info().rss / 1024 / 1024:.2f} MB")
if __name__ == "__main__":
asyncio.run(simulate_reflex_upload())Recommended Mitigation
- Configurable Size Limits: Introduce a
MAX_UPLOAD_SIZEsetting to reject large files before they are read. - Streaming/Spilling to Disk: Leverage FastAPI's
UploadFileability to spill to disk or usetempfile.TemporaryFileinstead ofio.BytesIOfor large payloads.