217 files

This commit is contained in:
Home Assistant Version Control
2026-07-30 23:59:38 +00:00
parent d43a63ad29
commit 7b5e46e702
217 changed files with 15978 additions and 3912 deletions
@@ -1,11 +1,20 @@
"""Defensive sanitization for config-flow input.
"""Defensive sanitization for the non-WebSocket write paths.
The WebSocket schemas enforce length and range caps on every str/int field at
the boundary. Config-flow forms accept arbitrary lengths because HA's selectors
don't enforce them. To keep both paths at parity (and prevent a malicious or
buggy programmatic config-flow caller from bloating ConfigEntry.data), every
config-flow save handler runs the relevant cap helper below right before
persisting.
the boundary, so the WS handlers need no sanitiser (they reject rather than
truncate). The other two write paths have no such guarantee and DO call the cap
helpers below right before persisting:
* **Config flow** — HA's selectors don't enforce lengths, so a malicious or
buggy programmatic flow caller could otherwise bloat ConfigEntry.data. Every
save handler caps.
* **Services** (``add_task`` / ``update_task``) — their voluptuous schemas
mirror the WS caps, but ``websocket/tasks_persist.py``'s
``async_create_task_simple`` / ``async_update_task_simple`` are plain Python
reachable in-process without going through a schema at all, so they cap too.
Keeping all three at parity is the point: a value one surface rejects must not
be writable through another.
"""
from __future__ import annotations
@@ -147,6 +156,13 @@ def cap_task_fields(task_data: dict[str, Any]) -> dict[str, Any]:
if rs not in ROTATION_STRATEGIES:
task_data.pop("rotation_strategy", None)
if task_data.get("required_completion_fields") is not None:
from .completion_requirements import sanitize_required_completion_fields
task_data["required_completion_fields"] = sanitize_required_completion_fields(
task_data["required_completion_fields"]
)
seed_rotation_assignee(task_data)
# v1.3.0: per-task on_complete_action — embedded HA service-call config.