diff --git a/backend/app/schemas.py b/backend/app/schemas.py index d7c6de77..508c3c28 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -57,6 +57,7 @@ class ConnectionCreateIn(BaseModel): min_length=1, max_length=4096, description=("PostgreSQL or Snowflake connection string. Not logged."), + pattern=r"^[^\x00-\x1F\x7F]+$", ) @@ -77,6 +78,7 @@ class ApplySqlIn(BaseModel): "Conservative PostgreSQL DDL subset with unquoted snake_case " "identifiers. Arbitrary SQL is rejected." ), + pattern=r"^[^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+$", ) # Default to a rolled-back pre-flight; the caller must opt in to persist. dry_run: bool = True @@ -190,7 +192,7 @@ class IndexRedundancyOut(BaseModel): class DiagramViewCreateIn(BaseModel): """Request body for saving an ERD canvas view.""" - name: str = Field(min_length=1, max_length=200) + name: str = Field(min_length=1, max_length=200, pattern=r"^[^\x00-\x1F\x7F]+$") # Opaque client layout (node positions, hidden tables, viewport). The API # bounds the serialized size in the endpoint to prevent abuse. layout_json: dict @@ -214,9 +216,9 @@ class DiagramViewDetailOut(DiagramViewOut): class TableAnnotationUpsertIn(BaseModel): """Request body for creating/updating a table annotation.""" - schema_name: str = Field(min_length=1, max_length=255) - relation_name: str = Field(min_length=1, max_length=255) - body: str = Field(min_length=1, max_length=10_000) + schema_name: str = Field(min_length=1, max_length=255, pattern=r"^[^\x00-\x1F\x7F]+$") + relation_name: str = Field(min_length=1, max_length=255, pattern=r"^[^\x00-\x1F\x7F]+$") + body: str = Field(min_length=1, max_length=10_000, pattern=r"^[^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+$") class TableAnnotationOut(BaseModel): @@ -285,7 +287,7 @@ class NamingLintOut(BaseModel): class DbmlConvertIn(BaseModel): """Request body for converting DBML text into a snapshot.""" - dbml: str = Field(min_length=1, max_length=524_288) + dbml: str = Field(min_length=1, max_length=524_288, pattern=r"^[^\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+$") include_ddl: bool = True dialect: Literal["postgresql", "snowflake"] = "postgresql" @@ -302,7 +304,7 @@ class DbmlConvertOut(BaseModel): class ApiKeyCreateIn(BaseModel): """Request body for creating an API key.""" - key_name: str = Field(min_length=1, max_length=128) + key_name: str = Field(min_length=1, max_length=128, pattern=r"^[^\x00-\x1F\x7F]+$") class ApiKeyOut(BaseModel):