T09 · Insecure Skill Coding Practices
- Location
scripts/run_setup.py:6- Finding
Unsafe External Module Loading from a Shared Writable Directory
- Content
View full analysis
Vulnerability Details
File Location:
scripts/run_setup.py:6-7, 22-30
Vulnerability Type: Python module search-path hijacking
Risk Level: HighVulnerable Code
python def _repo_root() -> Path: return Path(__file__).resolve().parents[3]python repo_root = _repo_root() sys.path.insert(0, str(repo_root)) try: from setup_package import setup_openclaw_package # type: ignore except Exception as e: print(f"STATUS: FAILED. Could not import setup_package.py: {e}") return 1 result = setup_openclaw_package( api_key=args.api_key, mac_permission_confirmed=bool(args.mac_permission_confirmed), )Technical Analysis
In the audited directory layout, the script is located at:
text /tmp/clawhub-codex-scan-v57bx59bfkbyn5fe24xvwrtktx8egd74-n00wnX/artifact/scripts/run_setup.pyPath(__file__).resolve().parents[3]therefore resolves to/tmp, rather than the project or Skill root. The script inserts this shared temporary directory at index zero ofsys.path, giving it precedence during Python module resolution.The subsequent import of
setup_packagecan consequently load/tmp/setup_package.py. This module is not included in the audited project, and its integrity, origin, and behavior are not verified. Importing a Python module executes its top-level code immediately.The imported function also receives the API key supplied by the user. A malicious module can therefore execute arbitrary Python code and directly capture the secret.
Attack Path
- An attacker obtains the ability to create
/tmp/setup_package.py, such as through another compromised process or an unsafe temporary-file workflow. - The attacker defines malicious top-level code or a malicious
setup_openclaw_packagefunction in that file. - The user follows
SKILL.mdand invokespython3 scripts/run_setup.py, potentially ...[truncated 862 chars]
- An attacker obtains the ability to create
- Remediation
View remediation
Remediation Suggestions
- Package
setup_package.pyinside the audited project and import it through a package-relative import. - Derive the project root from the actual package layout rather than using a fixed and incorrect parent depth.
- Do not prepend
/tmpor any other shared writable directory tosys.path. - Resolve the expected module path explicitly and verify with
Path.resolve()that it remains within the trusted project directory. - Fail closed when the trusted installer module is missing instead of searching external locations.
- If dynamic module loading is unavoidable, verify the module against a pinned cryptographic hash or trusted signature before execution.
- Add a regression test that asserts the calculated root equals the expected project directory and that imports cannot resolve from
/tmp. - Avoid passing secrets to unaudited extension modules; keep secret handling inside a trusted, packaged implementation.
- Package
