T09 · Insecure Skill Coding Practices
- Location
scripts/publish.py:1017- Finding
Marketplace publication lacks executable confirmation and preflight enforcement
- Content
View full analysis
Vulnerability Details
File Location:
scripts/publish.py:950, 1017, 1074-1084; related requirement atSKILL.md:267-268
Vulnerability Type: Unconfirmed external publication using stored account credentials
Risk Level: MediumCode Snippet
python creds, err = load_creds(host_override) if not creds: print(json.dumps({"success": False, "error": err}, ensure_ascii=False, indent=2)) return 1 token, host = credspython for attempt in range(max_retry): last_status, last_body = post_publish(host, token, payload, files) if last_status == 429: ra = last_body.get("retryAfter") or delay try: ra = int(ra) except Exception: ra = delay print(f" [429] 限流,等待 {ra}s({attempt+1}/{max_retry})", file=sys.stderr, flush=True) time.sleep(ra) delay = min(delay * 2, 600) continue breakpython pp = sub.add_parser("publish", help="发布/更新") pp.add_argument("dir") pp.add_argument("--version", default="") pp.add_argument("--changelog", default="") pp.add_argument("--icon", "--cover", dest="icon", default=None, help="图标/封面图片(png/jpg/webp,≤2MB)。走 skill-icons/upload 上传") pp.add_argument("--slug", default="") pp.add_argument("--host", default=None) pp.add_argument("--dry-run", action="store_true") pp.add_argument("--force", action="store_true", help="跳过版本递增检查")The corresponding Skill instructions state:
markdown 1. **绝不在回复中打印、展示或记录 token**(`skh_` / `gho_` / `ghp_` 开头一律脱敏)。 2. 发布前必须跑预检、必须获得用户确认。Technical Analysis
The Skill documentation requires both preflight validation and user confirmation before publication. However, the executable entry point does not enforce either requirement. The
publishsubcommand only distinguishes a dry run from a real publication; it has no mandatory confirmation parameter, confirmation to ...[truncated 2063 chars]- Remediation
View remediation
Remediation Suggestions
- Require a dedicated confirmation argument such as
--yes-publishfor every non-dry-run publication and reject the operation when it is absent. - Run
preflight.py --jsoninternally before loading credentials or performing network requests, and block publication when preflight reports an error. - Before confirmation, display the destination host, authenticated account, slug, version, icon, category, complete upload file list, and total size.
- Consider requiring confirmation data bound to the reviewed publication plan, such as a digest of the final file bundle and metadata, so modifications after review invalidate approval.
- Keep
--dry-runas the default behavior for agent-driven workflows and permit live publication only after explicit user authorization. - Document that changing
--hostchanges the credential recipient, and include the resolved host in the mandatory confirmation summary.
- Require a dedicated confirmation argument such as
