harden against symlink attacks

/config is owned by the unprivileged runtime user after the ownership sweep, so root operations on files there could be redirected by a planted symlink.

- go2rtc HomeKit setup: replace the root yq/jq normalization and chown with an O_NOFOLLOW helper (prepare_homekit.py), so a symlink at go2rtc_homekit.yml can't redirect a root write or chown onto another file
- go2rtc binary override: ignore /config/go2rtc whenever the service runs as root, so a planted binary can't exec as root under FRIGATE_ROOT_SERVICES
- sweep sentinel: read and write it through safe-sentinel, which trusts only a root-owned regular file and never follows a symlink, so it can't be forged to skip the migration or symlinked to clobber a root file
- ownership sweep: chown with -execdir so a parent directory swapped for a symlink mid-walk can't redirect the chown out of the volume
- validate inputs: restrict DEVICE_ACL_PATHS to /dev, require nonzero numeric EXTRA_GROUPS, and reject PUID/PGID that collide with the go2rtc ids
- docs: correct the TLS key ownership note to match what actually happens
This commit is contained in:
Josh Hawkins
2026-08-29 17:26:17 -05:00
parent baa00147b4
commit 46c189fced
7 changed files with 214 additions and 55 deletions
@@ -53,6 +53,15 @@ if [[ "$puid" -eq 0 || "$pgid" -eq 0 ]]; then
exit 1
fi
# Colliding with the go2rtc ids would merge the two users and collapse the
# separation between the main process and the network-facing restreamer.
go2rtc_uid="$(id -u go2rtc)"
go2rtc_gid="$(id -g go2rtc)"
if [[ "$puid" -eq "$go2rtc_uid" || "$pgid" -eq "$go2rtc_gid" ]]; then
echo "[ERROR] PUID/PGID must not equal the go2rtc service ids (${go2rtc_uid}:${go2rtc_gid})." >&2
exit 1
fi
current_uid="$(id -u frigate)"
current_gid="$(id -g frigate)"
@@ -71,6 +80,10 @@ fi
# EXTRA_GROUPS: numeric host GIDs granting device access (e.g. host render/video)
if [[ -n "${EXTRA_GROUPS:-}" ]]; then
for gid in ${EXTRA_GROUPS//,/ }; do
if ! [[ "$gid" =~ ^[0-9]+$ ]] || [[ "$gid" -eq 0 ]]; then
echo "[ERROR] EXTRA_GROUPS must be nonzero numeric GIDs, got '${gid}'" >&2
exit 1
fi
if ! getent group "$gid" >/dev/null; then
groupadd -o -g "$gid" "frigate-extra-${gid}"
fi