From 7aef571b27844320c0e8e20e569ba9ca5e239fba Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 21:10:22 +0000 Subject: [PATCH] authelia: strip YAML quoting from parsed domain/portal-URL values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of the recurring Mealie OIDC "unexpected character '/' in variable name" failure, confirmed against the user's actual configuration.yml byte content: this repo's own scripts write authelia_url/domain unquoted, but YAML makes quoting optional, and a hand-edited config can add single or double quotes around the value (here: authelia_url: 'https://authelia.example.com.'). awk's `print $2`/`print $3` is a naive whitespace-split token grab that doesn't know about YAML quoting, so it captured the value WITH the literal quote characters attached. The generated discovery URL then came out `'https://authelia.example.com.'/.well-known/openid-configuration` — Docker Compose's env parser closed the quoted value at that embedded closing quote and choked on the trailing text as an invalid new token. The earlier \r-stripping commit was a real but different fix (a CRLF-tainted line fails to match these anchored awk patterns at all) — it didn't cause and couldn't have fixed this. Both guards are needed and now both apply, in both _authelia_provision_oidc_client() (domain and portal URL) and the same latent bug in _authelia_add_oidc_client()'s domain parse. Verified end-to-end: reconstructed the user's exact reported byte content (od -c dump) in a synthetic configuration.yml, ran the actual _authelia_ensure_oidc_provider/_authelia_provision_oidc_client/ _mealie_offer_authelia_oidc functions against it (docker calls stubbed), and confirmed the generated .env line is now a single clean line with no embedded quotes or split. --- services/authelia.sh | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/services/authelia.sh b/services/authelia.sh index 8c67ee0..f2f3511 100644 --- a/services/authelia.sh +++ b/services/authelia.sh @@ -1741,11 +1741,24 @@ _authelia_provision_oidc_client() { # line-anchored awk pattern below fail to match at all, not just leave a # stray \r in the captured value: " cookies:\r" doesn't match # /^ cookies:$/ since $ anchors end-of-string and the \r is still part - # of it. Confirmed live: this exact case produced a "line 12: unexpected - # character '/' in variable name" failure in Mealie's .env once a - # \r-tainted authelia_url value got concatenated with more text after - # it — Docker Compose's env parser treats a bare \r as a line break too. - OIDC_AUTHELIA_DOMAIN="$(tr -d '\r' < "$CONFIG_FILE" | awk '/^ cookies:$/{f=1; next} f && /domain:/{print $3; exit}')" + # of it. Also strip a leading/trailing quote character: these fields are + # unquoted in every value this repo's own scripts write, but YAML makes + # quoting optional and a hand-edited config can add single or double + # quotes around the value. awk's `print $2`/`print $3` is a naive + # whitespace-split token grab that doesn't know about YAML quoting, so a + # quoted value comes back WITH the literal quote characters still + # attached. Confirmed live: this is what actually caused a "line 12: + # unexpected character '/' in variable name" failure in Mealie's + # .env — an authelia_url value hand-edited to + # `authelia_url: 'https://authelia.example.com'` got captured as the + # literal string including both single quotes, so the generated + # discovery URL came out `'https://authelia.example.com'/.well-known/...` + # — Docker Compose's env parser closed the quoted value at that + # embedded closing quote and choked on everything after it as a new, + # invalid token. (The earlier \r-stripping guards a different, + # also-real failure mode — a CRLF-tainted line failing to match these + # anchored patterns at all — not this one; both are needed.) + OIDC_AUTHELIA_DOMAIN="$(tr -d '\r' < "$CONFIG_FILE" | awk '/^ cookies:$/{f=1; next} f && /domain:/{print $3; exit}' | sed "s/^[\"']//; s/[\"']\$//")" if [ -z "$OIDC_AUTHELIA_DOMAIN" ]; then log_warning "Couldn't determine this Authelia instance's domain from $CONFIG_FILE — aborting." return 1 @@ -1755,7 +1768,7 @@ _authelia_provision_oidc_client() { # "auth." prefix — see the OIDC_AUTHELIA_PORTAL_URL out-param comment # above for why this can't be hardcoded. Falls back to the "auth." # default only if parsing somehow comes up empty. - OIDC_AUTHELIA_PORTAL_URL="$(tr -d '\r' < "$CONFIG_FILE" | awk '/^ cookies:$/{f=1; next} f && /authelia_url:/{print $2; exit}')" + OIDC_AUTHELIA_PORTAL_URL="$(tr -d '\r' < "$CONFIG_FILE" | awk '/^ cookies:$/{f=1; next} f && /authelia_url:/{print $2; exit}' | sed "s/^[\"']//; s/[\"']\$//")" [ -z "$OIDC_AUTHELIA_PORTAL_URL" ] && OIDC_AUTHELIA_PORTAL_URL="https://auth.${OIDC_AUTHELIA_DOMAIN}" # A stale registration (e.g. from the interactive "Register an app" menu @@ -1851,7 +1864,7 @@ _authelia_add_oidc_client() { # below only to suggest a domain default — _authelia_provision_oidc_client # re-derives its own copy independently. local AUTHELIA_DOMAIN - AUTHELIA_DOMAIN="$(awk '/^ cookies:$/{f=1; next} f && /domain:/{print $3; exit}' "$CONFIG_FILE")" + AUTHELIA_DOMAIN="$(tr -d '\r' < "$CONFIG_FILE" | awk '/^ cookies:$/{f=1; next} f && /domain:/{print $3; exit}' | sed "s/^[\"']//; s/[\"']\$//")" if [ -z "$AUTHELIA_DOMAIN" ]; then log_warning "Couldn't determine this Authelia instance's domain from $CONFIG_FILE — aborting." return 1