mirror of
https://github.com/makeplane/plane.git
synced 2026-08-29 10:08:51 +02:00
fix: enforce FILE_SIZE_LIMIT on published Space asset upload (#9242)
* fix(api): enforce FILE_SIZE_LIMIT on published Space asset upload
The public Space asset upload endpoint
(POST /api/public/assets/v2/anchor/{anchor}/) trusted the client-supplied
`size` value end-to-end: it was stored on the FileAsset and passed straight
to generate_presigned_post(), which uses it as the S3/MinIO policy bound
(["content-length-range", 1, file_size]). This let an authenticated user
obtain a signed upload policy exceeding the instance's FILE_SIZE_LIMIT.
Cap the value with `size_limit = min(size, settings.FILE_SIZE_LIMIT)` and use
it consistently for the stored asset metadata and the presigned POST policy,
matching every other asset upload endpoint.
* fix(api): clamp Space asset size to a valid lower bound
Address review feedback: reject malformed (non-integer) `size` with 400 and
clamp the value to [1, FILE_SIZE_LIMIT] via max(1, min(...)) so the presigned
content-length-range is always valid and no non-positive size is persisted.
This commit is contained in:
committed by
GitHub
parent
c5951e7def
commit
25c6843fce
@@ -86,10 +86,21 @@ class EntityAssetEndpoint(BaseAPIView):
|
||||
# Get the asset
|
||||
name = sanitize_filename(request.data.get("name")) or "unnamed"
|
||||
type = request.data.get("type", "image/jpeg")
|
||||
size = int(request.data.get("size", settings.FILE_SIZE_LIMIT))
|
||||
try:
|
||||
size = int(request.data.get("size", settings.FILE_SIZE_LIMIT))
|
||||
except (TypeError, ValueError):
|
||||
return Response(
|
||||
{"error": "Invalid size.", "status": False},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
entity_type = request.data.get("entity_type", "")
|
||||
entity_identifier = request.data.get("entity_identifier")
|
||||
|
||||
# Clamp the client-provided size to [1, FILE_SIZE_LIMIT] so the signed
|
||||
# upload policy cannot exceed the instance limit and always carries a
|
||||
# valid content-length-range bound
|
||||
size_limit = max(1, min(size, settings.FILE_SIZE_LIMIT))
|
||||
|
||||
# Check if the entity type is allowed
|
||||
if entity_type not in FileAsset.EntityTypeContext.values:
|
||||
return Response(
|
||||
@@ -119,9 +130,9 @@ class EntityAssetEndpoint(BaseAPIView):
|
||||
|
||||
# Create a File Asset
|
||||
asset = FileAsset.objects.create(
|
||||
attributes={"name": name, "type": type, "size": size},
|
||||
attributes={"name": name, "type": type, "size": size_limit},
|
||||
asset=asset_key,
|
||||
size=size,
|
||||
size=size_limit,
|
||||
workspace=deploy_board.workspace,
|
||||
created_by=request.user,
|
||||
entity_type=entity_type,
|
||||
@@ -132,7 +143,7 @@ class EntityAssetEndpoint(BaseAPIView):
|
||||
# Get the presigned URL
|
||||
storage = S3Storage(request=request)
|
||||
# Generate a presigned URL to share an S3 object
|
||||
presigned_url = storage.generate_presigned_post(object_name=asset_key, file_type=type, file_size=size)
|
||||
presigned_url = storage.generate_presigned_post(object_name=asset_key, file_type=type, file_size=size_limit)
|
||||
# Return the presigned URL
|
||||
return Response(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user