mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-13 20:26:29 +00:00
Improve addon slug validation (#4188)
This commit is contained in:
parent
2a625defc0
commit
8fc036874a
@ -26,3 +26,5 @@ ADDON_UPDATE_CONDITIONS = [
|
||||
JobCondition.PLUGINS_UPDATED,
|
||||
JobCondition.SUPERVISOR_UPDATED,
|
||||
]
|
||||
|
||||
RE_SLUG = r"[-_.A-Za-z0-9]+"
|
||||
|
@ -109,7 +109,7 @@ from ..validate import (
|
||||
uuid_match,
|
||||
version_tag,
|
||||
)
|
||||
from .const import ATTR_BACKUP, ATTR_CODENOTARY, AddonBackupMode
|
||||
from .const import ATTR_BACKUP, ATTR_CODENOTARY, RE_SLUG, AddonBackupMode
|
||||
from .options import RE_SCHEMA_ELEMENT
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
@ -147,6 +147,8 @@ RE_MACHINE = re.compile(
|
||||
r")$"
|
||||
)
|
||||
|
||||
RE_SLUG_FIELD = re.compile(r"^" + RE_SLUG + r"$")
|
||||
|
||||
|
||||
def _warn_addon_config(config: dict[str, Any]):
|
||||
"""Warn about miss configs."""
|
||||
@ -252,7 +254,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_NAME): str,
|
||||
vol.Required(ATTR_VERSION): version_tag,
|
||||
vol.Required(ATTR_SLUG): str,
|
||||
vol.Required(ATTR_SLUG): vol.Match(RE_SLUG_FIELD),
|
||||
vol.Required(ATTR_DESCRIPTON): str,
|
||||
vol.Required(ATTR_ARCH): [vol.In(ARCH_ALL)],
|
||||
vol.Optional(ATTR_MACHINE): vol.All([vol.Match(RE_MACHINE)], vol.Unique()),
|
||||
|
@ -8,6 +8,7 @@ from aiohttp.web import Request, RequestHandler, Response, middleware
|
||||
from aiohttp.web_exceptions import HTTPBadRequest, HTTPForbidden, HTTPUnauthorized
|
||||
from awesomeversion import AwesomeVersion
|
||||
|
||||
from ...addons.const import RE_SLUG
|
||||
from ...const import (
|
||||
REQUEST_FROM,
|
||||
ROLE_ADMIN,
|
||||
@ -27,7 +28,7 @@ _CORE_VERSION: Final = AwesomeVersion("2023.3.0")
|
||||
|
||||
_CORE_FRONTEND_PATHS: Final = (
|
||||
r"|/app/.*\.(?:js|gz|json|map)"
|
||||
r"|/(store/)?addons/[^/]+/(logo|icon)"
|
||||
r"|/(store/)?addons/" + RE_SLUG + r"/(logo|icon)"
|
||||
)
|
||||
|
||||
CORE_FRONTEND: Final = re.compile(
|
||||
@ -51,7 +52,7 @@ NO_SECURITY_CHECK: Final = re.compile(
|
||||
r"|/core/api/.*"
|
||||
r"|/core/websocket"
|
||||
r"|/supervisor/ping"
|
||||
r"|/ingress/[^/]+/.*"
|
||||
r"|/ingress/[-_A-Za-z0-9]+/.*"
|
||||
+ _CORE_FRONTEND_PATHS
|
||||
+ r")$"
|
||||
)
|
||||
@ -98,7 +99,7 @@ ADDONS_ROLE_ACCESS: dict[str, re.Pattern] = {
|
||||
ROLE_MANAGER: re.compile(
|
||||
r"^(?:"
|
||||
r"|/.+/info"
|
||||
r"|/addons(?:/[^/]+/(?!security).+|/reload)?"
|
||||
r"|/addons(?:/" + RE_SLUG + r"/(?!security).+|/reload)?"
|
||||
r"|/audio/.+"
|
||||
r"|/auth/cache"
|
||||
r"|/cli/.+"
|
||||
|
@ -249,3 +249,38 @@ def test_watchdog_url():
|
||||
):
|
||||
config["watchdog"] = test_options
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
|
||||
def test_valid_slug():
|
||||
"""Test valid and invalid addon slugs."""
|
||||
config = load_json_fixture("basic-addon-config.json")
|
||||
|
||||
# All examples pulled from https://analytics.home-assistant.io/addons.json
|
||||
config["slug"] = "uptime-kuma"
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
config["slug"] = "hassio_google_drive_backup"
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
config["slug"] = "paradox_alarm_interface_3.x"
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
config["slug"] = "Lupusec2Mqtt"
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
# No whitespace
|
||||
config["slug"] = "my addon"
|
||||
with pytest.raises(vol.Invalid):
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
# No url control chars (or other non-word ascii characters)
|
||||
config["slug"] = "a/b_&_c\\d_@ddon$:_test=#2?"
|
||||
with pytest.raises(vol.Invalid):
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
# No unicode
|
||||
config["slug"] = "complemento telefónico"
|
||||
with pytest.raises(vol.Invalid):
|
||||
assert vd.SCHEMA_ADDON_CONFIG(config)
|
||||
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user