T08 · Insecure Dependencies
- Location
- scripts/pipeline_advance.py:223
- Finding
- Unverified External Script Execution, Including During Dry-Run<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pipeline_advance.py`, lines 43–44, 61–62, 223–237, and 362 **Vulnerability Type**: Unverified execution of code outside the audited Skill package **Risk Level**: High ### Complete Code Snippet ```python _SKILL_DIR = _SCRIPTS_DIR.parent _WORKSPACE = _SKILL_DIR.parent.parent # workspace/skills/<skill>/scripts → workspace FACT_CHECKER_SCRIPT = _WORKSPACE / "skills" / "fact-checker" / "scripts" / "fact_check.py" PYTHON = "/Users/loki/.pyenv/versions/3.14.3/bin/python3" def run_factcheck(file_path: Path) -> Optional[str]: """Run fact_check.py if available. Returns report string or None.""" if not FACT_CHECKER_SCRIPT.exists(): return None result = subprocess.run( [PYTHON, str(FACT_CHECKER_SCRIPT), str(file_path)], capture_output=True, text=True, timeout=120, ) output = result.stdout if result.stderr: output += f"\n[stderr]: {result.stderr[:200]}" return output.strip() if output.strip() else "(no output)" # The subprocess is reached even when dry_run is True. report = run_factcheck(file_path) ``` ### Technical Analysis The Skill invokes a sibling `fact_check.py` script that is outside its own audited package. The only validation is an existence check. It does not verify the external file's ownership, permissions, expected version, cryptographic digest, or provenance. The Python interpreter is also selected through a hardcoded absolute path outside the Skill's trust boundary. If either that interpreter or the sibling script can be replaced or modified, invoking the pipeline executes attacker-controlled code with the privileges of the user running the Skill. The fact-check call is not conditioned on `dry_run`. Consequently, `--dry-run`, which is documented as a preview that should not make changes, can still execute arbitrary external code and allow any network or filesystem side effects implemented by that external c ...[truncated 1622 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Package the fact-checking implementation as an audited, versioned dependency instead of locating mutable code at a predictable sibling path. 2. Pin the accepted dependency version and verify a cryptographic digest or signed manifest before execution. 3. Validate that the script and interpreter are owned by an expected user and are not group- or world-writable. 4. Replace the machine-specific interpreter path with `sys.executable` or a securely configured, verified interpreter. 5. Require explicit user opt-in before invoking code outside the Skill package. 6. Do not call `run_factcheck()` when `dry_run` is enabled: ```python if dry_run: report = None print(" [dry-run] Would run fact-checker") else: report = run_factcheck(file_path) ``` 7. Run the fact-checker in a restricted subprocess environment: - Remove unrelated credentials from `env`. - Restrict filesystem access where sandboxing is available. - Disable network access unless fact-checking explicitly requires it. 8. Treat nonzero subprocess exit codes and timeouts as failures rather than accepting partial output without validation. ]]>
