fix(marker): validate marker name and expose enabled via REST

Add a name pattern constraint to MarkerCreate schema (alphanumeric +
_.-) to prevent injection into uBridge commands, with a matching
defense-in-depth check in _ubridge_add_marker_filter for hand-edited
topology files. Also add the missing "enabled" field to MarkerCreate
and pass it through the PUT route so the documented toggle actually
works.
This commit is contained in:
YueGuobin 2026-07-13 15:04:55 +08:00
parent a495b5ddf2
commit 7e4600b5a1
No known key found for this signature in database
3 changed files with 17 additions and 2 deletions

View File

@ -506,6 +506,7 @@ async def update_marker(
bpf=marker_data.bpf if marker_data.bpf else None,
tag=marker_data.tag,
color=marker_data.color,
enabled=marker_data.enabled,
)
return link.markers.get(marker_name, {})

View File

@ -1091,6 +1091,11 @@ class BaseNode:
"""
# mark <bpf> [tag <id>] [pcap <path>] — tag/pcap keyword pairs, any order.
# name travels from the controller REST layer (MarkerCreate schema) but is
# validated here too as defense-in-depth against hand-edited topology files.
_MARKER_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.-]*$")
if not _MARKER_NAME_RE.match(name):
raise UbridgeError(f"Invalid marker name: {name!r}")
cmd = 'bridge add_packet_filter {bridge} {name} mark "{bpf}"'.format(
bridge=bridge_name, name=name, bpf=bpf
)

View File

@ -149,13 +149,22 @@ class MarkerCreate(BaseModel):
absent) but always set when the controller forwards to the compute.
"""
name: Optional[str] = None
name: Optional[str] = Field(
None,
pattern=r"^[A-Za-z0-9][A-Za-z0-9_.-]*$",
max_length=128,
description="Unique marker name on the link. Auto-generated when absent.",
)
bpf: str
tag: Optional[int] = None
link_id: Optional[str] = None
color: Optional[str] = Field(
None,
description="User-chosen hex color for this marker in the Web UI, e.g. '#ff5722'"
description="User-chosen hex color for this marker in the Web UI, e.g. '#ff5722'",
)
enabled: Optional[bool] = Field(
None,
description="Whether the marker is active. Defaults to true on creation.",
)