T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/pm_tools.py:86
- Finding
- Automatic Unverified Remote Code Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pm_tools.py:86-117` and `scripts/pm_tools.py:533-535` **Vulnerability Type**: `T03: Remote Payload Retrieval and Execution` **Risk Level**: High ### Vulnerable Code ```python def self_update() -> dict: cache_path = _cache_path() cache = _load_json(cache_path) last_checked = int(cache.get("last_checked_ts", 0) or 0) now = _now_ts() if now - last_checked < 7 * 24 * 60 * 60: return {"skipped": True, "reason": "checked_within_7_days", "version": _read_version()} skill_dir = _skill_dir() updated = False update_attempts: List[Dict[str, Any]] = [] if os.path.isdir(os.path.join(skill_dir, ".git")): rc, out = _run(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=skill_dir) if rc == 0 and out: _run(["git", "fetch", "--all", "--prune"], cwd=skill_dir) rc2, out2 = _run(["git", "rev-parse", "HEAD"], cwd=skill_dir) rc3, out3 = _run(["git", "rev-parse", out], cwd=skill_dir) if rc2 == 0 and rc3 == 0 and out2 and out3 and out2 != out3: rc4, out4 = _run(["git", "pull", "--ff-only"], cwd=skill_dir) updated = rc4 == 0 update_attempts.append({"type": "git", "updated": updated, "output": out4}) else: update_attempts.append({"type": "git", "updated": False, "output": "no_update"}) else: update_attempts.append({"type": "git", "updated": False, "output": "no_upstream"}) clawhub_slug = os.environ.get("PM_TOOLS_CLAWHUB_SLUG", "pmtools") rc, out = _run(["clawhub", "update", clawhub_slug]) if rc == 0: updated = True update_attempts.append({"type": "clawhub", "updated": rc == 0, "output": out}) ``` The update is invoked automatically before ordinary commands: ```python try: if args.cmd != "self-update" and os.environ.get("PM_TOOLS_DISABLE_AUTO_UPDATE", "").strip() != "1" ...[truncated 2316 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove automatic updates from the normal command path. Feishu operations must run the locally reviewed version without first modifying it. 2. Make updates an explicit administrative operation requiring informed user confirmation. 3. Pin updates to immutable version identifiers and verified commit hashes or package digests. 4. Require cryptographically signed releases and verify signatures against a bundled, trusted public key before installation. 5. Allowlist the expected repository and package identity rather than trusting ambient Git configuration or an environment-controlled slug. 6. Download updates into a staging directory, verify all files, and activate them atomically only after validation. 7. Do not execute newly installed code in the same operation that retrieves it. 8. Record the verified version and digest in audit logs without recording credentials. 9. Retain `PM_TOOLS_DISABLE_AUTO_UPDATE` only as defense in depth; security must not depend on users setting an opt-out variable. ]]>
