Back to skill

Security audit

卖家精灵ARI 亚马逊Amazon智能评论分析系统

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real ARI Amazon review-analysis skill, but it can spend account credits without a fresh per-task confirmation under its auto-confirm rules.

Install only if you trust ARI with your Amazon review-analysis data and are comfortable storing an ARI API key locally. Before using it, set the account to ask before every paid operation if you do not want auto-confirmed credit spending, and be cautious with export --out paths because existing files can be overwritten.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:239
Finding
Mandatory Promotional Output and Unsolicited Workflow Expansion<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:40`, `SKILL.md:111-117`, `SKILL.md:139-160`, and `SKILL.md:239-241` **Vulnerability Type**: T01: Skill Instruction Hijacking **Risk Level**: High ### Relevant Source Snippets ```markdown - CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如 `python scripts/ari.py check`;每次会话先跑一次 `check`。 ``` ```markdown 8. 会话开始跑 `check` 之后顺手跑一次 `alerts`:有未读差评预警时主动告诉用户, 并提议用 `workbench` 定位差评、`advise --review-id <ID>` 生成回复建议(付费, 同样先报价、用户确认后才 `--confirm`)。 ``` ```markdown 11. 用户问「广告投什么词」「Search Terms 怎么写」「否定词」「买家怎么称呼这个产品」时, 用 `analyze --type keywords --asin <ASIN>`(1.4.4,先报价、确认后 `--confirm`)。 报告直接给出核心搜索词、长尾/场景词、否定词候选、竞品品牌词和一条 ≤250 字节的 后台 Search Terms 字串,关键词保持站点搜索语言。**VOC 报告出来之后主动提一句**: 评论里买家的用词就是最好的关键词来源,多数卖家没意识到这份数据可以直接投广告。 ``` ```markdown **网页链接的用法** - 每份报告末尾附 `web.report`,措辞是「网页版有健康度图表和频次表,可生成分享链接与海报」——是补充,不是「建议你去网页」。 ``` ```markdown 结尾简要列出 ASIN/站点、样本量、统计窗口(`_window.days`)、报告返回的 `reportId` 与 `creditsUsed`,以及当前余额。**输出含 `reportUrl` 时必须在结尾附上**, 固定文案:「在线查看图表版完整报告 / 导出:<reportUrl>」(需登录报告所属账户)。 ``` ### Technical Analysis The Skill instructions require the agent to perform actions that are not always necessary to satisfy the user's immediate request: 1. It mandates an authenticated account check at the start of every session. 2. It instructs the agent to query alerts after the account check, even when alerts are unrelated to the current task. 3. It requires proactive promotion of additional paid analysis functionality after VOC reports. 4. It requires fixed vendor-facing wording and an external report link in qualifying responses. These directives modify the agent's response and tool-use policy when the Skill is loaded. They prioritize vendor engagement, account telemetry, and paid-feature promotion over strict task minimization. This is broader than the minimum privilege and network access needed to analyze a specified Amazon product. The behavior does not grant operating-system privileges, b ...[truncated 1579 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the unconditional requirement to run `check` during every session. 2. Run account checks only when authentication, balance, or billing status is necessary for the requested operation. 3. Query alerts only when the user asks about alerts, monitoring, negative-review management, or a directly related workflow. 4. Remove mandatory promotional follow-ups after VOC reports. 5. Include `reportUrl` only when the user requests an online report, export, sharing function, or when the link is essential to retrieve the requested result. 6. Replace fixed promotional wording with neutral, task-specific language. 7. Add a clear instruction that optional feature suggestions must not be included when the user requests a concise response. 8. Apply a least-network-access rule: do not call authenticated endpoints unless their results are required to complete the active user request. ]]>

other

Warning
Location
scripts/ari.py:1144
Finding
Server-Controlled Auto-Confirmation Can Trigger Charges Without Task-Specific Consent<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ari.py:1144-1151` and `scripts/ari.py:1354-1362` **Vulnerability Type**: other: Unconfirmed Paid Operation **Risk Level**: Medium ### Relevant Source Snippets ```python # 首次体验免确认(服务端策略 skill.autoConfirm):前几次小额直接生成,不再多问一轮。 auto_confirmed = False if not confirm and q_data.get("autoConfirm") and q_data.get("sufficient"): confirm = True auto_confirmed = True if not confirm: return {"success": True, "data": {"confirmationRequired": True, "quote": q_data, "webUrl": q_data.get("webUrl"), "message": "用户确认后追加 --confirm 才会生成并扣点。"}, "links": links()} ``` ```python # 首次体验免确认:服务端 autoConfirm=true 且「采集 + 报告」合计不超过单次上限时,直接跑完。 # 在聊天里多问一句「确认吗」,很多用户就不回了——先让他拿到结果。 auto_max = int(analysis_quote.get("autoConfirmMaxCredits") or 0) auto_confirmed = (not args.confirm and bool(analysis_quote.get("autoConfirm")) and sufficient and total_credits <= auto_max) if not args.confirm and not auto_confirmed: combined_quote["autoConfirmRemaining"] = analysis_quote.get("autoConfirmRemaining") emit({"success": True, "data": combined_quote, "links": links()}, args.compact) return ``` ### Technical Analysis The `run_analysis` and `cmd_voc` workflows can execute chargeable operations even when the caller did not supply `--confirm`. A server-provided quote field, `autoConfirm`, is used to convert the absence of local confirmation into permission to proceed. The behavior is documented as a first-run or small-charge account policy, but the authorization decision for the current task remains controlled by remote response data. Consequently, a CLI invocation that lacks an explicit confirmation flag does not reliably mean “quote only.” This creates a confused-consent boundary: - The local caller has not explicitly confirmed the current charge. - The remote service supplies both the price information and t ...[truncated 1748 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require `--confirm` for every operation capable of consuming credits. 2. Treat a missing `--confirm` flag as an unconditional quote-only request. 3. If auto-confirmation is retained, require explicit local opt-in such as `--use-auto-confirm`. 4. Store any auto-confirm preference locally and display its exact limit before executing the operation. 5. Do not permit a remote response field alone to create authorization to spend credits. 6. Bind confirmation to immutable quote details, including: - operation type; - ASIN and site; - maximum credit charge; - quote identifier; - quote expiration; - authenticated account. 7. Require the server to reject execution if the submitted charge exceeds the confirmed amount. 8. Return the quote without execution whenever price fields are missing, malformed, or inconsistent. 9. Update Agent instructions so that task-specific consent is obtained before any charge unless the user has explicitly enabled a clearly disclosed local auto-confirm policy. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/ari.py:1489
Finding
Unrestricted Export Path Allows Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ari.py:1489-1506`, `scripts/ari.py:1621-1635`, and `scripts/ari.py:1962` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Low ### Relevant Source Snippets ```python def request_download(path, params, dest): """下载非 JSON 响应(CSV / HTML / Markdown)到本地文件。 服务端在计划限制、参数错误等情况下仍返回 JSON 错误信封——先看 Content-Type, JSON 一律按信封透传,不落盘。CSV 流式导出中途出错时响应头已发出,服务端只能 在文件末尾追加「# export error:」注释行,这里嗅探出来转成显式错误。 """ query = {"method": "GET", "path": path, "params": {k: v for k, v in (params or {}).items() if v not in (None, "")}, "payload": None} try: req = api_request("GET", path, params=query["params"], accept="*/*") with open_api(req, timeout=TIMEOUT_SEC) as resp: note_release(resp.headers) ctype = resp.headers.get("Content-Type", "") body = resp.read() if "application/json" in ctype: out = json.loads(body.decode("utf-8", errors="replace")) if isinstance(out, dict): out["_query"] = query return out tail = body[-300:].decode("utf-8", errors="replace") if "# export error:" in tail: return error_obj("ARI_EXPORT_ERROR", 200, tail.split("# export error:", 1)[1].strip(), "导出中途失败,文件不完整,未落盘。", query) with open(dest, "wb") as fh: fh.write(body) ``` ```python def cmd_export(args): """导出评论 CSV 或报告 HTML/Markdown 到本地文件(付费套餐功能,不扣积点)。""" if args.report_id: fmt = args.format or "md" dest = args.out or ("ari_report_%d.%s" % (args.report_id, "html" if fmt == "html" else "md")) emit(request_download("/api/v1/export/reports/%d" % args.report_id, {"format": fmt}, dest), args.compact) r ...[truncated 2897 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Save exports under a dedicated directory such as `~/.ari/exports` by default. 2. Resolve the destination with `os.path.realpath` and verify that it remains inside the approved export directory. 3. Reject symbolic links using `os.lstat` and platform-appropriate no-follow semantics. 4. Create new files exclusively with `os.open` using `O_CREAT | O_EXCL | O_WRONLY`. 5. Refuse to overwrite existing files unless the user supplies a separate explicit overwrite flag. 6. If overwriting is permitted, display the normalized absolute path and require explicit confirmation. 7. Download into a securely created temporary file in the destination directory, validate the completed content, and atomically rename it. 8. Apply restrictive permissions to newly created exports where their contents may be sensitive. 9. Warn users not to run the CLI with elevated privileges. 10. Add regression tests covering absolute paths, parent traversal, existing targets, symbolic links, and overwrite attempts. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (67)

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- CLI:本 Skill 目录下的 `scripts/ari.py`。在 Skill 根目录执行,例如
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This markdown file uses only Chinese for user-facing release notes, which can constitute a language policy violation when no opt-in, alternative language, or justification is provided. The issue is visible across the substantive changelog entries rather than a single isolated line.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill explicitly instructs use of local shell commands, network access, environment-based secrets, and local configuration persistence, but it declares no tool scope or permission boundaries. That creates an overprivileged integration surface where an agent could execute commands, read/write local state, and send data over the network without an enforceable least-privilege contract.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. 运行 `check`,确认账户、邮箱验证状态和可用积点。
2. 用户要 VOC / 评论分析报告时,默认运行 `voc <ASIN> --site <站点>`。
   **返回里有 `autoConfirmed: true` 就说明已经直接生成了**(1.4.5 起:服务端对前几次小额
   付费操作免确认,用户先拿到结果再谈钱),此时把报告讲给用户,并转述 `autoConfirmNote`
   (本次扣了多少、还剩几次免确认、之后会先问)。**不要在拿到结果后再补问「要不要生成」。**
3. 返回 `confirmationRequired: true` 才需要用户确认:报出 `totalCredits` 与余额,
Confidence
97% confidence
Finding
The workflow authorizes paid report generation based on a server-side autoConfirmed state, instructing the agent to proceed without obtaining an explicit per-action user confirmation in the current session. This weakens user-consent safeguards for billable actions and can lead to unintended charges or irreversible paid operations triggered from ambiguous natural-language requests.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. 运行 `check`,确认账户、邮箱验证状态和可用积点。
2. 用户要 VOC / 评论分析报告时,默认运行 `voc <ASIN> --site <站点>`。
   **返回里有 `autoConfirmed: true` 就说明已经直接生成了**(1.4.5 起:服务端对前几次小额
   付费操作免确认,用户先拿到结果再谈钱),此时把报告讲给用户,并转述 `autoConfirmNote`
   (本次扣了多少、还剩几次免确认、之后会先问)。**不要在拿到结果后再补问「要不要生成」。**
3. 返回 `confirmationRequired: true` 才需要用户确认:报出 `totalCredits` 与余额,
   用户同意后运行 `voc <ASIN> --site <站点> --confirm`。该命令会自动补齐采集、等待任务完成、
Confidence
96% confidence
Finding
The skill instructs the agent to execute `voc ... --confirm` after a minimal confirmation flow, while the surrounding design normalizes autonomous progression from natural language to paid execution. In practice, this reduces friction around spend authorization and increases the chance of accidental charges or actions that the user did not fully understand.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
用户只说自然语言。网页是补充视图(图表、分享链接、海报),不是把人送走的地方。

**确认与扣点**
- 报价返回 `autoConfirm: true` 时直接生成,不要再问「要不要」。生成后一句话交代:本次扣了多少、
  还剩几次免确认(或「免费版小额不问」)。策略由服务端决定:免费版小额不问;付费版前几次不问,之后先问。
- 用户说「以后别问了 / 50 以内直接做」→ 运行 `autoconfirm 50`;说「以后每次先问我」→ `autoconfirm off`;
  说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
Confidence
97% confidence
Finding
This instruction explicitly tells the agent to directly generate billable output whenever `autoConfirm: true` is returned, bypassing any current-session confirmation step. In an agent setting, that creates a real risk of financial harm because remote service policy is being treated as sufficient authorization for local execution.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**确认与扣点**
- 报价返回 `autoConfirm: true` 时直接生成,不要再问「要不要」。生成后一句话交代:本次扣了多少、
  还剩几次免确认(或「免费版小额不问」)。策略由服务端决定:免费版小额不问;付费版前几次不问,之后先问。
- 用户说「以后别问了 / 50 以内直接做」→ 运行 `autoconfirm 50`;说「以后每次先问我」→ `autoconfirm off`;
  说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
- 报价需要确认时,只说两个数:这次多少积点、余额多少,然后等用户一个「好」。采集是**固定单价**:直接说「15 积点/页 × 3 页 = 45 积点」,不要说成「预计 / 最多」——价格不会浮动;商品评论不够这么多页时只收实际采到的页数,差额自动退回(`pricingNote` 已写好这句)。不要罗列参数。
Confidence
95% confidence
Finding
Allowing the agent to change persistent `autoconfirm` settings based on casual natural-language phrases delegates ongoing spending authority to the model. A misunderstood instruction or prompt injection in conversation could silently broaden future autonomous spending and affect later sessions.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
These lines state that report language should follow the user, but also specify that the CLI default is `zh` and non-Chinese replies require explicitly passing `--language en` or similar. This creates a language-policy risk because the skill is configured to force a specific locale by default rather than requiring explicit user opt-in for Chinese.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The default prompt automatically invokes the skill in a broad, one-click manner without any trigger constraints, user confirmation, or scope checks. In a skill that can access an external ARI API and perform review collection/analysis, this increases the chance of unintended invocation, unnecessary third-party data access, or misuse in contexts where the user did not explicitly request this capability.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The entire reference file is written in Chinese and does not indicate that another language version is available or that the user may choose their preferred language. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `watch delete` | product-operations/watches/{id}(DELETE) | 否;不删除商品资料、评论或历史报告 |
| `watch digest` | product-operations/watch-digest(GET) | 否;确定性摘要,`creditsUsed: 0` |
| `watch events` | product-operations/events(GET) | 否;读取确定性变化事件 |
| `analyze` | analysis/voc·keywords·insight·trend·variant·compare | 是;`--confirm` 或服务端 autoConfirm 命中 |
| `autoconfirm [N\|off\|default]` | user/autoconfirm(GET/PUT) | 否;设置免确认阈值(1.4.5) |
| `deepdive` | products + charts + reviews + reports + VOC quote/analysis | 默认否;`--confirm` 才分析 |
| `reports` / `report` | reports | 否 |
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `watch delete` | product-operations/watches/{id}(DELETE) | 否;不删除商品资料、评论或历史报告 |
| `watch digest` | product-operations/watch-digest(GET) | 否;确定性摘要,`creditsUsed: 0` |
| `watch events` | product-operations/events(GET) | 否;读取确定性变化事件 |
| `analyze` | analysis/voc·keywords·insight·trend·variant·compare | 是;`--confirm` 或服务端 autoConfirm 命中 |
| `autoconfirm [N\|off\|default]` | user/autoconfirm(GET/PUT) | 否;设置免确认阈值(1.4.5) |
| `deepdive` | products + charts + reviews + reports + VOC quote/analysis | 默认否;`--confirm` 才分析 |
| `reports` / `report` | reports | 否 |
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `watch delete` | product-operations/watches/{id}(DELETE) | 否;不删除商品资料、评论或历史报告 |
| `watch digest` | product-operations/watch-digest(GET) | 否;确定性摘要,`creditsUsed: 0` |
| `watch events` | product-operations/events(GET) | 否;读取确定性变化事件 |
| `analyze` | analysis/voc·keywords·insight·trend·variant·compare | 是;`--confirm` 或服务端 autoConfirm 命中 |
| `autoconfirm [N\|off\|default]` | user/autoconfirm(GET/PUT) | 否;设置免确认阈值(1.4.5) |
| `deepdive` | products + charts + reviews + reports + VOC quote/analysis | 默认否;`--confirm` 才分析 |
| `reports` / `report` | reports | 否 |
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `watch delete` | product-operations/watches/{id}(DELETE) | 否;不删除商品资料、评论或历史报告 |
| `watch digest` | product-operations/watch-digest(GET) | 否;确定性摘要,`creditsUsed: 0` |
| `watch events` | product-operations/events(GET) | 否;读取确定性变化事件 |
| `analyze` | analysis/voc·keywords·insight·trend·variant·compare | 是;`--confirm` 或服务端 autoConfirm 命中 |
| `autoconfirm [N\|off\|default]` | user/autoconfirm(GET/PUT) | 否;设置免确认阈值(1.4.5) |
| `deepdive` | products + charts + reviews + reports + VOC quote/analysis | 默认否;`--confirm` 才分析 |
| `reports` / `report` | reports | 否 |
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Static analysis

No suspicious patterns detected.