From 3d5d26c20c167f8d1c81ae933709763af3af0cd8 Mon Sep 17 00:00:00 2001 From: mptyl Date: Tue, 4 Aug 2026 08:29:02 +0200 Subject: [PATCH] fix: validate workspace secret source paths --- scripts/test-verify-workspace-install-docs.sh | 5 +- scripts/verify-workspace-install-docs.sh | 47 +++++++++++++------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/scripts/test-verify-workspace-install-docs.sh b/scripts/test-verify-workspace-install-docs.sh index c74c880d..d0506271 100755 --- a/scripts/test-verify-workspace-install-docs.sh +++ b/scripts/test-verify-workspace-install-docs.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Regression test for copyable installation examples and secret-file validation. +# Regression test for copyable installation examples and secret-path validation. set -euo pipefail root="$(cd "$(dirname "$0")/.." && pwd -P)" @@ -15,7 +15,8 @@ for fixture in \ "copied SSH Git override fixture" \ "copied connector binding/secret fixture" \ "core process sees connector bindings and secret files" \ - "non-path secret-file fixture rejected"; do + "non-path secret-file fixture rejected" \ + "literal secret-source fixture rejected"; do grep -Fqx "$fixture passed" "$output" >/dev/null || { echo "missing fixture verification: $fixture" >&2 cat "$output" >&2 diff --git a/scripts/verify-workspace-install-docs.sh b/scripts/verify-workspace-install-docs.sh index 24f0d9e2..5d67620e 100755 --- a/scripts/verify-workspace-install-docs.sh +++ b/scripts/verify-workspace-install-docs.sh @@ -12,7 +12,17 @@ trim() { printf '%s' "$value" } -verify_secret_file_values() { +is_safe_absolute_path() { + local value="$1" segment + local -a segments + [[ "$value" == /* && "$value" != *//* ]] || return 1 + IFS=/ read -r -a segments <<<"$value" + for segment in "${segments[@]}"; do + [[ "$segment" != . && "$segment" != .. ]] || return 1 + done +} + +verify_path_variable_values() { local source="$1" line trimmed name value while IFS= read -r line || [[ -n "$line" ]]; do trimmed="$(trim "$line")" @@ -20,14 +30,14 @@ verify_secret_file_values() { name="$(trim "${trimmed%%[=:]*}")" value="$(trim "${trimmed#"$name"}")" value="$(trim "${value#[:=]}")" - if [[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_FILE$ ]]; then + if [[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_(FILE|SOURCE)$ ]]; then value="$(trim "${value%%#*}")" - value="${value#\"}"; value="${value%\"}" - value="${value#\'}"; value="${value%\'}" - if [[ -n "$value" && "$value" != /* ]]; then - echo "non-path secret-file value for $name in $source" >&2 - return 1 - fi + value="${value#\"}"; value="${value%\"}" + value="${value#\'}"; value="${value%\'}" + if [[ -n "$value" ]] && ! is_safe_absolute_path "$value"; then + echo "unsafe path value for $name in $source" >&2 + return 1 + fi fi fi done <"$source" @@ -168,11 +178,18 @@ verify_copied_operator_fixtures() { verify_connector_fixture "$connector_dir" printf 'THT_WS_EXAMPLE_DWH_PASSWORD_FILE=not-a-path\n' >"$fixture_root/non-path-secret.env" - if verify_secret_file_values "$fixture_root/non-path-secret.env" >/dev/null 2>&1; then + if verify_path_variable_values "$fixture_root/non-path-secret.env" >/dev/null 2>&1; then echo "non-path secret-file fixture was accepted" >&2 return 1 fi echo "non-path secret-file fixture rejected passed" + + printf 'THT_WS_EXAMPLE_DWH_PASSWORD_SOURCE=literal-value\n' >"$fixture_root/literal-source.env" + if verify_path_variable_values "$fixture_root/literal-source.env" >/dev/null 2>&1; then + echo "literal secret-source fixture was accepted" >&2 + return 1 + fi + echo "literal secret-source fixture rejected passed" } case "$profile" in @@ -247,12 +264,12 @@ if grep -Ein '(^|[[:space:]])(password|api[_-]?key|token|secret)[[:space:]]*[:=] echo "installation documentation contains a secret literal" >&2 exit 1 fi -verify_secret_file_values "$manual" -verify_secret_file_values "$example" -verify_secret_file_values "$root/docs/install/examples/git-https.workspace-registry.yaml" -verify_secret_file_values "$root/docs/install/examples/git-ssh.workspace-registry.yaml" -verify_secret_file_values "$root/docs/install/examples/workspace-bindings.env.example" -verify_secret_file_values "$root/docs/install/examples/connector-secrets.workspace-registry.yaml" +verify_path_variable_values "$manual" +verify_path_variable_values "$example" +verify_path_variable_values "$root/docs/install/examples/git-https.workspace-registry.yaml" +verify_path_variable_values "$root/docs/install/examples/git-ssh.workspace-registry.yaml" +verify_path_variable_values "$root/docs/install/examples/workspace-bindings.env.example" +verify_path_variable_values "$root/docs/install/examples/connector-secrets.workspace-registry.yaml" verify_server_public_contract commands="$(mktemp "${TMPDIR:-/tmp}/thoth-install-docs.XXXXXX")"