diff --git a/apps/api/plane/space/views/asset.py b/apps/api/plane/space/views/asset.py index bc20724ca80..7ecfc8d2afb 100644 --- a/apps/api/plane/space/views/asset.py +++ b/apps/api/plane/space/views/asset.py @@ -76,10 +76,21 @@ def post(self, request, anchor): # 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( @@ -109,9 +120,9 @@ def post(self, request, anchor): # 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, @@ -122,7 +133,7 @@ def post(self, request, anchor): # 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( {