I think most web frameworks should, by default, prevent DDoS and Slow Loris attacks. There's a bunch of places this needs to happen, here are some ideas:
A Slowloris middleware that kills the connection if you spend more than X seconds waiting on the client.
A middleware that limits total payload size for uploads.
Stricter form parsing
With regards to form parsing, we currently rely entirely on Starlette and blindly call Request.form(), which is not great given we have a ton of metadata about what we expect in the form. Inspired by multer I would like something like this:
from typing import Annotated, List
import annotated_types as at
from xpresso.bodies import FormField, FormFile, Multipart
MB = 2**20
# Define a model, this restricts the fields that can be included
# unless extra = "allow" is set on the Pydantic model itself
# This protects against attacks that spam a lot of fields
class MyForm(BaseModel):
# Restrict the age field to 4 bytes
# If the client sends more than this we'll error immediately
# We also use Pydantic to automatically parse the string into an int
age: Annotated[int, FormField(), at.Len(max_length=10)]
# Images is a list of bytes
# We first declare that the list itself cannot have more than 10 items
# Xpresso would have to check if the type is a List and if so check if `max_items` is set on the field
# as a special case since we can use this to error before reading more fields
# (I think re-using Pydantic's metadata makes sense when possible)
# We also limit each image to 10 MB and will immediately stop parsing and error
# if it is larger than this
images: Annotated[List[Annotated[bytes, FormFile(), at.Len(max_length=10*MB], at.Len(max_length=10)]
extra_data: Annotated[bytes, FormFile()] # just to demonstrate max_length below
# restrict the size (in bytes) of the entire body to 100MB
async def endpoint(form: Annotated[MyForm, Multipart(max_length=100*MB)]):
...
This is a super explicit and perhaps overkill example, but it gets the idea across.
With JSON or raw bytes we can at least limit the total size of the request body:
I think most web frameworks should, by default, prevent DDoS and Slow Loris attacks. There's a bunch of places this needs to happen, here are some ideas:
Slowloris
middleware that kills the connection if you spend more than X seconds waiting on the client.With regards to form parsing, we currently rely entirely on Starlette and blindly call
Request.form()
, which is not great given we have a ton of metadata about what we expect in the form. Inspired by multer I would like something like this:This is a super explicit and perhaps overkill example, but it gets the idea across.
With JSON or raw bytes we can at least limit the total size of the request body: