T08 · Insecure Dependencies
Error
- Location
- __main__.py:70
- Finding
- Default Migration Executes an Unpinned Global Package Through Shell-Based PATH Resolution## Vulnerability Details **File Location**: `__main__.py:70-73`, `openclaw_setup.py:21-27`, `openclaw_setup.py:45-52`, `tui.py:186-190` **Vulnerability Type**: Unpinned dependency installation and unsafe executable resolution **Risk Level**: High ### Vulnerable Code ```python # __main__.py:70-73 # --- Always reinstall openclaw (unless user explicitly opted out via flag) --- if setup_openclaw or not skip_verify: # Default behavior: reinstall openclaw at the end print("Reinstalling openclaw (npm i -g openclaw)...", file=sys.stderr) setup_result = install_openclaw_and_onboard(out_root) ``` ```python # openclaw_setup.py:21-27 r = subprocess.run( "npm install -g openclaw", capture_output=True, text=True, timeout=120, shell=True, ) ``` ```python # openclaw_setup.py:45-52 r = subprocess.run( "openclaw onboard", cwd=str(target_dir), capture_output=True, text=True, timeout=60, shell=True, ) ``` ```python # tui.py:186-190 # --- Always reinstall openclaw --- print(style("\n Reinstalling openclaw (npm i -g openclaw)...", CYAN)) print(style(" This ensures you have the latest version.\n", DIM)) setup_result = install_openclaw_and_onboard(out_root) ``` ### Technical Analysis The noninteractive migration command installs OpenClaw when the following condition is true: ```python setup_openclaw or not skip_verify ``` Because verification is enabled by default, `skip_verify` is normally false and `not skip_verify` is true. Consequently, a standard migration invokes the installation even when the user did not provide the apparently opt-in `--setup-openclaw` option. The command installs the latest available version of `openclaw` globally without a pinned version or integrity constraint. It then invokes both `npm` and `openclaw` through `shell=True`, allowing the shell to resolve those executable names from the invoking proce ...[truncated 2173 chars]
- Remediation
- ## Remediation Suggestions 1. Make OpenClaw setup strictly opt-in: ```python if setup_openclaw: setup_result = install_openclaw_and_onboard(out_root) ``` 2. Add a separate explicit `--no-setup-openclaw` option only if backward compatibility requires automatic behavior, and issue a clear confirmation prompt before any global installation. 3. Replace shell command strings with argument arrays and disable the shell: ```python subprocess.run( ["npm", "install", "--global", "openclaw@AUDITED_VERSION"], shell=False, check=False, capture_output=True, text=True, timeout=120, ) ``` 4. Resolve executables with `shutil.which`, reject suspicious or unexpected executable locations, and document the resolved path before execution. 5. Pin OpenClaw to a reviewed version. Where supported, verify package integrity or use a lockfile and trusted registry configuration. 6. Prefer a project-local or isolated installation over a global installation. 7. Separate migration from onboarding so copying files never implicitly executes third-party code. 8. Correct the documentation so installation behavior, network access, global modifications, and consent requirements are stated consistently.
