mirror of
https://github.com/home-assistant/supervisor.git
synced 2026-04-02 00:07:16 +01:00
Reuse IMAGE_REGISTRY_REGEX for docker_image validation (#6667)
* Reuse IMAGE_REGISTRY_REGEX for docker_image validation Replace the monolithic regex in docker_image validator with a function-based approach that reuses get_registry_from_image() from docker.utils for robust registry detection. This properly handles domains, IPv4/IPv6 addresses, ports, and localhost while still rejecting tags (managed separately by the add-on system). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review feedback: reorder checks for efficiency Check falsy value before isinstance, and empty path before tag check, as suggested in PR review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,7 @@ from .const import (
|
||||
LogLevel,
|
||||
UpdateChannel,
|
||||
)
|
||||
from .docker.utils import get_registry_from_image
|
||||
from .utils.validate import validate_timezone
|
||||
|
||||
# Move to store.validate when addons_repository config removed
|
||||
@@ -60,9 +61,46 @@ RE_REGISTRY = re.compile(r"^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$")
|
||||
# pylint: disable=invalid-name
|
||||
network_port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535))
|
||||
wait_boot = vol.All(vol.Coerce(int), vol.Range(min=1, max=60))
|
||||
docker_image = vol.Match(
|
||||
r"^([a-z0-9][a-z0-9.\-]*(:[0-9]+)?/)*?([a-z0-9{][a-z0-9.\-_{}]*/)*?([a-z0-9{][a-z0-9.\-_{}]*)$"
|
||||
)
|
||||
# Path component pattern for Docker image names (supports {arch}/{machine} templates)
|
||||
_RE_IMAGE_PATH_COMPONENT = re.compile(r"^[a-z0-9{][a-z0-9.\-_{}]*$")
|
||||
|
||||
|
||||
def docker_image(image: str) -> str:
|
||||
"""Validate a Docker image name without tag.
|
||||
|
||||
Tags are not allowed as the version/tag is managed separately.
|
||||
Uses IMAGE_REGISTRY_REGEX from docker.utils for robust registry detection.
|
||||
"""
|
||||
if not image or not isinstance(image, str):
|
||||
raise vol.Invalid(f"Expected a non-empty string for docker image, got: {image}")
|
||||
|
||||
# Extract registry if present (handles domains, IPv4/IPv6, ports, localhost)
|
||||
registry = get_registry_from_image(image)
|
||||
if registry:
|
||||
# Registry must be lowercase
|
||||
if registry != registry.lower():
|
||||
raise vol.Invalid(f"Docker image registry must be lowercase: {image}")
|
||||
path = image[len(registry) + 1 :] # Remove "registry/" prefix
|
||||
else:
|
||||
path = image
|
||||
|
||||
if not path:
|
||||
raise vol.Invalid(f"Docker image has no name: {image}")
|
||||
|
||||
# Tags are not allowed - version is managed separately by the add-on system
|
||||
if ":" in path:
|
||||
raise vol.Invalid(f"Docker image must not contain a tag: {image}")
|
||||
|
||||
# Validate each path component (org/name)
|
||||
for component in path.split("/"):
|
||||
if not _RE_IMAGE_PATH_COMPONENT.match(component):
|
||||
raise vol.Invalid(
|
||||
f"Invalid Docker image path component '{component}' in: {image}"
|
||||
)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
uuid_match = vol.Match(r"^[0-9a-f]{32}$")
|
||||
sha256 = vol.Match(r"^[0-9a-f]{64}$")
|
||||
token = vol.Match(r"^[0-9a-f]{32,256}$")
|
||||
|
||||
@@ -25,14 +25,23 @@ IMAGE_NAME_GOOD = [
|
||||
"homeassistant/amd64-homeassistant",
|
||||
"ttl.sh/homeassistant",
|
||||
"myreg.local:8080/homeassistant",
|
||||
"localhost/myimage",
|
||||
"localhost:5000/myimage",
|
||||
"127.0.0.1/myimage",
|
||||
"127.0.0.1:5000/org/myimage",
|
||||
"[::1]:5000/myimage",
|
||||
"dockeruser/nice-app-1.2",
|
||||
"ghcr.io/blakeblackshear/frigate",
|
||||
]
|
||||
IMAGE_NAME_BAD = [
|
||||
"ghcr.io/home-assistant/homeassistant:123",
|
||||
"ghcr.io/blakeblackshear/frigate:stable-rocm",
|
||||
".ghcr.io/home-assistant/homeassistant",
|
||||
"HOMEASSISTANT/homeassistant",
|
||||
"homeassistant/HOMEASSISTANT",
|
||||
"homeassistant/_homeassistant",
|
||||
"homeassistant/-homeassistant",
|
||||
"GHCR.IO/home-assistant/homeassistant",
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user