T09 · Insecure Skill Coding Practices
- Location
scripts/poetize_cli.py:965- Finding
Documented confirmation gate is not enforced by state-changing CLI operations
- Content
View full analysis
Vulnerability Details
File Location:
scripts/poetize_cli.py:965-979
Vulnerability Type: Missing executable authorization and confirmation enforcement
Risk Level: MediumComplete Code Snippet
python if mc == "delete-article": article_id = resolve_article_id(args) brief = resolve_brief(args) payload = apply_ops_strategy( brief, {"id": article_id}, expected_task_type="delete_article", ) response = call_recycle_bin_api( "POST", f"{args.base_url.rstrip('/')}/api/api/article/delete", args.api_key, payload, ) if response.get("code") == 200: retention_days = (response.get("data") or {}).get("retentionDays") window = f"{retention_days} days" if retention_days else "the retention window" response["agent_guide"] = { "message": ( "Article moved to the recycle bin. It is recoverable during " f"the retention window ({window}); permanent purge happens " "automatically only after that." ), "next_steps": [ "Verify it is in trash: python poetize_cli.py manage list-trash", f"Restore it: python poetize_cli.py manage restore-article " f"--article-id {article_id}", ], }Other directly reachable mutation examples include:
python if mc == "delete-resource": body: dict[str, Any] = {} if getattr(args, "resource_id", None): body["id"] = args.resource_id if getattr(args, "path", None): body["path"] = args.path if not body: raise SystemExit("delete-resource requires --resource-id or --path") response = call_recycle_bin_api( "POST", f"{args.base_url.rstrip('/')}/api/api/resource/delete", args.api_key, body, )python if mc == "activate-theme": response = request_json( "POST", f"{args.base_url.rst ...[truncated 3662 chars]- Remediation
View remediation
Remediation Suggestions
- Add a centralized mutation gate before dispatching every state-changing command.
- Require an explicit confirmation artifact, such as
--confirm, that is bound to:- The exact operation.
- The concrete target identifier or path.
- The destination blog origin.
- Reject mutation requests if the confirmation data does not match the resolved operation and target.
- Prefer a two-step workflow:
- First generate a dry-run or preview containing the destination, target, and exact payload.
- Then execute only after receiving a fresh confirmation token for that preview.
- Do not treat a strategy brief as user authorization unless it contains verifiable, operation-bound approval generated after the preview.
- Apply the check centrally so new mutation subcommands cannot accidentally omit it.
- Add automated tests asserting that every mutating command fails before any network request when confirmation is absent or mismatched.
- Preserve non-interactive automation by supporting a machine-readable approval token rather than relying exclusively on an interactive prompt.
