T09 · Insecure Skill Coding Practices
- Location
scripts/feishu-reaction.sh:11- Finding
Arbitrary Python Code Execution Through OPENCLAW_CONFIG Path Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/feishu-reaction.sh, lines 11–19
Vulnerability Type: Python source injection through unsafe shell-variable interpolation
Risk Level: HighVulnerable Code
bash # Locate openclaw config CONFIG="${OPENCLAW_CONFIG:-$HOME/.openclaw/openclaw.json}" if [ ! -f "$CONFIG" ]; then echo "Error: openclaw.json not found at $CONFIG" >&2 exit 1 fi # Extract Feishu credentials APP_ID=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appId'])") APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])")Technical Analysis
The value of
OPENCLAW_CONFIG, stored inCONFIG, is interpolated directly into Python source passed topython3 -c. Shell quoting protects the shell command structurally, but it does not encode the value as a safe Python string literal.An attacker-controlled configuration path containing a single quote and valid Python syntax can terminate the intended
open('...')expression and inject additional Python statements or expressions. The file-existence check does not eliminate the issue because Unix filenames can contain quotes and other characters usable in a Python injection sequence. If an attacker can create a correspondingly named file and controlOPENCLAW_CONFIG, the injected Python executes with the privileges of the user running the Skill.The unsafe value is evaluated twice, once while extracting
appIdand again while extractingappSecret.Attack Path
- An attacker gains influence over the environment used to invoke the Skill, particularly
OPENCLAW_CONFIG. - The attacker creates a file whose path both passes the
-fcheck and contains characters that terminate the Python string literal. - The attacker sets
OPENCLAW_CONFIGto that crafted path. - The script interpolates the path into the
python3 -cprogram without ...[truncated 1002 chars]
- An attacker gains influence over the environment used to invoke the Skill, particularly
- Remediation
View remediation
Remediation Suggestions
Never embed a dynamic path directly in Python source. Pass it as a positional argument:
bash APP_ID=$(python3 - "$CONFIG" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as config_file: config = json.load(config_file) print(config["channels"]["feishu"]["appId"]) PY ) APP_SECRET=$(python3 - "$CONFIG" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as config_file: config = json.load(config_file) print(config["channels"]["feishu"]["appSecret"]) PY )Additional hardening should include:
- Resolve the path to a canonical absolute path before use.
- Restrict custom configuration paths to explicitly trusted directories where feasible.
- Verify that the configuration is a regular file and is not unexpectedly writable by other users.
- Parse the configuration once rather than invoking Python separately for each credential.
- Ensure errors never print
appSecretor tenant tokens. - Apply restrictive filesystem permissions to the OpenClaw configuration.
