diff --git a/api/schemas/crawler.py b/api/schemas/crawler.py index 6eb3b1b7e..ba61b2a3b 100644 --- a/api/schemas/crawler.py +++ b/api/schemas/crawler.py @@ -16,9 +16,10 @@ # 详细许可条款请参阅项目根目录下的LICENSE文件。 # 使用本代码即表示您同意遵守上述原则和LICENSE中的所有条款。 +import re from enum import Enum from typing import Optional, Literal -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator MAX_API_LIMIT_COUNT = 10000 @@ -74,6 +75,23 @@ class CrawlerStartRequest(BaseModel): save_option: SaveDataOptionEnum = SaveDataOptionEnum.JSONL cookies: str = "" headless: bool = False + + @field_validator("keywords", "cookies", mode="before") + @classmethod + def sanitize_free_text(cls, v: str) -> str: + """Remove null bytes and newlines to prevent argument injection.""" + if isinstance(v, str): + return re.sub(r"[\x00\n\r]", "", v) + return v + + @field_validator("specified_ids", "creator_ids", mode="before") + @classmethod + def validate_ids(cls, v: str) -> str: + """Allow only alphanumeric characters, commas, hyphens, and underscores.""" + if isinstance(v, str) and v: + if not re.fullmatch(r"[A-Za-z0-9,_\-\s]*", v): + raise ValueError("IDs must contain only alphanumeric characters, commas, hyphens, or underscores.") + return v max_notes_count: Optional[int] = Field(default=None, ge=1, le=MAX_API_LIMIT_COUNT) max_comments_count: Optional[int] = Field(default=None, ge=1, le=MAX_API_LIMIT_COUNT)