feat: add backup recovery, setup wizard and user-view guards
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Bound security-sensitive request bodies before JSON/multipart parsing."""
|
||||
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.types import ASGIApp, Message, Receive, Scope, Send
|
||||
|
||||
|
||||
# Encrypted backup limit is 32 MiB. Allow a bounded margin for the multipart
|
||||
# envelope; count streamed chunks as well as checking the untrusted header.
|
||||
RESTORE_BODY_LIMIT = 34 * 1024 * 1024
|
||||
BOOTSTRAP_BODY_LIMIT = 16 * 1024
|
||||
|
||||
|
||||
class InstallationBodyLimitMiddleware:
|
||||
def __init__(self, app: ASGIApp) -> None:
|
||||
self.app = app
|
||||
|
||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||
if scope["type"] != "http" or scope.get("method") != "POST":
|
||||
await self.app(scope, receive, send)
|
||||
return
|
||||
path = scope.get("path", "").rstrip("/")
|
||||
limit = {
|
||||
"/admin/backups/restore": RESTORE_BODY_LIMIT,
|
||||
"/admin/backups/export": BOOTSTRAP_BODY_LIMIT,
|
||||
"/setup/bootstrap": BOOTSTRAP_BODY_LIMIT,
|
||||
}.get(path)
|
||||
if limit is None:
|
||||
await self.app(scope, receive, send)
|
||||
return
|
||||
headers = dict(scope.get("headers", []))
|
||||
try:
|
||||
length = int(headers.get(b"content-length", b"0"))
|
||||
except ValueError:
|
||||
length = -1
|
||||
if length < 0 or length > limit:
|
||||
await JSONResponse({"detail": "Request body is too large or has an invalid length."}, status_code=413)(scope, receive, send)
|
||||
return
|
||||
received = 0
|
||||
|
||||
async def bounded_receive() -> Message:
|
||||
nonlocal received
|
||||
message = await receive()
|
||||
if message["type"] == "http.request":
|
||||
received += len(message.get("body", b""))
|
||||
if received > limit:
|
||||
raise HTTPException(status_code=413, detail="Request body is too large.")
|
||||
return message
|
||||
|
||||
await self.app(scope, bounded_receive, send)
|
||||
Reference in New Issue
Block a user