T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/codex_auth.py:518
- Finding
- Shell Command Injection Through Unsanitized Profile Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/codex_auth.py:518-560` **Vulnerability Type**: Shell command injection in a generated Bash script **Risk Level**: High ### Vulnerable Code ```python def safe_profile_slug(profile_id: str) -> str: return (profile_id or "unknown").replace(":", "_") ``` ```python if args.queue_apply: os.makedirs("/tmp/openclaw", exist_ok=True) safe_profile = safe_profile_slug(profile_id) payload_path = f"/tmp/openclaw/codex-auth-apply-{safe_profile}.json" script_path = f"/tmp/openclaw/codex-auth-apply-{safe_profile}.sh" log_path = f"/tmp/openclaw/codex-auth-apply-{safe_profile}.log" status_path = per_profile_status_path(profile_id) write_json_atomic(payload_path, {"profile": profile_id, "tokens": tokens}) py = shlex.quote(sys.executable or "python3") this_file = shlex.quote(os.path.abspath(__file__)) payload_q = shlex.quote(payload_path) auth_q = shlex.quote(args.auth_path) log_q = shlex.quote(log_path) allow_default_flag = " --allow-default" if (profile_id == "openai-codex:default" and args.allow_default) else "" script = f"""#!/usr/bin/env bash set -euo pipefail {{ echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] codex-auth apply start profile={profile_id}"; {py} {this_file} apply --payload {payload_q} --auth-path {auth_q}{allow_default_flag}; echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] codex-auth apply done profile={profile_id}"; }} >> {log_q} 2>&1 """ Path(script_path).write_text(script, encoding="utf-8") os.chmod(script_path, 0o700) launcher = "nohup" unit_name = f"codex-auth-apply-{safe_profile}-{int(time.time())}" try: sd = subprocess.run( ["systemd-run", "--user", "--unit", unit_name, "--collect", "/bin/bash", script_path], capture_output=True, text=True, timeout=15, ) if sd.returncode == 0: launcher = "systemd-run" else: subprocess ...[truncated 2791 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce a strict profile identifier allowlist before using a profile value: ```python import re PROFILE_RE = re.compile(r"^[A-Za-z0-9._-]{1,64}$") def validate_profile_suffix(value: str) -> str: if not PROFILE_RE.fullmatch(value): raise ValueError("Invalid profile identifier") return value ``` 2. Explicitly reject path separators, whitespace, control characters, shell metacharacters, backticks, dollar signs, and newline characters. 3. Do not generate executable shell scripts containing dynamic data. Implement the queued apply operation in Python and invoke subprocesses with fixed argument arrays. 4. If shell generation cannot immediately be removed, shell-quote every dynamic value with `shlex.quote()` and avoid placing dynamic values inside executable shell syntax. 5. Derive filenames and systemd unit names from a cryptographic random identifier rather than directly from a profile name. 6. Apply the same validation to profile identifiers loaded from `auth-profiles.json`, since that file may contain externally modified or previously malicious values. 7. Add regression tests using values containing `$(...)`, backticks, semicolons, quotes, newlines, spaces, `../`, and absolute paths. ]]>
