Restrict notification action links to application paths
This commit is contained in:
@@ -3,12 +3,28 @@ from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
|
||||
NotificationStatus = Literal["pending", "queued", "sending", "sent", "failed", "skipped", "cancelled"]
|
||||
|
||||
|
||||
def normalize_notification_action_url(value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
candidate = value.strip()
|
||||
if not candidate:
|
||||
return None
|
||||
if (
|
||||
not candidate.startswith("/")
|
||||
or candidate.startswith("//")
|
||||
or "\\" in candidate
|
||||
or any(ord(character) < 32 or ord(character) == 127 for character in candidate)
|
||||
):
|
||||
raise ValueError("Notification action URL must be an application-relative path")
|
||||
return candidate
|
||||
|
||||
|
||||
class NotificationCreateRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
@@ -31,6 +47,11 @@ class NotificationCreateRequest(BaseModel):
|
||||
payload: dict[str, Any] = Field(default_factory=dict)
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
@field_validator("action_url")
|
||||
@classmethod
|
||||
def validate_action_url(cls, value: str | None) -> str | None:
|
||||
return normalize_notification_action_url(value)
|
||||
|
||||
|
||||
class NotificationUpdateRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
Reference in New Issue
Block a user