T08 · Insecure Dependencies
Warning
- Location
- scripts/advisor.py:21
- Finding
- Unverified Python Modules Loaded from a Mutable User Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/advisor.py:21-28, 61-62`; `scripts/cross_ref.py:15-17, 42-46` **Vulnerability Type**: Unsafe dynamic module resolution from an unverified sibling Skill **Risk Level**: Medium ### Vulnerable Code ```python # scripts/advisor.py:21-28 _SCREENER_DIR = os.path.expanduser('~/.workbuddy/skills/volume-price-screener/scripts') _CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) if '__file__' in dir() and '__file__' in locals() else os.path.dirname(os.path.abspath(sys.argv[0])) if _CURRENT_DIR not in sys.path: sys.path.insert(0, _CURRENT_DIR) if os.path.exists(_SCREENER_DIR) and _SCREENER_DIR not in sys.path: sys.path.append(_SCREENER_DIR) ``` ```python # scripts/advisor.py:61-62 try: from data_provider import get_kline, get_realtime_quote ``` ```python # scripts/cross_ref.py:15-17 _SCREENER_DIR = os.path.expanduser('~/.workbuddy/skills/volume-price-screener/scripts') if _SCREENER_DIR not in sys.path: sys.path.insert(0, _SCREENER_DIR) ``` ```python # scripts/cross_ref.py:42-46 try: from pattern_detect import detect_pattern, Bar from scoring import score_pattern except ImportError: return None ``` ### Technical Analysis The application adds `~/.workbuddy/skills/volume-price-screener/scripts` to Python's module search path and subsequently imports `data_provider`, `pattern_detect`, and `scoring` by unqualified module name. No package version, cryptographic hash, canonical origin, file ownership, or directory permission verification is performed before these modules are imported. In `cross_ref.py`, the external directory is inserted at index zero, giving modules in that directory priority over other modules with the same names. Python executes module-level code during import. Therefore, any party able to create or replace files in the sibling Skill directory can execute arbitrary Python code when the affected import path is reached. This is a local supply-chain and depe ...[truncated 1481 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Package the sibling functionality as a normal, versioned Python dependency rather than modifying `sys.path`. 2. Pin the dependency to an audited version and use a lockfile containing cryptographic hashes. 3. Install dependencies in an isolated virtual environment with restricted write permissions. 4. Use package-qualified imports to prevent module-name collisions. 5. If external-directory loading is unavoidable: - Resolve and validate the canonical directory path. - Confirm that the directory and module files are owned by the expected user. - Reject group-writable or world-writable directories and files. - Verify each imported file against a trusted SHA-256 allowlist. - Load modules by an explicit validated file path rather than by an ambiguous module name. 6. Avoid placing external dependency directories at the beginning of `sys.path`. 7. Document the sibling Skill as an executable trust dependency in the manifest, including its expected version and integrity requirements. ]]>
