chore: added validation for description (#7507)

* added PageBinaryUpdateSerializer for binary data validation and update

* chore: added validation for description

* chore: removed the duplicated file

* Fixed coderabbit comments

- Improve content validation by consolidating patterns and enhancing recursion checks

- Updated `PageBinaryUpdateSerializer` to simplify assignment of validated data.
- Enhanced `content_validator.py` with consolidated dangerous patterns and added recursion depth checks to prevent stack overflow during validation.
- Improved readability and maintainability of validation functions by using constants for patterns.

---------

Co-authored-by: Dheeraj Kumar Ketireddy <dheeru0198@gmail.com>
This commit is contained in:
Bavisetti Narayan 2025-07-30 14:19:49 +05:30 committed by GitHub
parent b93883fc14
commit 69d5cd183f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 613 additions and 16 deletions

View file

@ -21,6 +21,11 @@ from plane.db.models import (
State,
User,
)
from plane.utils.content_validator import (
validate_html_content,
validate_json_content,
validate_binary_data,
)
from .base import BaseSerializer
from .cycle import CycleLiteSerializer, CycleSerializer
@ -75,6 +80,22 @@ class IssueSerializer(BaseSerializer):
except Exception:
raise serializers.ValidationError("Invalid HTML passed")
# Validate description content for security
if data.get("description"):
is_valid, error_msg = validate_json_content(data["description"])
if not is_valid:
raise serializers.ValidationError({"description": error_msg})
if data.get("description_html"):
is_valid, error_msg = validate_html_content(data["description_html"])
if not is_valid:
raise serializers.ValidationError({"description_html": error_msg})
if data.get("description_binary"):
is_valid, error_msg = validate_binary_data(data["description_binary"])
if not is_valid:
raise serializers.ValidationError({"description_binary": error_msg})
# Validate assignees are from project
if data.get("assignees", []):
data["assignees"] = ProjectMember.objects.filter(

View file

@ -3,6 +3,11 @@ from rest_framework import serializers
# Module imports
from plane.db.models import Project, ProjectIdentifier, WorkspaceMember
from plane.utils.content_validator import (
validate_html_content,
validate_json_content,
validate_binary_data,
)
from .base import BaseSerializer
@ -57,6 +62,29 @@ class ProjectSerializer(BaseSerializer):
"Default assignee should be a user in the workspace"
)
# Validate description content for security
if "description" in data and data["description"]:
# For Project, description might be text field, not JSON
if isinstance(data["description"], dict):
is_valid, error_msg = validate_json_content(data["description"])
if not is_valid:
raise serializers.ValidationError({"description": error_msg})
if "description_text" in data and data["description_text"]:
is_valid, error_msg = validate_json_content(data["description_text"])
if not is_valid:
raise serializers.ValidationError({"description_text": error_msg})
if "description_html" in data and data["description_html"]:
if isinstance(data["description_html"], dict):
is_valid, error_msg = validate_json_content(data["description_html"])
else:
is_valid, error_msg = validate_html_content(
str(data["description_html"])
)
if not is_valid:
raise serializers.ValidationError({"description_html": error_msg})
return data
def create(self, validated_data):