From 2febd921bc1bf9cdb3d1e603531fa273af74574d Mon Sep 17 00:00:00 2001 From: anti Date: Mon, 20 Apr 2026 01:26:07 -0400 Subject: [PATCH] fix(models): added lenght validation to the common name, which per RFC 5280 must be max =< 64 --- decnet/web/db/models.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/decnet/web/db/models.py b/decnet/web/db/models.py index fe0b94c..5d75bc7 100644 --- a/decnet/web/db/models.py +++ b/decnet/web/db/models.py @@ -293,10 +293,30 @@ class HealthResponse(BaseModel): # DeckyShard — live above; these are the HTTP-facing shapes. class SwarmEnrollRequest(BaseModel): - name: str = PydanticField(..., min_length=1, max_length=128) - address: str = PydanticField(..., description="IP or DNS the master uses to reach the worker") + # x509 CommonName is capped at 64 bytes (RFC 5280 UB-common-name) — the + # cert issuer would reject anything longer with a ValueError. + # Pattern: ASCII hostname-safe characters only. The name is embedded + # both in the CN and as a SAN DNS entry; x509.DNSName only accepts + # A-label ASCII, so non-ASCII would blow up at issuance. + name: str = PydanticField( + ..., min_length=1, max_length=64, + pattern=r"^[A-Za-z0-9][A-Za-z0-9._\-]*$", + ) + address: str = PydanticField( + ..., min_length=1, max_length=253, + pattern=r"^[A-Za-z0-9][A-Za-z0-9._:\-]*$", + description="IP or DNS the master uses to reach the worker", + ) agent_port: int = PydanticField(default=8765, ge=1, le=65535) - sans: list[str] = PydanticField( + sans: list[ + Annotated[ + str, + PydanticField( + min_length=1, max_length=253, + pattern=r"^[A-Za-z0-9][A-Za-z0-9._:\-]*$", + ), + ] + ] = PydanticField( default_factory=list, description="Extra SANs (IPs / hostnames) to embed in the worker cert", )