From 5086b88a00747d05181f84f15fb3b1b8e18e66a7 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 05:28:32 +0300 Subject: [PATCH 01/13] feat: Add gateway environment variables support - Add 'gateway_env_vars' configuration option to addon config - Parse semicolon-separated KEY=VALUE pairs from add-on options - Export environment variables to gateway process at startup - Store parsed env vars in openclaw.json (gateway.env) Allows users to pass custom environment variables to the gateway via Home Assistant add-on configuration, e.g.: gateway_env_vars: 'SERVICE_API_KEY=123;SERVICE2_API=1231' These variables are exported to the gateway process and can be used for API authentication, feature flags, or other configuration needs. --- openclaw_assistant/config.yaml | 6 ++++ openclaw_assistant/oc_config_helper.py | 44 +++++++++++++++++++++++--- openclaw_assistant/run.sh | 24 +++++++++++++- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index 013b2fc..3b99056 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -88,6 +88,11 @@ options: # (can affect Telegram API polling in some HAOS/VM setups). force_ipv4_dns: false + # Environment variables to pass to the gateway (semicolon-separated key=value pairs) + # Example: "SERVICE_API=123;SERVICE2_API=1231" + # These will be exported as environment variables when running the gateway + gateway_env_vars: "" + schema: timezone: str @@ -109,3 +114,4 @@ schema: enable_openai_api: bool? allow_insecure_auth: bool? force_ipv4_dns: bool? + gateway_env_vars: str? diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index d87c0f3..3bfbd44 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -57,7 +57,7 @@ def set_gateway_setting(key, value): return write_config(cfg) -def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool): +def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = ""): """ Apply gateway settings to OpenClaw config. @@ -67,6 +67,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a port: Port number to listen on (must be 1-65535) enable_openai_api: Enable OpenAI-compatible Chat Completions endpoint allow_insecure_auth: Allow insecure HTTP authentication + env_vars: Semicolon-separated environment variables (e.g., "VAR1=value1;VAR2=value2") """ # Validate gateway mode if mode not in ["local", "remote"]: @@ -112,6 +113,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a current_port = gateway.get("port", 18789) current_openai_api = chat_completions.get("enabled", False) current_insecure = control_ui.get("allowInsecureAuth", False) + current_env_vars = gateway.get("env", {}) changes = [] @@ -135,6 +137,37 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a control_ui["allowInsecureAuth"] = allow_insecure_auth changes.append(f"allowInsecureAuth: {current_insecure} -> {allow_insecure_auth}") + # Parse and apply environment variables + new_env_vars = {} + if env_vars.strip(): + try: + # Parse semicolon-separated key=value pairs + pairs = env_vars.split(';') + for pair in pairs: + pair = pair.strip() + if not pair: + continue + if '=' not in pair: + print(f"WARN: Invalid env var format '{pair}' (missing '=')") + continue + key, value = pair.split('=', 1) + key = key.strip() + value = value.strip() + if not key: + print(f"WARN: Invalid env var key (empty)") + continue + new_env_vars[key] = value + except Exception as e: + print(f"ERROR: Failed to parse environment variables: {e}") + return False + + if new_env_vars != current_env_vars: + gateway["env"] = new_env_vars + if new_env_vars: + changes.append(f"env: {len(new_env_vars)} variables") + else: + changes.append("env: cleared") + if changes: if write_config(cfg): print(f"INFO: Updated gateway settings: {', '.join(changes)}") @@ -143,7 +176,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a print("ERROR: Failed to write config") return False else: - print(f"INFO: Gateway settings already correct (mode={mode}, bind={bind_mode}, port={port}, chatCompletions={enable_openai_api}, allowInsecureAuth={allow_insecure_auth})") + print(f"INFO: Gateway settings already correct (mode={mode}, bind={bind_mode}, port={port}, chatCompletions={enable_openai_api}, allowInsecureAuth={allow_insecure_auth}, env vars={len(current_env_vars)})") return True @@ -156,15 +189,16 @@ def main(): cmd = sys.argv[1] if cmd == "apply-gateway-settings": - if len(sys.argv) != 7: - print("Usage: oc_config_helper.py apply-gateway-settings ") + if len(sys.argv) < 7: + print("Usage: oc_config_helper.py apply-gateway-settings [env_vars]") sys.exit(1) mode = sys.argv[2] bind_mode = sys.argv[3] port = int(sys.argv[4]) enable_openai_api = sys.argv[5].lower() == "true" allow_insecure_auth = sys.argv[6].lower() == "true" - success = apply_gateway_settings(mode, bind_mode, port, enable_openai_api, allow_insecure_auth) + env_vars = sys.argv[7] if len(sys.argv) > 7 else "" + success = apply_gateway_settings(mode, bind_mode, port, enable_openai_api, allow_insecure_auth, env_vars) sys.exit(0 if success else 1) elif cmd == "get": diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index fa89a64..b9ef6b7 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -52,6 +52,7 @@ GATEWAY_PORT=$(jq -r '.gateway_port // 18789' "$OPTIONS_FILE") ENABLE_OPENAI_API=$(jq -r '.enable_openai_api // false' "$OPTIONS_FILE") ALLOW_INSECURE_AUTH=$(jq -r '.allow_insecure_auth // false' "$OPTIONS_FILE") FORCE_IPV4_DNS=$(jq -r '.force_ipv4_dns // false' "$OPTIONS_FILE") +GW_ENV_VARS=$(jq -r '.gateway_env_vars // empty' "$OPTIONS_FILE") export TZ="$TZNAME" @@ -147,6 +148,27 @@ export PNPM_HOME="${PERSISTENT_NODE_GLOBAL}/pnpm" mkdir -p "$PNPM_HOME" export PATH="${PNPM_HOME}:${PATH}" +# Export gateway environment variables from add-on config +# These are user-defined variables that should be available to the gateway process +if [ -n "$GW_ENV_VARS" ]; then + echo "INFO: Setting gateway environment variables from add-on config..." + IFS=';' read -ra ENV_VARS <<< "$GW_ENV_VARS" + for var in "${ENV_VARS[@]}"; do + var=$(echo "$var" | xargs) # trim whitespace + if [ -z "$var" ]; then + continue + fi + if [[ ! "$var" =~ ^[A-Za-z_][A-Za-z0-9_]*=.*$ ]]; then + echo "WARN: Invalid environment variable format: '$var' (skipping)" + continue + fi + export "$var" + # Extract key for logging (don't log values for security) + key="${var%%=*}" + echo "INFO: Exported gateway env var: $key" + done +fi + # ------------------------------------------------------------------------------ # Persist Linuxbrew/Homebrew across Docker image rebuilds # Homebrew installs to /home/linuxbrew/.linuxbrew/ which is ephemeral. @@ -353,7 +375,7 @@ fi if [ -f "$OPENCLAW_CONFIG_PATH" ]; then if [ -f "$HELPER_PATH" ]; then - if ! python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_BIND_MODE" "$GATEWAY_PORT" "$ENABLE_OPENAI_API" "$ALLOW_INSECURE_AUTH"; then + if ! python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_BIND_MODE" "$GATEWAY_PORT" "$ENABLE_OPENAI_API" "$ALLOW_INSECURE_AUTH" "$GW_ENV_VARS"; then rc=$? echo "ERROR: Failed to apply gateway settings via oc_config_helper.py (exit code ${rc})." echo "ERROR: Gateway configuration may be incorrect; aborting startup." From 9b402d31302a9feddc2650c7092ef365735505ac Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 05:36:07 +0300 Subject: [PATCH 02/13] refactor: improve gateway env vars security and limits - Add max limits (50 vars, 255 char names, 10000 char values) - Validate variable names with regex - Warn about duplicate variables - Show var names in logs (not just count) - Improve bash parsing with process substitution - Better config documentation with examples --- openclaw_assistant/config.yaml | 9 ++++-- openclaw_assistant/oc_config_helper.py | 32 +++++++++++++++++- openclaw_assistant/run.sh | 45 ++++++++++++++++++++------ 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index 3b99056..f9421ca 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -89,8 +89,13 @@ options: force_ipv4_dns: false # Environment variables to pass to the gateway (semicolon-separated key=value pairs) - # Example: "SERVICE_API=123;SERVICE2_API=1231" - # These will be exported as environment variables when running the gateway + # Format: "KEY1=value1;KEY2=value2" (semicolon-separated, no spaces around '=') + # Examples: + # - API keys: "OPENAI_API_KEY=sk-abc123;ANTHROPIC_API_KEY=claude-key" + # - Service URLs: "SERVICE_URL=https://api.example.com;LOG_LEVEL=debug" + # - Features: "FEATURE_FLAG_X=1;FEATURE_FLAG_Y=0" + # Limits: max 50 variables, max key length 255 chars, max value length 10000 chars + # Note: Values may contain special characters; they are not shell-escaped gateway_env_vars: "" diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index 3bfbd44..aecc798 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -12,6 +12,11 @@ from pathlib import Path CONFIG_PATH = Path(os.environ.get("OPENCLAW_CONFIG_PATH", "/config/.openclaw/openclaw.json")) +# Limits for environment variable handling +MAX_ENV_VARS = 50 +MAX_ENV_VAR_NAME_SIZE = 255 +MAX_ENV_VAR_VALUE_SIZE = 10000 + def read_config(): @@ -150,13 +155,37 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a if '=' not in pair: print(f"WARN: Invalid env var format '{pair}' (missing '=')") continue + key, value = pair.split('=', 1) key = key.strip() value = value.strip() + + # Validate key format if not key: print(f"WARN: Invalid env var key (empty)") continue + if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', key): + print(f"WARN: Invalid env var name '{key}' (must start with letter/underscore)") + continue + + # Enforce size limits + if len(key) > MAX_ENV_VAR_NAME_SIZE: + print(f"ERROR: Environment variable name '{key}' too long (max {MAX_ENV_VAR_NAME_SIZE} chars)") + return False + if len(value) > MAX_ENV_VAR_VALUE_SIZE: + print(f"ERROR: Environment variable '{key}' value too large (max {MAX_ENV_VAR_VALUE_SIZE} chars)") + return False + + # Warn about duplicate keys + if key in new_env_vars: + print(f"WARN: Environment variable '{key}' appears multiple times; using last value") + new_env_vars[key] = value + + # Enforce limit on total variables + if len(new_env_vars) > MAX_ENV_VARS: + print(f"ERROR: Too many environment variables ({len(new_env_vars)}), max {MAX_ENV_VARS}") + return False except Exception as e: print(f"ERROR: Failed to parse environment variables: {e}") return False @@ -164,7 +193,8 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a if new_env_vars != current_env_vars: gateway["env"] = new_env_vars if new_env_vars: - changes.append(f"env: {len(new_env_vars)} variables") + var_names = ', '.join(sorted(new_env_vars.keys())) + changes.append(f"env: {var_names}") else: changes.append("env: cleared") diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index b9ef6b7..76a4cc0 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -152,21 +152,46 @@ export PATH="${PNPM_HOME}:${PATH}" # These are user-defined variables that should be available to the gateway process if [ -n "$GW_ENV_VARS" ]; then echo "INFO: Setting gateway environment variables from add-on config..." - IFS=';' read -ra ENV_VARS <<< "$GW_ENV_VARS" - for var in "${ENV_VARS[@]}"; do - var=$(echo "$var" | xargs) # trim whitespace - if [ -z "$var" ]; then + env_count=0 + max_env_vars=50 + max_var_name_size=255 + + while IFS='=' read -r key value; do + # Skip empty lines + if [ -z "$key" ]; then continue fi - if [[ ! "$var" =~ ^[A-Za-z_][A-Za-z0-9_]*=.*$ ]]; then - echo "WARN: Invalid environment variable format: '$var' (skipping)" + + # Trim whitespace + key=$(echo "$key" | xargs) + value=$(echo "$value" | xargs) + + # Validate variable name format + if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then + echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" continue fi - export "$var" - # Extract key for logging (don't log values for security) - key="${var%%=*}" + + # Enforce max variable name length + if [ ${#key} -gt $max_var_name_size ]; then + echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" + continue + fi + + # Enforce limit on number of variables + if [ $env_count -ge $max_env_vars ]; then + echo "WARN: Maximum environment variables limit ($max_env_vars) reached (skip)" + continue + fi + + export "$key=$value" + ((env_count++)) echo "INFO: Exported gateway env var: $key" - done + done < <(echo "$GW_ENV_VARS" | tr ';' '\n') + + if [ $env_count -gt 0 ]; then + echo "INFO: Successfully exported $env_count gateway environment variable(s)" + fi fi # ------------------------------------------------------------------------------ From 30d95b879870b8353a3fe1ee5585a8e3a5580b2f Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 05:40:32 +0300 Subject: [PATCH 03/13] refactor: use YAML map for gateway environment variables instead of string parsing Benefits: - More idiomatic configuration format for Home Assistant add-ons - config.yaml: Change default from empty string to empty YAML map - config.yaml: Update schema type from str? to map(str)? - config.yaml: Improve documentation to explain YAML map usage - run.sh: Parse JSON object from jq using to_entries instead of semicolon splitting - oc_config_helper.py: Accept JSON string and parse as dict instead of semicolon-separated values - Better error handling for invalid JSON - Cleaner and more maintainable parsing logic This allows users to configure environment variables more naturally: gateway_env_vars: OPENAI_API_KEY: sk-abc123 SERVICE_URL: https://api.example.com --- openclaw_assistant/config.yaml | 21 +++++++----- openclaw_assistant/oc_config_helper.py | 44 ++++++++++++-------------- openclaw_assistant/run.sh | 16 +++++----- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index f9421ca..d37c5d9 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -88,15 +88,20 @@ options: # (can affect Telegram API polling in some HAOS/VM setups). force_ipv4_dns: false - # Environment variables to pass to the gateway (semicolon-separated key=value pairs) - # Format: "KEY1=value1;KEY2=value2" (semicolon-separated, no spaces around '=') + # Environment variables to pass to the gateway as a YAML map + # These variables are exported to the gateway process at startup # Examples: - # - API keys: "OPENAI_API_KEY=sk-abc123;ANTHROPIC_API_KEY=claude-key" - # - Service URLs: "SERVICE_URL=https://api.example.com;LOG_LEVEL=debug" - # - Features: "FEATURE_FLAG_X=1;FEATURE_FLAG_Y=0" + # API keys: + # OPENAI_API_KEY: "sk-abc123" + # ANTHROPIC_API_KEY: "claude-key" + # Service URLs: + # SERVICE_URL: "https://api.example.com" + # LOG_LEVEL: "debug" + # Feature flags: + # FEATURE_FLAG_X: "1" + # FEATURE_FLAG_Y: "0" # Limits: max 50 variables, max key length 255 chars, max value length 10000 chars - # Note: Values may contain special characters; they are not shell-escaped - gateway_env_vars: "" + gateway_env_vars: {} schema: @@ -119,4 +124,4 @@ schema: enable_openai_api: bool? allow_insecure_auth: bool? force_ipv4_dns: bool? - gateway_env_vars: str? + gateway_env_vars: map(str)? diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index aecc798..08bdd5b 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -62,7 +62,7 @@ def set_gateway_setting(key, value): return write_config(cfg) -def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = ""): +def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = "{}"): """ Apply gateway settings to OpenClaw config. @@ -72,7 +72,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a port: Port number to listen on (must be 1-65535) enable_openai_api: Enable OpenAI-compatible Chat Completions endpoint allow_insecure_auth: Allow insecure HTTP authentication - env_vars: Semicolon-separated environment variables (e.g., "VAR1=value1;VAR2=value2") + env_vars: JSON string with environment variables as key-value pairs (e.g., '{"VAR1":"value1","VAR2":"value2"}') """ # Validate gateway mode if mode not in ["local", "remote"]: @@ -142,23 +142,20 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a control_ui["allowInsecureAuth"] = allow_insecure_auth changes.append(f"allowInsecureAuth: {current_insecure} -> {allow_insecure_auth}") - # Parse and apply environment variables + # Parse and apply environment variables from JSON new_env_vars = {} - if env_vars.strip(): + if env_vars.strip() and env_vars != "{}": try: - # Parse semicolon-separated key=value pairs - pairs = env_vars.split(';') - for pair in pairs: - pair = pair.strip() - if not pair: - continue - if '=' not in pair: - print(f"WARN: Invalid env var format '{pair}' (missing '=')") - continue - - key, value = pair.split('=', 1) - key = key.strip() - value = value.strip() + # Parse JSON object containing environment variables + parsed = json.loads(env_vars) + if not isinstance(parsed, dict): + print(f"ERROR: Environment variables must be a JSON object (dict), got {type(parsed).__name__}") + return False + + for key, value in parsed.items(): + # Ensure value is string + if not isinstance(value, str): + value = str(value) # Validate key format if not key: @@ -176,18 +173,17 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a print(f"ERROR: Environment variable '{key}' value too large (max {MAX_ENV_VAR_VALUE_SIZE} chars)") return False - # Warn about duplicate keys - if key in new_env_vars: - print(f"WARN: Environment variable '{key}' appears multiple times; using last value") - new_env_vars[key] = value # Enforce limit on total variables if len(new_env_vars) > MAX_ENV_VARS: print(f"ERROR: Too many environment variables ({len(new_env_vars)}), max {MAX_ENV_VARS}") return False + except json.JSONDecodeError as e: + print(f"ERROR: Failed to parse environment variables JSON: {e}") + return False except Exception as e: - print(f"ERROR: Failed to parse environment variables: {e}") + print(f"ERROR: Failed to process environment variables: {e}") return False if new_env_vars != current_env_vars: @@ -220,14 +216,14 @@ def main(): if cmd == "apply-gateway-settings": if len(sys.argv) < 7: - print("Usage: oc_config_helper.py apply-gateway-settings [env_vars]") + print("Usage: oc_config_helper.py apply-gateway-settings [env_vars_json]") sys.exit(1) mode = sys.argv[2] bind_mode = sys.argv[3] port = int(sys.argv[4]) enable_openai_api = sys.argv[5].lower() == "true" allow_insecure_auth = sys.argv[6].lower() == "true" - env_vars = sys.argv[7] if len(sys.argv) > 7 else "" + env_vars = sys.argv[7] if len(sys.argv) > 7 else "{}" success = apply_gateway_settings(mode, bind_mode, port, enable_openai_api, allow_insecure_auth, env_vars) sys.exit(0 if success else 1) diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 76a4cc0..b1fb12b 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -52,7 +52,7 @@ GATEWAY_PORT=$(jq -r '.gateway_port // 18789' "$OPTIONS_FILE") ENABLE_OPENAI_API=$(jq -r '.enable_openai_api // false' "$OPTIONS_FILE") ALLOW_INSECURE_AUTH=$(jq -r '.allow_insecure_auth // false' "$OPTIONS_FILE") FORCE_IPV4_DNS=$(jq -r '.force_ipv4_dns // false' "$OPTIONS_FILE") -GW_ENV_VARS=$(jq -r '.gateway_env_vars // empty' "$OPTIONS_FILE") +GW_ENV_VARS=$(jq -c '.gateway_env_vars // {}' "$OPTIONS_FILE") export TZ="$TZNAME" @@ -150,22 +150,22 @@ export PATH="${PNPM_HOME}:${PATH}" # Export gateway environment variables from add-on config # These are user-defined variables that should be available to the gateway process -if [ -n "$GW_ENV_VARS" ]; then +if [ "$GW_ENV_VARS" != "{}" ] && [ -n "$GW_ENV_VARS" ]; then echo "INFO: Setting gateway environment variables from add-on config..." env_count=0 max_env_vars=50 max_var_name_size=255 + # Parse JSON object and export each key=value pair while IFS='=' read -r key value; do - # Skip empty lines + # Skip empty lines and trim whitespace + key=$(echo "$key" | xargs) + value=$(echo "$value" | xargs) + if [ -z "$key" ]; then continue fi - # Trim whitespace - key=$(echo "$key" | xargs) - value=$(echo "$value" | xargs) - # Validate variable name format if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" @@ -187,7 +187,7 @@ if [ -n "$GW_ENV_VARS" ]; then export "$key=$value" ((env_count++)) echo "INFO: Exported gateway env var: $key" - done < <(echo "$GW_ENV_VARS" | tr ';' '\n') + done < <(echo "$GW_ENV_VARS" | jq -r 'to_entries[] | "\(.key)=\(.value)"') if [ $env_count -gt 0 ]; then echo "INFO: Successfully exported $env_count gateway environment variable(s)" From 47631c1968a5ad04229743259d9a631385f15d71 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 05:55:59 +0300 Subject: [PATCH 04/13] fix: store env vars in cfg[env][vars] not cfg[gateway][env] --- openclaw_assistant/oc_config_helper.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index 08bdd5b..51f2e1e 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -64,7 +64,7 @@ def set_gateway_setting(key, value): def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = "{}"): """ - Apply gateway settings to OpenClaw config. + Apply gateway settings and environment variables to OpenClaw config. Args: mode: "local" or "remote" @@ -73,6 +73,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a enable_openai_api: Enable OpenAI-compatible Chat Completions endpoint allow_insecure_auth: Allow insecure HTTP authentication env_vars: JSON string with environment variables as key-value pairs (e.g., '{"VAR1":"value1","VAR2":"value2"}') + These are stored in cfg["env"]["vars"] and exported to the gateway process """ # Validate gateway mode if mode not in ["local", "remote"]: @@ -113,12 +114,24 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a control_ui = gateway["controlUi"] chat_completions = gateway["http"]["endpoints"]["chatCompletions"] + # Ensure env structure exists at root level + if "env" not in cfg: + cfg["env"] = { + "shellEnv": { + "enabled": True + }, + "vars": {} + } + + if "vars" not in cfg["env"]: + cfg["env"]["vars"] = {} + current_mode = gateway.get("mode", "") current_bind = gateway.get("bind", "") current_port = gateway.get("port", 18789) current_openai_api = chat_completions.get("enabled", False) current_insecure = control_ui.get("allowInsecureAuth", False) - current_env_vars = gateway.get("env", {}) + current_env_vars = cfg["env"]["vars"] changes = [] @@ -187,12 +200,12 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a return False if new_env_vars != current_env_vars: - gateway["env"] = new_env_vars + cfg["env"]["vars"] = new_env_vars if new_env_vars: var_names = ', '.join(sorted(new_env_vars.keys())) - changes.append(f"env: {var_names}") + changes.append(f"env.vars: {var_names}") else: - changes.append("env: cleared") + changes.append("env.vars: cleared") if changes: if write_config(cfg): From b45d2e685a2813a8f90990445b4f727acbc80ea2 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 06:00:01 +0300 Subject: [PATCH 05/13] refactor: remove env vars persistence, only validate and export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Environment variables should NOT be saved to openclaw.json config. Instead, they are injected directly into the gateway process via run.sh. Flow: options.json (gateway_env_vars) → run.sh (export) → gateway process env Changes: - Remove cfg["env"] initialization from apply_gateway_settings - Only validate env vars format and size limits in oc_config_helper.py - Log validated vars but don't persist them to config - run.sh remains responsible for parsing and exporting to process env - Cleaner separation of concerns: helpers validates, run.sh exports --- openclaw_assistant/oc_config_helper.py | 33 +++++++------------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index 51f2e1e..6ab8d71 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -64,7 +64,8 @@ def set_gateway_setting(key, value): def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = "{}"): """ - Apply gateway settings and environment variables to OpenClaw config. + Apply gateway settings to OpenClaw config. + Environment variables are handled separately via run.sh and do not need to be saved to config. Args: mode: "local" or "remote" @@ -72,8 +73,8 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a port: Port number to listen on (must be 1-65535) enable_openai_api: Enable OpenAI-compatible Chat Completions endpoint allow_insecure_auth: Allow insecure HTTP authentication - env_vars: JSON string with environment variables as key-value pairs (e.g., '{"VAR1":"value1","VAR2":"value2"}') - These are stored in cfg["env"]["vars"] and exported to the gateway process + env_vars: JSON string with environment variables (not saved to config, just validated) + These are exported to the gateway process by run.sh """ # Validate gateway mode if mode not in ["local", "remote"]: @@ -114,24 +115,11 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a control_ui = gateway["controlUi"] chat_completions = gateway["http"]["endpoints"]["chatCompletions"] - # Ensure env structure exists at root level - if "env" not in cfg: - cfg["env"] = { - "shellEnv": { - "enabled": True - }, - "vars": {} - } - - if "vars" not in cfg["env"]: - cfg["env"]["vars"] = {} - current_mode = gateway.get("mode", "") current_bind = gateway.get("bind", "") current_port = gateway.get("port", 18789) current_openai_api = chat_completions.get("enabled", False) current_insecure = control_ui.get("allowInsecureAuth", False) - current_env_vars = cfg["env"]["vars"] changes = [] @@ -199,13 +187,10 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a print(f"ERROR: Failed to process environment variables: {e}") return False - if new_env_vars != current_env_vars: - cfg["env"]["vars"] = new_env_vars - if new_env_vars: - var_names = ', '.join(sorted(new_env_vars.keys())) - changes.append(f"env.vars: {var_names}") - else: - changes.append("env.vars: cleared") + # Log validated environment variables (not saved to config, handled by run.sh) + if new_env_vars: + var_names = ', '.join(sorted(new_env_vars.keys())) + print(f"INFO: Environment variables validated (will be exported by run.sh): {var_names}") if changes: if write_config(cfg): @@ -215,7 +200,7 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a print("ERROR: Failed to write config") return False else: - print(f"INFO: Gateway settings already correct (mode={mode}, bind={bind_mode}, port={port}, chatCompletions={enable_openai_api}, allowInsecureAuth={allow_insecure_auth}, env vars={len(current_env_vars)})") + print(f"INFO: Gateway settings already correct (mode={mode}, bind={bind_mode}, port={port}, chatCompletions={enable_openai_api}, allowInsecureAuth={allow_insecure_auth})") return True From 872a52221e40c47fafcf13d91aafa899385bbdd9 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 06:06:20 +0300 Subject: [PATCH 06/13] refactor: remove env vars from oc_config_helper, keep validation in run.sh Environment variables are fully handled by run.sh: - run.sh reads gateway_env_vars from options.json - run.sh validates variable names (alphanumeric + underscore) - run.sh enforces max 50 variables and 255 char name limit - run.sh exports to process environment oc_config_helper.py now only manages gateway config (mode, port, bind). Removes: - env_vars parameter from apply_gateway_settings() - All env var parsing and validation from Python helper - MAX_ENV_VARS constants - env_vars CLI argument --- openclaw_assistant/oc_config_helper.py | 66 ++------------------------ openclaw_assistant/run.sh | 2 +- 2 files changed, 5 insertions(+), 63 deletions(-) diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index 6ab8d71..d87c0f3 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -12,11 +12,6 @@ from pathlib import Path CONFIG_PATH = Path(os.environ.get("OPENCLAW_CONFIG_PATH", "/config/.openclaw/openclaw.json")) -# Limits for environment variable handling -MAX_ENV_VARS = 50 -MAX_ENV_VAR_NAME_SIZE = 255 -MAX_ENV_VAR_VALUE_SIZE = 10000 - def read_config(): @@ -62,10 +57,9 @@ def set_gateway_setting(key, value): return write_config(cfg) -def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool, env_vars: str = "{}"): +def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_api: bool, allow_insecure_auth: bool): """ Apply gateway settings to OpenClaw config. - Environment variables are handled separately via run.sh and do not need to be saved to config. Args: mode: "local" or "remote" @@ -73,8 +67,6 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a port: Port number to listen on (must be 1-65535) enable_openai_api: Enable OpenAI-compatible Chat Completions endpoint allow_insecure_auth: Allow insecure HTTP authentication - env_vars: JSON string with environment variables (not saved to config, just validated) - These are exported to the gateway process by run.sh """ # Validate gateway mode if mode not in ["local", "remote"]: @@ -143,55 +135,6 @@ def apply_gateway_settings(mode: str, bind_mode: str, port: int, enable_openai_a control_ui["allowInsecureAuth"] = allow_insecure_auth changes.append(f"allowInsecureAuth: {current_insecure} -> {allow_insecure_auth}") - # Parse and apply environment variables from JSON - new_env_vars = {} - if env_vars.strip() and env_vars != "{}": - try: - # Parse JSON object containing environment variables - parsed = json.loads(env_vars) - if not isinstance(parsed, dict): - print(f"ERROR: Environment variables must be a JSON object (dict), got {type(parsed).__name__}") - return False - - for key, value in parsed.items(): - # Ensure value is string - if not isinstance(value, str): - value = str(value) - - # Validate key format - if not key: - print(f"WARN: Invalid env var key (empty)") - continue - if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', key): - print(f"WARN: Invalid env var name '{key}' (must start with letter/underscore)") - continue - - # Enforce size limits - if len(key) > MAX_ENV_VAR_NAME_SIZE: - print(f"ERROR: Environment variable name '{key}' too long (max {MAX_ENV_VAR_NAME_SIZE} chars)") - return False - if len(value) > MAX_ENV_VAR_VALUE_SIZE: - print(f"ERROR: Environment variable '{key}' value too large (max {MAX_ENV_VAR_VALUE_SIZE} chars)") - return False - - new_env_vars[key] = value - - # Enforce limit on total variables - if len(new_env_vars) > MAX_ENV_VARS: - print(f"ERROR: Too many environment variables ({len(new_env_vars)}), max {MAX_ENV_VARS}") - return False - except json.JSONDecodeError as e: - print(f"ERROR: Failed to parse environment variables JSON: {e}") - return False - except Exception as e: - print(f"ERROR: Failed to process environment variables: {e}") - return False - - # Log validated environment variables (not saved to config, handled by run.sh) - if new_env_vars: - var_names = ', '.join(sorted(new_env_vars.keys())) - print(f"INFO: Environment variables validated (will be exported by run.sh): {var_names}") - if changes: if write_config(cfg): print(f"INFO: Updated gateway settings: {', '.join(changes)}") @@ -213,16 +156,15 @@ def main(): cmd = sys.argv[1] if cmd == "apply-gateway-settings": - if len(sys.argv) < 7: - print("Usage: oc_config_helper.py apply-gateway-settings [env_vars_json]") + if len(sys.argv) != 7: + print("Usage: oc_config_helper.py apply-gateway-settings ") sys.exit(1) mode = sys.argv[2] bind_mode = sys.argv[3] port = int(sys.argv[4]) enable_openai_api = sys.argv[5].lower() == "true" allow_insecure_auth = sys.argv[6].lower() == "true" - env_vars = sys.argv[7] if len(sys.argv) > 7 else "{}" - success = apply_gateway_settings(mode, bind_mode, port, enable_openai_api, allow_insecure_auth, env_vars) + success = apply_gateway_settings(mode, bind_mode, port, enable_openai_api, allow_insecure_auth) sys.exit(0 if success else 1) elif cmd == "get": diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index b1fb12b..77dbc7d 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -400,7 +400,7 @@ fi if [ -f "$OPENCLAW_CONFIG_PATH" ]; then if [ -f "$HELPER_PATH" ]; then - if ! python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_BIND_MODE" "$GATEWAY_PORT" "$ENABLE_OPENAI_API" "$ALLOW_INSECURE_AUTH" "$GW_ENV_VARS"; then + if ! python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_BIND_MODE" "$GATEWAY_PORT" "$ENABLE_OPENAI_API" "$ALLOW_INSECURE_AUTH"; then rc=$? echo "ERROR: Failed to apply gateway settings via oc_config_helper.py (exit code ${rc})." echo "ERROR: Gateway configuration may be incorrect; aborting startup." From 94fab5b2604b71a1f7fd957763414de48095021a Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 06:31:41 +0300 Subject: [PATCH 07/13] added translation --- openclaw_assistant/translations/bg.yaml | 4 ++++ openclaw_assistant/translations/de.yaml | 4 ++++ openclaw_assistant/translations/en.yaml | 4 ++++ openclaw_assistant/translations/es.yaml | 4 ++++ openclaw_assistant/translations/pl.yaml | 4 ++++ openclaw_assistant/translations/pt-BR.yaml | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/openclaw_assistant/translations/bg.yaml b/openclaw_assistant/translations/bg.yaml index e8a6514..47b196d 100644 --- a/openclaw_assistant/translations/bg.yaml +++ b/openclaw_assistant/translations/bg.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: Принудителен IPv4 DNS ред description: Принудително задава IPv4-приоритет при DNS резолв за Node мрежови заявки. Полезно е, когато IPv6 DNS се резолвира, но IPv6 интернет маршрутизацията е неработеща (може да влияе на Telegram API polling). + + gateway_env_vars: + name: Променливи на средата за Gateway + description: Променливи на средата, предавани на OpenClaw gateway процеса при стартиране (дефинирани като YAML карта; макс. 50 променливи, ключове до 255 знака, стойности до 10000 знака). diff --git a/openclaw_assistant/translations/de.yaml b/openclaw_assistant/translations/de.yaml index f0945b9..cc5e064 100644 --- a/openclaw_assistant/translations/de.yaml +++ b/openclaw_assistant/translations/de.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: IPv4-DNS-Reihenfolge erzwingen description: Erzwingt IPv4-vorrangige DNS-Auflösung für Node-Netzwerkaufrufe. Nützlich, wenn IPv6-DNS aufgelöst wird, aber IPv6-Internet-Routing nicht funktioniert (kann Telegram-API-Polling beeinträchtigen). + + gateway_env_vars: + name: Gateway-Umgebungsvariablen + description: Umgebungsvariablen, die beim Start an den OpenClaw-Gateway-Prozess übergeben werden (als YAML-Map; max. 50 Variablen, Schlüssel bis 255 Zeichen, Werte bis 10.000 Zeichen). diff --git a/openclaw_assistant/translations/en.yaml b/openclaw_assistant/translations/en.yaml index 191b024..c3a740a 100644 --- a/openclaw_assistant/translations/en.yaml +++ b/openclaw_assistant/translations/en.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: Force IPv4 DNS Order description: Force IPv4-first DNS ordering for Node network calls. Useful when IPv6 DNS resolves but IPv6 internet routing is broken (can affect Telegram API polling). + + gateway_env_vars: + name: Gateway Environment Variables + description: Environment variables passed to the OpenClaw gateway process at startup (defined as a YAML map; max 50 variables, keys up to 255 characters, values up to 10,000 characters). diff --git a/openclaw_assistant/translations/es.yaml b/openclaw_assistant/translations/es.yaml index 8a7ce84..d3e26ab 100644 --- a/openclaw_assistant/translations/es.yaml +++ b/openclaw_assistant/translations/es.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: Forzar orden DNS IPv4 description: Fuerza el orden de DNS con prioridad IPv4 para llamadas de red de Node. Útil cuando el DNS IPv6 resuelve, pero el enrutamiento IPv6 a Internet falla (puede afectar el polling de la API de Telegram). + + gateway_env_vars: + name: Variables de entorno del Gateway + description: Variables de entorno que se pasan al proceso del gateway OpenClaw al iniciarse (definidas como un mapa YAML; máximo 50 variables, claves de hasta 255 caracteres, valores de hasta 10 000 caracteres). diff --git a/openclaw_assistant/translations/pl.yaml b/openclaw_assistant/translations/pl.yaml index 7b6324d..f5aeb03 100644 --- a/openclaw_assistant/translations/pl.yaml +++ b/openclaw_assistant/translations/pl.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: Wymuś kolejność DNS IPv4 description: Wymusza preferowanie IPv4 przy rozwiązywaniu DNS dla wywołań sieciowych Node. Przydatne, gdy DNS IPv6 się rozwiązuje, ale routing IPv6 do Internetu nie działa (może wpływać na polling API Telegrama). + + gateway_env_vars: + name: Zmienne środowiskowe gateway + description: Zmienne środowiskowe przekazywane do procesu gateway OpenClaw podczas uruchamiania (zdefiniowane jako mapa YAML; maks. 50 zmiennych, klucze do 255 znaków, wartości do 10000 znaków). diff --git a/openclaw_assistant/translations/pt-BR.yaml b/openclaw_assistant/translations/pt-BR.yaml index d688d7f..d05889a 100644 --- a/openclaw_assistant/translations/pt-BR.yaml +++ b/openclaw_assistant/translations/pt-BR.yaml @@ -66,3 +66,7 @@ configuration: force_ipv4_dns: name: Forçar ordem DNS IPv4 description: Força a ordem de DNS com prioridade para IPv4 nas chamadas de rede do Node. Útil quando o DNS IPv6 resolve, mas o roteamento IPv6 para a internet está quebrado (pode afetar o polling da API do Telegram). + + gateway_env_vars: + name: Variáveis de Ambiente do Gateway + description: Variáveis de ambiente passadas para o processo do gateway OpenClaw na inicialização (definidas como um mapa YAML; máximo de 50 variáveis, chaves com até 255 caracteres, valores com até 10.000 caracteres). From 6990b07d79a104a74b35365b491abd3e97041278 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 06:38:40 +0300 Subject: [PATCH 08/13] feat: add gateway env vars option --- DOCS.md | 1 + openclaw_assistant/CHANGELOG.md | 5 ++ openclaw_assistant/config.yaml | 2 +- openclaw_assistant/run.sh | 85 ++++++++++++++++++--------------- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/DOCS.md b/DOCS.md index c3c306b..8586068 100644 --- a/DOCS.md +++ b/DOCS.md @@ -204,6 +204,7 @@ All options are set via **Settings → Apps/Add-ons → OpenClaw Assistant → C | `enable_openai_api` | bool | `false` | Enable the OpenAI-compatible `/v1/chat/completions` endpoint. Required for [Assist pipeline integration](#6c-assist-pipeline-integration-openai-api) | | `allow_insecure_auth` | bool | `false` | Allow HTTP (non-HTTPS) authentication on LAN. **Required** for browser access over plain HTTP | | `force_ipv4_dns` | bool | `false` | Force IPv4-first DNS ordering for Node network calls. Useful if IPv6 DNS resolves but IPv6 egress is broken (can affect Telegram API polling). | +| `gateway_env_vars` | map(string) | `{}` | Environment variables exported to the gateway process at startup. Use YAML map format (for example `OPENAI_API_KEY: "sk-..."`). Limits: max 50 vars, key length 255, value length 10000. | ### Terminal diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 3ffc263..f18263c 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be documented in this file. +## [0.5.50] - 2026-02-23 + +### Added +- New add-on option `gateway_env_vars` that accepts a YAML map; values are exported verbatim to the gateway process at startup with limits (50 vars, key ≤255 chars, value ≤10000 chars). + ## [0.5.49] - 2026-02-22 ### Added diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index d37c5d9..1e5f72c 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -1,5 +1,5 @@ name: OpenClaw Assistant -version: "0.5.49" +version: "0.5.50" slug: openclaw_assistant description: Run OpenClaw Assistant (OpenClaw-compatible) as a Home Assistant add-on. url: https://github.com/techartdev/OpenClawHomeAssistant diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 77dbc7d..9c8ef5f 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -151,46 +151,53 @@ export PATH="${PNPM_HOME}:${PATH}" # Export gateway environment variables from add-on config # These are user-defined variables that should be available to the gateway process if [ "$GW_ENV_VARS" != "{}" ] && [ -n "$GW_ENV_VARS" ]; then - echo "INFO: Setting gateway environment variables from add-on config..." - env_count=0 - max_env_vars=50 - max_var_name_size=255 - - # Parse JSON object and export each key=value pair - while IFS='=' read -r key value; do - # Skip empty lines and trim whitespace - key=$(echo "$key" | xargs) - value=$(echo "$value" | xargs) - - if [ -z "$key" ]; then - continue + if printf '%s' "$GW_ENV_VARS" | jq -e 'type == "object"' >/dev/null 2>&1; then + echo "INFO: Setting gateway environment variables from add-on config..." + env_count=0 + max_env_vars=50 + max_var_name_size=255 + max_var_value_size=10000 + + # Use null-delimited key/value pairs to preserve spaces and special chars. + while IFS= read -r -d '' key && IFS= read -r -d '' value; do + if [ -z "$key" ]; then + continue + fi + + # Validate variable name format + if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then + echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" + continue + fi + + # Enforce max variable name length + if [ ${#key} -gt $max_var_name_size ]; then + echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" + continue + fi + + # Enforce max variable value length + if [ ${#value} -gt $max_var_value_size ]; then + echo "WARN: Environment variable value too long for '$key' (max $max_var_value_size chars, skip)" + continue + fi + + # Enforce limit on number of variables + if [ $env_count -ge $max_env_vars ]; then + echo "WARN: Maximum environment variables limit ($max_env_vars) reached (skip)" + continue + fi + + export "$key=$value" + ((env_count++)) + echo "INFO: Exported gateway env var: $key" + done < <(printf '%s' "$GW_ENV_VARS" | jq -j 'to_entries[] | .key, "\u0000", (.value | tostring), "\u0000"') + + if [ $env_count -gt 0 ]; then + echo "INFO: Successfully exported $env_count gateway environment variable(s)" fi - - # Validate variable name format - if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then - echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" - continue - fi - - # Enforce max variable name length - if [ ${#key} -gt $max_var_name_size ]; then - echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" - continue - fi - - # Enforce limit on number of variables - if [ $env_count -ge $max_env_vars ]; then - echo "WARN: Maximum environment variables limit ($max_env_vars) reached (skip)" - continue - fi - - export "$key=$value" - ((env_count++)) - echo "INFO: Exported gateway env var: $key" - done < <(echo "$GW_ENV_VARS" | jq -r 'to_entries[] | "\(.key)=\(.value)"') - - if [ $env_count -gt 0 ]; then - echo "INFO: Successfully exported $env_count gateway environment variable(s)" + else + echo "WARN: Invalid gateway_env_vars format in add-on options (expected JSON object), skipping" fi fi From 0dea325473aa92da3c00e2e6bd84abbc8f8a557a Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 18:17:14 +0300 Subject: [PATCH 09/13] put some guards at critical runtime env vars --- DOCS.md | 2 +- openclaw_assistant/CHANGELOG.md | 1 + openclaw_assistant/config.yaml | 2 ++ openclaw_assistant/run.sh | 27 +++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/DOCS.md b/DOCS.md index ade1baa..4a3281c 100644 --- a/DOCS.md +++ b/DOCS.md @@ -251,7 +251,7 @@ All options are set via **Settings → Apps/Add-ons → OpenClaw Assistant → C When `gateway_auth_mode: trusted-proxy` is used, the add-on sets `gateway.auth.trustedProxy.userHeader` to `x-forwarded-user` by default. | `force_ipv4_dns` | bool | `false` | Force IPv4-first DNS ordering for Node network calls. Useful if IPv6 DNS resolves but IPv6 egress is broken (can affect Telegram API polling). | -| `gateway_env_vars` | map(string) | `{}` | Environment variables exported to the gateway process at startup. Use YAML map format (for example `OPENAI_API_KEY: "sk-..."`). Limits: max 50 vars, key length 255, value length 10000. | +| `gateway_env_vars` | map(string) | `{}` | Environment variables exported to the gateway process at startup. Use YAML map format (for example `SERVICE_API_KEY: "..."`). Limits: max 50 vars, key length 255, value length 10000. Reserved runtime keys are blocked (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars). | ### Terminal diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 4020249..4a3dc20 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be docu ### Fixed - **`web_fetch failed: fetch failed`**: changed `force_ipv4_dns` default to **true**. Node 22 tries IPv6 first; most HAOS VMs lack IPv6 egress, causing outbound `web_fetch` / HTTP tool calls to time out. +- **`gateway_env_vars` safety**: block overrides for reserved runtime variables (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars) to prevent accidental startup/security regressions. ### Added - **`nginx_log_level` option** (`minimal` / `full`, default `minimal`): suppresses repetitive Home Assistant health-check and polling requests (`GET /`, `GET /v1/models`, `POST /tools/invoke`) from the nginx access log. diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index efdd48b..0c6b651 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -116,6 +116,8 @@ options: # Feature flags: # FEATURE_FLAG_X: "1" # FEATURE_FLAG_Y: "0" + # Reserved keys are blocked to protect runtime/security + # (e.g. PATH, HOME, NODE_OPTIONS, NODE_PATH, OPENCLAW_*, proxy vars). # Limits: max 50 variables, max key length 255 chars, max value length 10000 chars gateway_env_vars: {} diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 45eb713..b58bcf5 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -190,6 +190,27 @@ export PNPM_HOME="${PERSISTENT_NODE_GLOBAL}/pnpm" mkdir -p "$PNPM_HOME" export PATH="${PNPM_HOME}:${PATH}" +# Protect critical runtime variables from accidental override via gateway_env_vars. +is_reserved_gateway_env_var() { + case "$1" in + # Critical runtime paths/process vars. + HOME|PATH|PWD|OLDPWD|SHLVL|TZ|XDG_CONFIG_HOME|PNPM_HOME|NODE_PATH|NODE_OPTIONS|NODE_NO_WARNINGS) + return 0 + ;; + # Proxy vars managed by add-on options. + HTTP_PROXY|HTTPS_PROXY|NO_PROXY|http_proxy|https_proxy|no_proxy) + return 0 + ;; + # Add-on internal control vars. + OPENCLAW_*) + return 0 + ;; + *) + return 1 + ;; + esac +} + # Export gateway environment variables from add-on config # These are user-defined variables that should be available to the gateway process if [ "$GW_ENV_VARS" != "{}" ] && [ -n "$GW_ENV_VARS" ]; then @@ -212,6 +233,12 @@ if [ "$GW_ENV_VARS" != "{}" ] && [ -n "$GW_ENV_VARS" ]; then continue fi + # Protect critical runtime variables from accidental override. + if is_reserved_gateway_env_var "$key"; then + echo "WARN: Reserved environment variable '$key' cannot be overridden via gateway_env_vars (skip)" + continue + fi + # Enforce max variable name length if [ ${#key} -gt $max_var_name_size ]; then echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" From e64a85bb3a5d56299037142f01b6ae4dfd1f2ca7 Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 18:21:30 +0300 Subject: [PATCH 10/13] updated version to 0.5.52, and added a note about reserved keys in gateway_env_vars. --- openclaw_assistant/CHANGELOG.md | 6 +++++- openclaw_assistant/config.yaml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 4a3dc20..63aa31a 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -2,11 +2,15 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be documented in this file. +## [0.5.52] - 2026-02-24 + +### Added +- New add-on option `gateway_env_vars` that accepts a YAML map and safely injects values into the gateway process at startup (max 50 vars, key ≤255 chars, value ≤10000 chars). + ## [0.5.51] - 2026-02-23 ### Fixed - **`web_fetch failed: fetch failed`**: changed `force_ipv4_dns` default to **true**. Node 22 tries IPv6 first; most HAOS VMs lack IPv6 egress, causing outbound `web_fetch` / HTTP tool calls to time out. -- **`gateway_env_vars` safety**: block overrides for reserved runtime variables (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars) to prevent accidental startup/security regressions. ### Added - **`nginx_log_level` option** (`minimal` / `full`, default `minimal`): suppresses repetitive Home Assistant health-check and polling requests (`GET /`, `GET /v1/models`, `POST /tools/invoke`) from the nginx access log. diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index 0c6b651..ff1fddc 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -1,5 +1,5 @@ name: OpenClaw Assistant -version: "0.5.51" +version: "0.5.52" slug: openclaw_assistant description: Run OpenClaw Assistant (OpenClaw-compatible) as a Home Assistant add-on. url: https://github.com/techartdev/OpenClawHomeAssistant From 9908db2f99433209c04e8f870ff53fb8c906de0e Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 18:53:09 +0300 Subject: [PATCH 11/13] feat: support list based gateway env vars --- DOCS.md | 2 +- openclaw_assistant/CHANGELOG.md | 8 +- openclaw_assistant/config.yaml | 26 ++-- openclaw_assistant/run.sh | 164 ++++++++++++++------- openclaw_assistant/translations/bg.yaml | 2 +- openclaw_assistant/translations/de.yaml | 2 +- openclaw_assistant/translations/en.yaml | 2 +- openclaw_assistant/translations/es.yaml | 2 +- openclaw_assistant/translations/pl.yaml | 2 +- openclaw_assistant/translations/pt-BR.yaml | 2 +- 10 files changed, 132 insertions(+), 80 deletions(-) diff --git a/DOCS.md b/DOCS.md index 4a3281c..e9b4f57 100644 --- a/DOCS.md +++ b/DOCS.md @@ -251,7 +251,7 @@ All options are set via **Settings → Apps/Add-ons → OpenClaw Assistant → C When `gateway_auth_mode: trusted-proxy` is used, the add-on sets `gateway.auth.trustedProxy.userHeader` to `x-forwarded-user` by default. | `force_ipv4_dns` | bool | `false` | Force IPv4-first DNS ordering for Node network calls. Useful if IPv6 DNS resolves but IPv6 egress is broken (can affect Telegram API polling). | -| `gateway_env_vars` | map(string) | `{}` | Environment variables exported to the gateway process at startup. Use YAML map format (for example `SERVICE_API_KEY: "..."`). Limits: max 50 vars, key length 255, value length 10000. Reserved runtime keys are blocked (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars). | +| `gateway_env_vars` | list of `{name, value}` | `[]` | Environment variables exported to the gateway process at startup. UI format: list entries with `name` and `value` (example: `name=OPENAI_API_KEY`, `value=sk-...`). Limits: max 50 vars, key length 255, value length 10000. Reserved runtime keys are blocked (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars). Legacy string/object formats are still accepted for backward compatibility. | ### Terminal diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 63aa31a..2cbbf10 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -2,10 +2,12 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be documented in this file. -## [0.5.52] - 2026-02-24 +## [0.5.52] - 2026-02-23 ### Added -- New add-on option `gateway_env_vars` that accepts a YAML map and safely injects values into the gateway process at startup (max 50 vars, key ≤255 chars, value ≤10000 chars). +- New add-on option `gateway_env_vars` that accepts a list of `{name, value}` objects from Home Assistant UI and safely injects values into the gateway process at startup (max 50 vars, key <=255 chars, value <=10000 chars). +- Guard `gateway_env_vars` from overriding reserved runtime/proxy/`OPENCLAW_*` keys. +- Keep legacy string/object input formats for backward compatibility. ## [0.5.51] - 2026-02-23 @@ -14,7 +16,7 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be docu ### Added - **`nginx_log_level` option** (`minimal` / `full`, default `minimal`): suppresses repetitive Home Assistant health-check and polling requests (`GET /`, `GET /v1/models`, `POST /tools/invoke`) from the nginx access log. -- New add-on option `gateway_env_vars` that accepts a YAML map; values are exported verbatim to the gateway process at startup with limits (50 vars, key <=255 chars, value <=10000 chars). +- New add-on option `gateway_env_vars` and export support for gateway process environment variables with limits (50 vars, key <=255 chars, value <=10000 chars). ## [0.5.50] - 2026-02-23 diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index ff1fddc..eb873c3 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -104,22 +104,18 @@ options: # minimal: suppress repetitive HA health-check and polling requests (default) nginx_log_level: minimal - # Environment variables to pass to the gateway as a YAML map - # These variables are exported to the gateway process at startup - # Examples: - # API keys: - # OPENAI_API_KEY: "sk-abc123" - # ANTHROPIC_API_KEY: "claude-key" - # Service URLs: - # SERVICE_URL: "https://api.example.com" - # LOG_LEVEL: "debug" - # Feature flags: - # FEATURE_FLAG_X: "1" - # FEATURE_FLAG_Y: "0" + # Environment variables to pass to the gateway process at startup. + # Format: list of objects with name/value fields. + # Example: + # gateway_env_vars: + # - name: OPENAI_API_KEY + # value: "sk-abc123" + # - name: LOG_LEVEL + # value: "debug" # Reserved keys are blocked to protect runtime/security # (e.g. PATH, HOME, NODE_OPTIONS, NODE_PATH, OPENCLAW_*, proxy vars). # Limits: max 50 variables, max key length 255 chars, max value length 10000 chars - gateway_env_vars: {} + gateway_env_vars: [] schema: @@ -144,5 +140,7 @@ schema: gateway_trusted_proxies: str? enable_openai_api: bool? force_ipv4_dns: bool? - gateway_env_vars: map(str)? + gateway_env_vars: + - name: "match(^[A-Z_][A-Z0-9_]*$)" + value: str nginx_log_level: list(full|minimal)? diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index b58bcf5..21d5b13 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -55,7 +55,9 @@ GATEWAY_TRUSTED_PROXIES=$(jq -r '.gateway_trusted_proxies // empty' "$OPTIONS_FI FORCE_IPV4_DNS=$(jq -r '.force_ipv4_dns // true' "$OPTIONS_FILE") ACCESS_MODE=$(jq -r '.access_mode // "custom"' "$OPTIONS_FILE") NGINX_LOG_LEVEL=$(jq -r '.nginx_log_level // "minimal"' "$OPTIONS_FILE") -GW_ENV_VARS=$(jq -c '.gateway_env_vars // {}' "$OPTIONS_FILE") +GW_ENV_VARS_TYPE=$(jq -r 'if .gateway_env_vars == null then "null" else (.gateway_env_vars | type) end' "$OPTIONS_FILE") +GW_ENV_VARS_RAW=$(jq -r '.gateway_env_vars // empty' "$OPTIONS_FILE") +GW_ENV_VARS_JSON=$(jq -c '.gateway_env_vars // []' "$OPTIONS_FILE") export TZ="$TZNAME" @@ -211,63 +213,113 @@ is_reserved_gateway_env_var() { esac } -# Export gateway environment variables from add-on config -# These are user-defined variables that should be available to the gateway process -if [ "$GW_ENV_VARS" != "{}" ] && [ -n "$GW_ENV_VARS" ]; then - if printf '%s' "$GW_ENV_VARS" | jq -e 'type == "object"' >/dev/null 2>&1; then - echo "INFO: Setting gateway environment variables from add-on config..." - env_count=0 - max_env_vars=50 - max_var_name_size=255 - max_var_value_size=10000 +try_export_gateway_env_var() { + local key="$1" + local value="$2" - # Use null-delimited key/value pairs to preserve spaces and special chars. - while IFS= read -r -d '' key && IFS= read -r -d '' value; do - if [ -z "$key" ]; then - continue - fi - - # Validate variable name format - if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then - echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" - continue - fi - - # Protect critical runtime variables from accidental override. - if is_reserved_gateway_env_var "$key"; then - echo "WARN: Reserved environment variable '$key' cannot be overridden via gateway_env_vars (skip)" - continue - fi - - # Enforce max variable name length - if [ ${#key} -gt $max_var_name_size ]; then - echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" - continue - fi - - # Enforce max variable value length - if [ ${#value} -gt $max_var_value_size ]; then - echo "WARN: Environment variable value too long for '$key' (max $max_var_value_size chars, skip)" - continue - fi - - # Enforce limit on number of variables - if [ $env_count -ge $max_env_vars ]; then - echo "WARN: Maximum environment variables limit ($max_env_vars) reached (skip)" - continue - fi - - export "$key=$value" - ((env_count++)) - echo "INFO: Exported gateway env var: $key" - done < <(printf '%s' "$GW_ENV_VARS" | jq -j 'to_entries[] | .key, "\u0000", (.value | tostring), "\u0000"') - - if [ $env_count -gt 0 ]; then - echo "INFO: Successfully exported $env_count gateway environment variable(s)" - fi - else - echo "WARN: Invalid gateway_env_vars format in add-on options (expected JSON object), skipping" + if [ -z "$key" ]; then + return 0 fi + + # Validate variable name format + if ! [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then + echo "WARN: Invalid environment variable name: '$key' (must start with letter/underscore, skip)" + return 0 + fi + + # Protect critical runtime variables from accidental override. + if is_reserved_gateway_env_var "$key"; then + echo "WARN: Reserved environment variable '$key' cannot be overridden via gateway_env_vars (skip)" + return 0 + fi + + # Enforce max variable name length + if [ ${#key} -gt $max_var_name_size ]; then + echo "WARN: Environment variable name too long: '$key' (max $max_var_name_size chars, skip)" + return 0 + fi + + # Enforce max variable value length + if [ ${#value} -gt $max_var_value_size ]; then + echo "WARN: Environment variable value too long for '$key' (max $max_var_value_size chars, skip)" + return 0 + fi + + # Enforce limit on number of variables + if [ $env_count -ge $max_env_vars ]; then + echo "WARN: Maximum environment variables limit ($max_env_vars) reached (skip)" + return 0 + fi + + export "$key=$value" + ((env_count++)) + echo "INFO: Exported gateway env var: $key" +} + +# Export gateway environment variables from add-on config +# These are user-defined variables that should be available to the gateway process. +# Primary format: array of {name, value} objects. +if [ "$GW_ENV_VARS_TYPE" = "array" ] || [ "$GW_ENV_VARS_TYPE" = "object" ] || { [ "$GW_ENV_VARS_TYPE" = "string" ] && [ -n "$GW_ENV_VARS_RAW" ]; }; then + env_count=0 + max_env_vars=50 + max_var_name_size=255 + max_var_value_size=10000 + + if [ "$GW_ENV_VARS_TYPE" = "array" ] && [ "$GW_ENV_VARS_JSON" != "[]" ]; then + echo "INFO: Setting gateway environment variables from list config..." + + invalid_entries_count=$(printf '%s' "$GW_ENV_VARS_JSON" | jq '[.[] | select((type != "object") or ((.name | type) != "string") or (has("value") | not))] | length') + if [ "$invalid_entries_count" -gt 0 ]; then + echo "WARN: Found $invalid_entries_count invalid gateway_env_vars entries; expected objects with 'name' and 'value' keys (skip)" + fi + + while IFS= read -r -d '' key && IFS= read -r -d '' value; do + try_export_gateway_env_var "$key" "$value" + done < <(printf '%s' "$GW_ENV_VARS_JSON" | jq -j '.[] | select((type == "object") and ((.name | type) == "string") and (has("value"))) | .name, "\u0000", (.value | tostring), "\u0000"') + elif [ "$GW_ENV_VARS_TYPE" = "object" ] && [ "$GW_ENV_VARS_JSON" != "{}" ]; then + # Backward compatibility for old map/object configuration. + echo "INFO: Setting gateway environment variables from object config (legacy format)..." + while IFS= read -r -d '' key && IFS= read -r -d '' value; do + try_export_gateway_env_var "$key" "$value" + done < <(printf '%s' "$GW_ENV_VARS_JSON" | jq -j 'to_entries[] | .key, "\u0000", (.value | tostring), "\u0000"') + elif [ "$GW_ENV_VARS_TYPE" = "string" ] && [ -n "$GW_ENV_VARS_RAW" ]; then + # Preferred for complex values: JSON object string in one line. + if printf '%s' "$GW_ENV_VARS_RAW" | jq -e 'type == "object"' >/dev/null 2>&1; then + echo "INFO: Setting gateway environment variables from JSON string config..." + while IFS= read -r -d '' key && IFS= read -r -d '' value; do + try_export_gateway_env_var "$key" "$value" + done < <(printf '%s' "$GW_ENV_VARS_RAW" | jq -j 'to_entries[] | .key, "\u0000", (.value | tostring), "\u0000"') + else + # Supported simple format: KEY=VALUE pairs separated by ';' or newlines. + echo "INFO: Setting gateway environment variables from KEY=VALUE string config..." + while IFS= read -r entry; do + entry="${entry%$'\r'}" + trimmed="$(printf '%s' "$entry" | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')" + + # Skip empty lines and comments. + if [ -z "$trimmed" ] || [[ "$trimmed" == \#* ]]; then + continue + fi + + if [[ "$trimmed" != *"="* ]]; then + echo "WARN: Invalid gateway_env_vars entry '$trimmed' (expected KEY=VALUE, skip)" + continue + fi + + key="${trimmed%%=*}" + value="${trimmed#*=}" + key="$(printf '%s' "$key" | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')" + + try_export_gateway_env_var "$key" "$value" + done < <(printf '%s' "$GW_ENV_VARS_RAW" | tr ';' '\n') + fi + fi + + if [ $env_count -gt 0 ]; then + echo "INFO: Successfully exported $env_count gateway environment variable(s)" + fi +elif [ "$GW_ENV_VARS_TYPE" != "null" ]; then + echo "WARN: Invalid gateway_env_vars format in add-on options (expected list, string or object), skipping" fi # ------------------------------------------------------------------------------ diff --git a/openclaw_assistant/translations/bg.yaml b/openclaw_assistant/translations/bg.yaml index 647827e..03ea571 100644 --- a/openclaw_assistant/translations/bg.yaml +++ b/openclaw_assistant/translations/bg.yaml @@ -97,4 +97,4 @@ configuration: full: "Пълно (логване на всички заявки)" gateway_env_vars: name: Променливи на средата за Gateway - description: Променливи на средата, предавани на OpenClaw gateway процеса при стартиране (дефинирани като YAML карта; макс. 50 променливи, ключове до 255 знака, стойности до 10000 знака). + description: Променливи на средата, предавани на OpenClaw gateway процеса при стартиране (списък от записи name/value в Home Assistant UI; макс. 50 променливи, ключове до 255 знака, стойности до 10000 знака). diff --git a/openclaw_assistant/translations/de.yaml b/openclaw_assistant/translations/de.yaml index 825eb30..49448ad 100644 --- a/openclaw_assistant/translations/de.yaml +++ b/openclaw_assistant/translations/de.yaml @@ -97,4 +97,4 @@ configuration: full: "Vollständig (alle Anfragen protokollieren)" gateway_env_vars: name: Gateway-Umgebungsvariablen - description: Umgebungsvariablen, die beim Start an den OpenClaw-Gateway-Prozess übergeben werden (als YAML-Map; max. 50 Variablen, Schlüssel bis 255 Zeichen, Werte bis 10.000 Zeichen). + description: Umgebungsvariablen, die beim Start an den OpenClaw-Gateway-Prozess übergeben werden (Liste mit name/value-Einträgen in der Home Assistant UI; max. 50 Variablen, Schlüssel bis 255 Zeichen, Werte bis 10.000 Zeichen). diff --git a/openclaw_assistant/translations/en.yaml b/openclaw_assistant/translations/en.yaml index 2dbf0d8..cd2cd70 100644 --- a/openclaw_assistant/translations/en.yaml +++ b/openclaw_assistant/translations/en.yaml @@ -97,4 +97,4 @@ configuration: full: "Full (log all requests)" gateway_env_vars: name: Gateway Environment Variables - description: Environment variables passed to the OpenClaw gateway process at startup (defined as a YAML map; max 50 variables, keys up to 255 characters, values up to 10,000 characters). + description: Environment variables passed to the OpenClaw gateway process at startup (list entries with name/value in Home Assistant UI; max 50 variables, keys up to 255 characters, values up to 10,000 characters). diff --git a/openclaw_assistant/translations/es.yaml b/openclaw_assistant/translations/es.yaml index 493a41c..771716f 100644 --- a/openclaw_assistant/translations/es.yaml +++ b/openclaw_assistant/translations/es.yaml @@ -97,4 +97,4 @@ configuration: full: "Completo (registrar todas las solicitudes)" gateway_env_vars: name: Variables de entorno del Gateway - description: Variables de entorno que se pasan al proceso del gateway OpenClaw al iniciarse (definidas como un mapa YAML; máximo 50 variables, claves de hasta 255 caracteres, valores de hasta 10 000 caracteres). + description: Variables de entorno que se pasan al proceso del gateway OpenClaw al iniciarse (lista de entradas name/value en la UI de Home Assistant; maximo 50 variables, claves de hasta 255 caracteres, valores de hasta 10 000 caracteres). diff --git a/openclaw_assistant/translations/pl.yaml b/openclaw_assistant/translations/pl.yaml index bf1bdac..d7dadf0 100644 --- a/openclaw_assistant/translations/pl.yaml +++ b/openclaw_assistant/translations/pl.yaml @@ -97,4 +97,4 @@ configuration: full: "Pełny (logowanie wszystkich żądań)" gateway_env_vars: name: Zmienne środowiskowe gateway - description: Zmienne środowiskowe przekazywane do procesu gateway OpenClaw podczas uruchamiania (zdefiniowane jako mapa YAML; maks. 50 zmiennych, klucze do 255 znaków, wartości do 10000 znaków). + description: Zmienne środowiskowe przekazywane do procesu gateway OpenClaw podczas uruchamiania (lista wpisow name/value w UI Home Assistant; maks. 50 zmiennych, klucze do 255 znakow, wartosci do 10000 znakow). diff --git a/openclaw_assistant/translations/pt-BR.yaml b/openclaw_assistant/translations/pt-BR.yaml index 9187e60..8207da3 100644 --- a/openclaw_assistant/translations/pt-BR.yaml +++ b/openclaw_assistant/translations/pt-BR.yaml @@ -97,4 +97,4 @@ configuration: full: "Completo (registrar todas as requisições)" gateway_env_vars: name: Variáveis de Ambiente do Gateway - description: Variáveis de ambiente passadas para o processo do gateway OpenClaw na inicialização (definidas como um mapa YAML; máximo de 50 variáveis, chaves com até 255 caracteres, valores com até 10.000 caracteres). + description: Variaveis de ambiente passadas para o processo do gateway OpenClaw na inicializacao (lista de entradas name/value na UI do Home Assistant; maximo de 50 variaveis, chaves com ate 255 caracteres, valores com ate 10.000 caracteres). From 1c2694c526a43dc1ab14ed7ccb2266c5aedab97a Mon Sep 17 00:00:00 2001 From: macm1 Date: Mon, 23 Feb 2026 20:34:36 +0300 Subject: [PATCH 12/13] -denylist includes low-level env injection vectors too: LD_, DYLD_, BASH_ENV, ENV, BASH_FUNC_* -fixed changelog --- openclaw_assistant/CHANGELOG.md | 1 - openclaw_assistant/run.sh | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 2cbbf10..b00b7c8 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -16,7 +16,6 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be docu ### Added - **`nginx_log_level` option** (`minimal` / `full`, default `minimal`): suppresses repetitive Home Assistant health-check and polling requests (`GET /`, `GET /v1/models`, `POST /tools/invoke`) from the nginx access log. -- New add-on option `gateway_env_vars` and export support for gateway process environment variables with limits (50 vars, key <=255 chars, value <=10000 chars). ## [0.5.50] - 2026-02-23 diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 21d5b13..5d62dea 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -199,6 +199,10 @@ is_reserved_gateway_env_var() { HOME|PATH|PWD|OLDPWD|SHLVL|TZ|XDG_CONFIG_HOME|PNPM_HOME|NODE_PATH|NODE_OPTIONS|NODE_NO_WARNINGS) return 0 ;; + # Low-level injection vectors that can alter process/linker/shell behavior. + LD_*|DYLD_*|BASH_ENV|ENV|BASH_FUNC_*) + return 0 + ;; # Proxy vars managed by add-on options. HTTP_PROXY|HTTPS_PROXY|NO_PROXY|http_proxy|https_proxy|no_proxy) return 0 From 5117d7c5616695db47b7ad695d2b13581cf2c6c2 Mon Sep 17 00:00:00 2001 From: TechArtDev Date: Mon, 23 Feb 2026 22:04:29 +0200 Subject: [PATCH 13/13] Fix increment of env_count variable --- openclaw_assistant/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 5d62dea..c578e52 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -256,7 +256,7 @@ try_export_gateway_env_var() { fi export "$key=$value" - ((env_count++)) + env_count=$((env_count + 1)) echo "INFO: Exported gateway env var: $key" }