From 99c8c3ce40f9ac91482aceaabde1b30eca8a8d87 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Sun, 2 Aug 2026 19:49:03 +0800 Subject: [PATCH] fix: parse Telegram config path safely --- .github/scripts/test_renovate_app_version.py | 34 ++++++++++++ .../7.0.7/scripts/init.sh | 52 +++++++++++++------ .../latest/scripts/init.sh | 52 +++++++++++++------ 3 files changed, 106 insertions(+), 32 deletions(-) diff --git a/.github/scripts/test_renovate_app_version.py b/.github/scripts/test_renovate_app_version.py index 68f532707..711acbb41 100644 --- a/.github/scripts/test_renovate_app_version.py +++ b/.github/scripts/test_renovate_app_version.py @@ -531,6 +531,40 @@ class RenovateAppVersionTests(unittest.TestCase): any(str(volume).endswith(":/app/config.toml") for volume in service["volumes"]) ) + def test_telegram_init_reads_only_config_path_from_dotenv(self): + init_paths = sorted( + (REPO_ROOT / "apps" / "telegram-linuxserver").glob("*/scripts/init.sh") + ) + + self.assertTrue(init_paths) + for init_path in init_paths: + with self.subTest(version=init_path.parents[1].name): + with tempfile.TemporaryDirectory(prefix="telegram-init-") as tmp: + version_dir = pathlib.Path(tmp) / "version" + scripts_dir = version_dir / "scripts" + scripts_dir.mkdir(parents=True) + copied_init = scripts_dir / "init.sh" + copied_init.write_bytes(init_path.read_bytes()) + marker = version_dir / "dotenv-command-ran" + (version_dir / ".env").write_text( + "CONFIG_PATH=./data/config\n" + f"MARKER_PATH={marker}\n" + 'TITLE=$(touch "$MARKER_PATH")\n', + encoding="utf-8", + ) + + result = subprocess.run( + ["bash", str(copied_init)], + cwd=version_dir, + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(0, result.returncode, result.stderr) + self.assertTrue((version_dir / "data" / "config").is_dir()) + self.assertFalse(marker.exists()) + def test_wukongim_primary_service_and_sidecar_policy_are_explicit(self): primary = json.loads( (REPO_ROOT / ".github" / "renovate-primary-services.json").read_text( diff --git a/apps/telegram-linuxserver/7.0.7/scripts/init.sh b/apps/telegram-linuxserver/7.0.7/scripts/init.sh index 02efde0b4..4f42ea4af 100755 --- a/apps/telegram-linuxserver/7.0.7/scripts/init.sh +++ b/apps/telegram-linuxserver/7.0.7/scripts/init.sh @@ -1,21 +1,41 @@ #!/usr/bin/env bash set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if [[ -f "$SCRIPT_DIR/../.env" ]]; then - set -a - # shellcheck disable=SC1091 - source "$SCRIPT_DIR/../.env" - set +a +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +read_env_value() { + local key="$1" + local value="" + [[ -f "$ENV_FILE" ]] || return 0 + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +config_path="${CONFIG_PATH:-$(read_env_value CONFIG_PATH)}" +config_path="${config_path:-./data/config}" + +if [[ "$config_path" == /* ]]; then + resolved_config_path="$(realpath -m -- "$config_path")" + chown_config=false +else + resolved_config_path="$(realpath -m -- "$ROOT_DIR/${config_path#./}")" + case "$resolved_config_path" in + "$ROOT_DIR"/*) ;; + *) printf '%s\n' 'CONFIG_PATH must remain inside the application version directory' >&2; exit 1 ;; + esac + chown_config=true fi -paths=( - "${CONFIG_PATH:-./data/config}" -) - -mkdir -p "${paths[@]}" -for path in "${paths[@]}"; do - case "$path" in - ./*|../*) chown -R 1000:1000 "$path" 2>/dev/null || true ;; - esac -done +[[ ! -L "$resolved_config_path" ]] || { + printf '%s\n' 'CONFIG_PATH must not be a symbolic link' >&2 + exit 1 +} +mkdir -p -- "$resolved_config_path" +if [[ "$chown_config" == true ]]; then + chown -R 1000:1000 -- "$resolved_config_path" 2>/dev/null || true +fi diff --git a/apps/telegram-linuxserver/latest/scripts/init.sh b/apps/telegram-linuxserver/latest/scripts/init.sh index 02efde0b4..4f42ea4af 100755 --- a/apps/telegram-linuxserver/latest/scripts/init.sh +++ b/apps/telegram-linuxserver/latest/scripts/init.sh @@ -1,21 +1,41 @@ #!/usr/bin/env bash set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if [[ -f "$SCRIPT_DIR/../.env" ]]; then - set -a - # shellcheck disable=SC1091 - source "$SCRIPT_DIR/../.env" - set +a +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +read_env_value() { + local key="$1" + local value="" + [[ -f "$ENV_FILE" ]] || return 0 + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +config_path="${CONFIG_PATH:-$(read_env_value CONFIG_PATH)}" +config_path="${config_path:-./data/config}" + +if [[ "$config_path" == /* ]]; then + resolved_config_path="$(realpath -m -- "$config_path")" + chown_config=false +else + resolved_config_path="$(realpath -m -- "$ROOT_DIR/${config_path#./}")" + case "$resolved_config_path" in + "$ROOT_DIR"/*) ;; + *) printf '%s\n' 'CONFIG_PATH must remain inside the application version directory' >&2; exit 1 ;; + esac + chown_config=true fi -paths=( - "${CONFIG_PATH:-./data/config}" -) - -mkdir -p "${paths[@]}" -for path in "${paths[@]}"; do - case "$path" in - ./*|../*) chown -R 1000:1000 "$path" 2>/dev/null || true ;; - esac -done +[[ ! -L "$resolved_config_path" ]] || { + printf '%s\n' 'CONFIG_PATH must not be a symbolic link' >&2 + exit 1 +} +mkdir -p -- "$resolved_config_path" +if [[ "$chown_config" == true ]]; then + chown -R 1000:1000 -- "$resolved_config_path" 2>/dev/null || true +fi