fix: harden project writes and uploads
This commit is contained in:
@@ -3,6 +3,7 @@ import unittest
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from unittest.mock import patch
|
||||
|
||||
import httpx
|
||||
from starlette.applications import Starlette
|
||||
@@ -103,6 +104,59 @@ class UploadEndpointTests(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(temp_paths, [])
|
||||
self.assertFalse(any(issubclass(warning.category, ResourceWarning) for warning in caught))
|
||||
|
||||
async def test_upload_rejects_non_file_form_fields(self) -> None:
|
||||
http_client = FakeHttpClient()
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
async with await self._client_for(http_client, temp_dir) as client:
|
||||
response = await client.post(
|
||||
"/uploads",
|
||||
files={"file": ("quote.pdf", b"pdf", "application/pdf")},
|
||||
data={"description": "quote"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()["error"]["code"], "invalid_upload")
|
||||
self.assertEqual(http_client.calls, [])
|
||||
self.assertEqual(list(Path(temp_dir).iterdir()), [])
|
||||
|
||||
async def test_upload_rejects_oversized_misreported_chunked_body_before_multipart_parsing(self) -> None:
|
||||
http_client = FakeHttpClient()
|
||||
endpoint = UploadEndpoint(http_client, max_bytes=5, temp_dir="/tmp")
|
||||
parsed = False
|
||||
|
||||
async def forbidden_form(self):
|
||||
nonlocal parsed
|
||||
parsed = True
|
||||
self.fail("multipart parsing must not begin for an oversized body")
|
||||
|
||||
body = b"x" * (5 + 65537)
|
||||
scope = {
|
||||
"type": "http",
|
||||
"method": "POST",
|
||||
"path": "/uploads",
|
||||
"headers": [
|
||||
(b"content-type", b"multipart/form-data; boundary=test"),
|
||||
(b"content-length", b"1"),
|
||||
],
|
||||
}
|
||||
messages = [
|
||||
{"type": "http.request", "body": body[:10], "more_body": True},
|
||||
{"type": "http.request", "body": body[10:], "more_body": False},
|
||||
]
|
||||
|
||||
async def receive():
|
||||
return messages.pop(0)
|
||||
|
||||
from starlette.requests import Request
|
||||
|
||||
starlette_request = Request(scope, receive=receive)
|
||||
with patch("nocobase_crm_mcp.uploads.Request.form", new=forbidden_form):
|
||||
response = await endpoint(starlette_request)
|
||||
|
||||
self.assertEqual(response.status_code, 413)
|
||||
self.assertFalse(parsed)
|
||||
self.assertEqual(http_client.calls, [])
|
||||
|
||||
async def test_upload_rejects_disallowed_mime_type_before_calling_nocobase(self) -> None:
|
||||
http_client = FakeHttpClient()
|
||||
with TemporaryDirectory() as temp_dir:
|
||||
|
||||
Reference in New Issue
Block a user