Back to skill

Security audit

FBA Send to Amazon

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Amazon FBA automation, but it needs Review because it can perform high-impact seller-account actions and includes an unguarded cancellation path plus weak API endpoint validation.

Review this before installing in a production seller account. Use a least-privilege SP-API authorization, keep the endpoint on the official Amazon SP-API host, avoid create_inbound_plan.py --void, use only the guarded void_plan.py dry run plus --yes flow for cancellations, and do not let an agent drive a signed-in Seller Central browser unless you explicitly intend that session use. Treat generated result JSON and label PDFs as sensitive business records.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/spapi.py:58
Finding

Configurable SP-API Endpoint Can Receive Amazon Access Tokens and Sensitive Payloads

Content
View full analysis
dict: return {"x-amz-access-token": access_token(), "Content-Type": "application/json"} def request(method: str, url: str, body=None, params=None, retries: int = 6): if params: url += "?" + urllib.parse.urlencode(params) data = json.dumps(body).encode() if body is not None else None last: Exception | None = None for attempt in range(retries): req = urllib.request.Request(url, data=data, headers=headers(), method=method) try: with urllib.request.urlopen(req, timeout=40) as resp: raw = resp.read() return json.loads(raw) if raw else {} ``` ### Technical Analysis The base SP-API endpoint can be supplied through either the `SPAPI_ENDPOINT` environment variable or the `endpoint` property in `~/.config/sp-api/credentials.json`. The value is not validated to ensure that: - The scheme is HTTPS. - The destination belongs to an approved Amazon SP-API domain. - User information is not present in the URL. - Redirects do not move the request to an untrusted destination. Every request constructed from this endpoint includes the `x-amz-access-token` bearer credential. State-changing workflow requests can also include seller inventory, SKUs, source addresses, telephone numbers, email addresses, carrier selections, and shipment identifiers. Reading SP-API credentials and sending a derived access token to Amazon is necessary for the declared functionality. Allowing the authenticated destination to be an arbitrary host exceeds ...[truncated 1246 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/spapi.py:125
Finding

Documented Smoke Test Logs a Portion of the Amazon Access Token

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_inbound_plan.py:308
Finding

Alternate Cancellation Interface Bypasses Shipment Fingerprint and Confirmation Safeguards

Content
View full analysis
{_req('GET', f'/inboundPlans/{plan_id}').get('status')}") def main(): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("config", nargs="?", help="plan config JSON") ap.add_argument("--resume", metavar="PLAN_ID") ap.add_argument("--void", nargs="+", metavar="PLAN_ID") ap.add_argument("--out", help="where to write the result JSON") args = ap.parse_args() if args.void: for pid in args.void: void(pid) return ``` ### Technical Analysis The project includes `void_plan.py`, whose documented safety design requires: - An explicitly supplied plan ID. - An exact set of expected FBA shipment IDs. - A dry run by default. - A separate `--yes` flag before cancellation. However, `create_inbound_plan.py` exposes an alternate `--void` option that immediately cancels every supplied plan ID. It performs no shipment-fingerprint comparison, has no dry-run default, and requires no explicit confirmation flag. This creates a direct bypass of the project's intended protection against cancelling a similar-looking or incorrectly selected production plan. ### Attack Path 1. A user, automation system, or agent selects an incorrect, stale, or mistyped plan ID. 2. It invokes: ```bash python3 scripts/create_inbound_plan.py --void ``` 3. The script immediately sends: ```http PUT /inboundPlans//cancellation ``` 4. Amazon processes the cancellation without the local script checking the plan's expected shipment set. ...[truncated 669 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:93
Finding

Third-Party PDF and Numerical Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_labels.py:184
Finding

Response-Controlled Label URL Is Downloaded and Parsed Without Destination or Size Validation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill includes destructive plan-cancellation and shipment-lookup behavior that is not clearly disclosed in the top-level purpose statement. Hidden or under-declared destructive functionality is dangerous because an agent may be authorized for routine shipping tasks while unexpectedly being able to cancel active inbound plans and alter business operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill includes destructive plan-cancellation and shipment-lookup behavior that is not clearly disclosed in the top-level purpose statement. Hidden or under-declared destructive functionality is dangerous because an agent may be authorized for routine shipping tasks while unexpectedly being able to cancel active inbound plans and alter business operations.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: fba-send-to-amazon
description: Create FBA inbound plans (Send to Amazon) via SP-API v2024-03-20 — identical-box packing for an even multi-warehouse split and $0 placement fee, carrier booking (Amazon SEND, partnered or your own), box-label download and square-sticker formatting. Use when asked to send inventory to FBA, create an inbound plan/shipment, book a freight carrier for an inbound, or print box labels. Triggers, send to amazon, STA, inbound plan, FBA shipment, box label, placement fee, Amazon SEND, partnered carrier, FBA发货, 创建入库计划, 箱唛.
version: 1.0.0
metadata:
  openclaw:
    emoji

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 12)May include surrounding context.

md
bins:
        - python3
      config:
        - ~/.config/sp-api/credentials.json
    envVars:
      - name: LWA_CLIENT_ID
        required: false

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 89)May include surrounding context.

md
bins:
        - python3
      config:
        - ~/.config/sp-api/credentials.json
    envVars:
      - name: LWA_CLIENT_ID
        required: false

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/spapi.py (reported line 14)May include surrounding context.

python
bins:
        - python3
      config:
        - ~/.config/sp-api/credentials.json
    envVars:
      - name: LWA_CLIENT_ID
        required: false

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/spapi.py (reported line 31)May include surrounding context.

python
bins:
        - python3
      config:
        - ~/.config/sp-api/credentials.json
    envVars:
      - name: LWA_CLIENT_ID
        required: false

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/spapi.py (reported line 65)May include surrounding context.

python
def access_token() -> str:
    """Return a cached LWA access token, refreshing ~1 min before expiry."""
    global _token
    if _token and time.time() < _token[1]:
        return _token[0]

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares access to Python, local config files, environment variables, and networked SP-API interactions, but does not constrain those capabilities with explicit tool permissions or allowed-tool scope. In an agent environment, that gap increases the chance of overbroad execution, unintended file/env access, and network actions beyond the user’s expectation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: fba-send-to-amazon
description: Create FBA inbound plans (Send to Amazon) via SP-API v2024-03-20 — identical-box packing for an even multi-warehouse split and $0 placement fee, carrier booking (Amazon SEND, partnered or your own), box-label download and square-sticker formatting. Use when asked to send inventory to FBA, create an inbound plan/shipment, book a freight carrier for an inbound, or print box labels. Triggers, send to amazon, STA, inbound plan, FBA shipment, box label, placement fee, Amazon SEND, partnered carrier, FBA发货, 创建入库计划, 箱唛.
version: 1.0.0
metadata:
  openclaw:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger text is broad enough to activate on many common logistics or Amazon-related requests, without clear boundaries about what the skill should and should not do. Overbroad activation increases the chance that the agent invokes a credentialed, network-capable, and partly destructive skill in situations where the user did not intend it.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation instructs the agent to operate a browser session already signed in to Seller Central, which expands the trust boundary from API calls into direct use of an authenticated user session. That creates significant risk of unintended account actions, session abuse, or access to unrelated account data, especially because browser automation often bypasses the tighter controls applied to API credentials.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advises querying an internal Seller Central endpoint using the user’s browser session credentials, which is outside the declared SP-API workflow and relies on an authenticated session to reach undocumented/internal functionality. Use of internal endpoints is risky because it can expose unstable, unsupported, or over-privileged operations and defeats expected security review based on public API boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code writes a result file containing shipment identifiers, warehouse details, box specifications, and item quantities, but there is no nearby warning or disclosure that operational data will be persisted locally. For a code-file warning check, the write is visible, but the user-facing output only says where it was saved and does not explain the sensitivity or persistence of the data.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/spapi.py (reported line 32)May include surrounding context.

python
from pathlib import Path

CONFIG_FILE = Path.home() / ".config" / "sp-api" / "credentials.json"
LWA_URL = "https://api.amazon.com/auth/o2/token"

_cfg_cache: dict | None = None
_token: tuple[str, float] | None = None   # (access_token, expires_at_epoch)