T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/update_repo.py:84
- Finding
- Mutable Repository Update Followed by Automatic Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/update_repo.py:84-128`; documented for users in `scripts/README.md:27-31` and `scripts/README.md:76-80` **Vulnerability Type**: Remote code and dependency supply-chain execution **Risk Level**: Critical ### Vulnerable Code ```python def sync_python_dependencies() -> None: if not REQUIREMENTS_FILE.exists(): print("requirements.txt not found; skipping Python dependency sync.") return print("requirements.txt changed. Syncing Python dependencies...") result = run_command([sys.executable, "-m", "pip", "install", "-r", str(REQUIREMENTS_FILE)]) if result.stdout.strip(): print(result.stdout.strip()) if result.stderr.strip(): print(result.stderr.strip()) def main() -> int: args = parse_args() try: ensure_git_available() ensure_clean_tracked_worktree() before_head = get_head_revision() before_requirements = file_digest(REQUIREMENTS_FILE) print(f"Repository: {REPO_ROOT}") pull_result = run_command(["git", "pull", "--ff-only"]) if pull_result.stdout.strip(): print(pull_result.stdout.strip()) if pull_result.stderr.strip(): print(pull_result.stderr.strip()) after_head = get_head_revision() after_requirements = file_digest(REQUIREMENTS_FILE) if before_head == after_head: print("Repository is already up to date.") else: print(f"Updated from {before_head[:7]} to {after_head[:7]}.") if args.skip_pip: print("Skipped Python dependency sync (--skip-pip).") elif before_requirements != after_requirements: sync_python_dependencies() else: print("requirements.txt unchanged. Skipping Python dependency sync.") ``` The operation is explicitly exposed as a normal repository-maintenance command: ```markdown Repository update: ```bash python3 scripts/update_ ...[truncated 2318 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Separate repository updates from dependency installation. An update command must not automatically install newly introduced dependencies. 2. Require an explicit second command or interactive approval after presenting the exact `requirements.txt` diff. 3. Update only from an allowlisted remote URL and verify the remote before pulling. 4. Retrieve signed release tags or commits and verify signatures against pinned maintainer keys. 5. Replace unconstrained requirements with a reviewed lock file containing exact versions and hashes. 6. Install with hash enforcement, for example `pip install --require-hashes -r requirements.lock`. 7. Reject direct URLs, editable installations, alternate indexes, and VCS dependencies unless individually approved. 8. Run installation in an isolated virtual environment with minimal filesystem and network privileges. 9. Default to `--skip-pip` behavior and make dependency synchronization an explicit opt-in operation. ]]>
