Back to skill

Security audit

亚马逊选品调研 · 评论验证需求

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Amazon review research tool, but it can spend account credits automatically under server-side auto-confirm rules and can change ongoing monitoring or confirmation settings.

Install only if you are comfortable letting this skill use an ARI API key, read and export your ARI/Amazon review data, create reports, and manage monitoring settings. Before using it, consider saying '以后每次扣点前先问我' or '只报价,不执行' when you want strict spending control, and do not set ARI_BASE_URL/ARI_ALLOW_CUSTOM_BASE unless you control the endpoint and understand where your API key will be sent.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ari.py:54
Finding
API Key Disclosure Through Unrestricted Custom API Endpoints and Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ari.py:54-71`, with credential transmission sinks at `scripts/ari.py:300-320`, `scripts/ari.py:337-350`, and `scripts/ari.py:1444-1460` **Vulnerability Type**: Arbitrary credential destination and plaintext sensitive-data transmission **Risk Level**: Medium ### Vulnerable Code ```python def base_url(): """API 基址。ARI_BASE_URL 覆盖必须同时显式设置 ARI_ALLOW_CUSTOM_BASE=1 才生效: 所有请求(含带 Bearer Key 的)都发往这里,若单凭一个环境变量就能改指向, 会话里被注入的一条 shell 命令就足以把 Key 重定向到第三方主机。双变量门槛 让「指向哪」与「我确认这是自己的环境」成为两个独立动作。 """ override = (os.environ.get("ARI_BASE_URL") or "").strip().rstrip("/") if not override or override == PROD_BASE: return PROD_BASE if (os.environ.get("ARI_ALLOW_CUSTOM_BASE") or "").strip() != "1": emit(error_obj( "ARI_CUSTOM_BASE_BLOCKED", 0, "ARI_BASE_URL 指向非官方地址:%s,已拒绝发送请求" % override, "若这是你自己的开发/自建环境,请同时设置 ARI_ALLOW_CUSTOM_BASE=1 后重试;" "若你并未主动设置过 ARI_BASE_URL,请勿继续,先清除该环境变量。")) raise SystemExit(2) return override ``` The returned custom URL is subsequently used with the API key: ```python def request_json(method, path, payload=None, params=None): query = { "method": method, "path": path, "params": {k: v for k, v in (params or {}).items() if v not in (None, "")}, "payload": payload, } url = base_url() + path if query["params"]: url += "?" + urllib.parse.urlencode(query["params"], doseq=True) data = None if payload is None else json.dumps(payload).encode("utf-8") headers = { "Authorization": "Bearer " + require_key(), "Accept": "application/json", "User-Agent": user_agent(), } if data is not None: headers["Content-Type"] = "application/json" try: req = urllib.request.Request(url, data=data, headers=headers, method=method) with urllib.request.urlopen(req, timeout=TIMEOUT_SEC) as resp: ``` The ...[truncated 4238 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Require HTTPS for authenticated remote endpoints** - Parse the configured URL with `urllib.parse.urlparse`. - Reject custom endpoints whose scheme is not `https`. - Reject malformed URLs and URLs containing embedded user information. 2. **Provide a narrowly scoped local-development exception** - If plaintext HTTP is genuinely necessary, permit it only for loopback destinations such as `127.0.0.1`, `::1`, or `localhost`. - Protect that behavior behind a separate, explicitly named development flag such as `ARI_ALLOW_INSECURE_LOCAL_HTTP=1`. - Do not permit plaintext HTTP for private-network or arbitrary remote hosts. 3. **Separate production and development credentials** - Refuse to send `ari_live_*` credentials to custom endpoints. - Require a distinct development-key prefix or a separate credential variable for non-production servers. - Display a clear warning identifying the destination before using a custom endpoint. 4. **Consider destination allowlisting** - Use the official ARI hostname by default. - If self-hosted deployments are supported, allow users to configure trusted hosts explicitly rather than accepting any URL. 5. **Preserve TLS verification** - Continue using the standard verified TLS context. - Do not introduce certificate-verification bypasses for custom endpoints. 6. **Add security regression tests** - Verify rejection of `http://example.com`. - Verify rejection of malformed and credential-bearing URLs. - Verify acceptance of the official HTTPS endpoint. - If required, verify that an explicitly enabled loopback-only HTTP endpoint is accepted while other HTTP hosts remain blocked. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (23)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill invokes shell commands, uses networked APIs, writes local files, and accesses environment-based credentials, yet does not declare permissions. That under-disclosure prevents proper sandboxing and informed consent, and is especially risky here because the instructions include key setup/storage, exports, and paid remote operations.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The published description frames the skill as narrow product-research/reporting, but the instructions authorize much broader behavior: authentication flows, billing/credit management, autoconfirm changes, recurring schedules, watch lifecycle management, exports, alerts, and operational workflows. This mismatch can cause users or hosting platforms to grant trust appropriate for a read-only research tool while the skill actually performs account-affecting and chargeable actions.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The skill exposes broader 'product-operations' capabilities beyond the declared product-research/review-analysis scope. Scope expansion increases the attack surface and can cause agents or users to invoke sensitive workflows they did not expect, especially when those workflows can trigger paid analysis runs or operational actions.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
Watch/alert/workbench/advise features enable ongoing monitoring and complaint-handling workflows that are not described in the manifest. Hidden or under-declared functionality is dangerous because agents may trigger collection, monitoring, or AI-generated handling actions outside the user’s informed expectations.

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
95% confidence
Finding
The workflow explicitly permits a paid VOC generation to proceed automatically when the backend marks it `autoConfirmed: true`, with the user only informed after charges and report creation. In a skill that can trigger billing and data collection, executing first and asking later undermines meaningful consent and can lead to unauthorized spending.

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
93% confidence
Finding
The documented flow normalizes automatic completion of collection and report generation after a minimal confirmation path, while mixing data collection, waiting, archiving, and billing into one command. This increases the chance that users approve a seemingly simple action without understanding that multiple consequential operations and charges will occur.

Autonomous Decision Making

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

**确认与扣点**
- 报价返回 `autoConfirm: true` 时直接生成,不要再问「要不要」。生成后一句话交代:本次扣了多少、
  还剩几次免确认(或「免费版小额不问」)。策略由服务端决定:免费版小额不问;付费版前几次不问,之后先问。
- 用户说「以后别问了 / 50 以内直接做」→ 运行 `autoconfirm 50`;说「以后每次先问我」→ `autoconfirm off`;
  说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
Confidence
96% confidence
Finding
The skill directs the agent to proceed immediately on `autoConfirm: true` and only explain charges afterward. In context, this is more dangerous because the skill can invoke paid API operations and persist reports, so post-hoc notice does not provide valid authorization for spending or state changes.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**确认与扣点**
- 报价返回 `autoConfirm: true` 时直接生成,不要再问「要不要」。生成后一句话交代:本次扣了多少、
  还剩几次免确认(或「免费版小额不问」)。策略由服务端决定:免费版小额不问;付费版前几次不问,之后先问。
- 用户说「以后别问了 / 50 以内直接做」→ 运行 `autoconfirm 50`;说「以后每次先问我」→ `autoconfirm off`;
  说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
- 报价需要确认时,只说两个数:这次多少积点、余额多少,然后等用户一个「好」。采集是**固定单价**:直接说「15 积点/页 × 3 页 = 45 积点」,不要说成「预计 / 最多」——价格不会浮动;商品评论不够这么多页时只收实际采到的页数,差额自动退回(`pricingNote` 已写好这句)。不要罗列参数。
Confidence
94% confidence
Finding
The same instruction set at this line also encourages reducing confirmation friction for future paid actions, which weakens spending controls. If a user is misunderstood, socially engineered, or the conversation is ambiguous, the agent could permanently broaden what it may charge without fresh approval.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**确认与扣点**
- 报价返回 `autoConfirm: true` 时直接生成,不要再问「要不要」。生成后一句话交代:本次扣了多少、
  还剩几次免确认(或「免费版小额不问」)。策略由服务端决定:免费版小额不问;付费版前几次不问,之后先问。
- 用户说「以后别问了 / 50 以内直接做」→ 运行 `autoconfirm 50`;说「以后每次先问我」→ `autoconfirm off`;
  说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
- 报价需要确认时,只说两个数:这次多少积点、余额多少,然后等用户一个「好」。采集是**固定单价**:直接说「15 积点/页 × 3 页 = 45 积点」,不要说成「预计 / 最多」——价格不会浮动;商品评论不够这么多页时只收实际采到的页数,差额自动退回(`pricingNote` 已写好这句)。不要罗列参数。
Confidence
94% confidence
Finding
The same instruction set at this line also encourages reducing confirmation friction for future paid actions, which weakens spending controls. If a user is misunderstood, socially engineered, or the conversation is ambiguous, the agent could permanently broaden what it may charge without fresh approval.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
说「恢复默认」→ `autoconfirm default`。这是唯一需要你代用户设置的东西,设完复述一句当前规则。
- 报价需要确认时,只说两个数:这次多少积点、余额多少,然后等用户一个「好」。采集是**固定单价**:直接说「15 积点/页 × 3 页 = 45 积点」,不要说成「预计 / 最多」——价格不会浮动;商品评论不够这么多页时只收实际采到的页数,差额自动退回(`pricingNote` 已写好这句)。不要罗列参数。

**新手(`check` 返回 `autoConfirm.mode` 为 `first_runs` / `free_small`,或问"然后呢")**
- 报告讲完只推一个下一步,附接口返回的成本,不写死月费用。用户同意再 `schedule --set weekly`。
- 不解释命令名,不列功能清单。用户问「还能做什么」时按他的产品状态给一条建议,不超过三句。
Confidence
88% confidence
Finding
After completing a report, the skill tells the agent to push a next-step recommendation with returned cost and then, upon a simple user agreement, enable recurring weekly scheduling. Because this establishes an ongoing monitored/paid workflow rather than a one-off action, the conversational upsell pattern increases the risk of users enabling recurring charges without fully understanding persistence and cost.

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
84% confidence
Finding
The reference explicitly allows paid analysis commands to execute when server-side autoConfirm rules are met, meaning a user request could trigger billable actions without an explicit per-action confirmation. In an agent setting, this weakens human approval boundaries and can lead to unintended spending or irreversible paid operations if the agent treats eligibility as sufficient authorization.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `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 | 否 |
| `alerts` | alerts(`--mark-read` 时 alerts/read) | 否 |
Confidence
91% confidence
Finding
This duplicate finding points to the same persistent auto-confirmation control, which reduces safeguards for future billable operations. Even if intended as convenience, exposing account-level approval relaxation to an autonomous agent creates a meaningful risk of unauthorized or unexpected charges.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| `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 | 否 |
| `alerts` | alerts(`--mark-read` 时 alerts/read) | 否 |
Confidence
91% confidence
Finding
This duplicate finding points to the same persistent auto-confirmation control, which reduces safeguards for future billable operations. Even if intended as convenience, exposing account-level approval relaxation to an autonomous agent creates a meaningful risk of unauthorized or unexpected charges.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
voc B0... --site amz_us 是完整 VOC 的入口:先取得报价,已有足够评论时使用当前分析价格;
数据不足时合并采集与分析费用。符合服务端免确认规则且总额不超过上限时可能直接生成,
返回 autoConfirmed。否则返回 confirmationRequired,取得用户同意后追加 --confirm,
自动完成必要采集、等待、分析和归档。只读询价应使用 quote / collect 报价入口。

`collect --asin B0... --site amz_us --pages 3` 只返回报价;确认后追加
Confidence
88% confidence
Finding
The VOC flow states that collection and analysis may be automatically performed and charged when server-side no-confirmation rules match. Because the workflow can include data collection, waiting, analysis, and archiving in one step, the blast radius is larger than a simple read and may surprise users who expected quote-only behavior.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
先调用 `quote --type ...`。报价字段:
`type, basePrice, price, sampledReviews, totalReviews, balance, sufficient`,
另有(1.4.5):`autoConfirm`(true = 服务端首次体验策略允许免确认直接生成)、
`autoConfirmMaxCredits`(免确认单次上限,采集 + 报告合计)、`autoConfirmRemaining`(还剩几次)、
`autoConfirmNote`、`webUrl`(该产品的网页报告页)。`sampleCap` / `degraded` 表示 Free 样本封顶与轻量模型。
`voc` / `analyze` 在 autoConfirm 命中时会直接生成,返回 `autoConfirmed: true` 与 `autoConfirmNote`,
并附 `web.report` / `web.product` 网页链接。
Confidence
87% confidence
Finding
This duplicate finding refers to the same direct-execution-on-autoConfirm behavior. The risk is not code execution or data exfiltration, but unauthorized billable operations triggered by an agent acting on backend policy rather than user intent.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
先调用 `quote --type ...`。报价字段:
`type, basePrice, price, sampledReviews, totalReviews, balance, sufficient`,
另有(1.4.5):`autoConfirm`(true = 服务端首次体验策略允许免确认直接生成)、
`autoConfirmMaxCredits`(免确认单次上限,采集 + 报告合计)、`autoConfirmRemaining`(还剩几次)、
`autoConfirmNote`、`webUrl`(该产品的网页报告页)。`sampleCap` / `degraded` 表示 Free 样本封顶与轻量模型。
`voc` / `analyze` 在 autoConfirm 命中时会直接生成,返回 `autoConfirmed: true` 与 `autoConfirmNote`,
并附 `web.report` / `web.product` 网页链接。
Confidence
87% confidence
Finding
This duplicate finding refers to the same direct-execution-on-autoConfirm behavior. The risk is not code execution or data exfiltration, but unauthorized billable operations triggered by an agent acting on backend policy rather than user intent.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
if not ok(quote):
        return quote
    q_data = data_of(quote) or {}
    # 首次体验免确认(服务端策略 skill.autoConfirm):前几次小额直接生成,不再多问一轮。
    auto_confirmed = False
    if not confirm and q_data.get("autoConfirm") and q_data.get("sufficient"):
        confirm = True
Confidence
92% confidence
Finding
The analysis flow can automatically flip confirm=True when the server says autoConfirm is enabled and the balance is sufficient, causing a paid analysis run without an explicit per-action confirmation. In an agent setting, this weakens user-consent guarantees and can lead to unintended spending or execution of analyses the user did not clearly approve at that moment.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
return quote
    q_data = data_of(quote) or {}
    # 首次体验免确认(服务端策略 skill.autoConfirm):前几次小额直接生成,不再多问一轮。
    auto_confirmed = False
    if not confirm and q_data.get("autoConfirm") and q_data.get("sufficient"):
        confirm = True
        auto_confirmed = True
Confidence
92% confidence
Finding
This line is part of the branch that enables automatic execution of a billed analysis based on server policy instead of contemporaneous user approval. In delegated agent contexts, that can turn informational requests into chargeable actions unexpectedly.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
q_data = data_of(quote) or {}
    # 首次体验免确认(服务端策略 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:
Confidence
92% confidence
Finding
The logic combines server-provided autoConfirm and sufficient balance to bypass the normal quote-confirm cycle. This is dangerous because spending authorization is effectively delegated to prior configuration, which may not reflect the user's current intent in a conversational agent session.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
if plan is not None and plan["balance"]["note"]:
        combined_quote["siteNote"] = plan["balance"]["note"]
    combined_quote["webUrl"] = analysis_quote.get("webUrl")
    # 首次体验免确认:服务端 autoConfirm=true 且「采集 + 报告」合计不超过单次上限时,直接跑完。
    # 在聊天里多问一句「确认吗」,很多用户就不回了——先让他拿到结果。
    auto_max = int(analysis_quote.get("autoConfirmMaxCredits") or 0)
    auto_confirmed = (not args.confirm and bool(analysis_quote.get("autoConfirm"))
Confidence
93% confidence
Finding
The combined VOC workflow can auto-confirm both collection and analysis based on server-side autoConfirm and a credit threshold, causing multiple paid operations to run automatically. In a chat-agent context this increases financial and operational risk because a single request can trigger collection, analysis, and archival without explicit step-by-step approval.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
combined_quote["webUrl"] = analysis_quote.get("webUrl")
    # 首次体验免确认:服务端 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:
Confidence
93% confidence
Finding
This condition authorizes auto-execution when total credits are under a threshold, effectively substituting server policy for immediate user intent. Threshold-based spending automation is particularly risky in agent environments where prompts may be ambiguous or manipulated.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
# 首次体验免确认:服务端 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")
Confidence
92% confidence
Finding
This line finalizes the auto_confirmed state for a multi-step billed workflow. Because it can suppress the normal quote pause, it undermines consent and can lead to surprise charges.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
# 首次体验免确认:服务端 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")
Confidence
92% confidence
Finding
This line finalizes the auto_confirmed state for a multi-step billed workflow. Because it can suppress the normal quote pause, it undermines consent and can lead to surprise charges.

Static analysis

No suspicious patterns detected.