Back to skill

Security audit

亚马逊-店铺A+页面

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs Amazon A+ content operations, but it also handles account login, API keys, payments, and broad response logging in ways users should review carefully before installing.

Install only if you expect to use LinkFox for Amazon A+ operations and are comfortable with the skill handling live storefront changes, LinkFox credentials, phone/SMS login, and payment/order flows. Avoid using custom endpoint environment variables, do not paste API keys into shared logs or chats, review saved response files for sensitive seller data, and confirm every create/update/ASIN replacement/approval/suspension or payment action before it runs.

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_aplus_common.py:25
Finding

Environment-controlled endpoints can receive authentication credentials

Content
View full analysis
dict: api_key = get_api_key() data = json.dumps(params).encode("utf-8") req = Request( endpoint, data=data, headers={ "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/1.0", "SESSION_ID": os.environ.get("SESSION_ID", ""), "MESSAGE_ID": os.environ.get("MESSAGE_ID", ""), "MODE_ID": os.environ.get("MODE_ID", ""), "APP_NAME": os.environ.get("APP_NAME", ""), }, method="POST", ) try: with urlopen(req, timeout=timeout) as response: return json.loads(response.read().decode("utf-8")) ``` ```python # scripts/onboarding.py:68-85 def _env_base(name: str, default: str, *fallbacks: str) -> str: for n in (name, *fallbacks): v = os.environ.get(n) if v: return v.rstrip("/") return default.rstrip("/") def _agent_base() -> str: return _env_base("LINKFOX_AGENT_API_URL", "https://tool-gateway.linkfox.com", "LINKFOX_TOOL_GATEWAY") def _login_base() -> str: return _env_base("LINKFOX_LOGIN_API_URL", "https://api.linkfox.com") def _agent_user_base() -> str: return _env_base("LINKFOX_AGEN ...[truncated 3443 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_spapi_aplus_common.py:227
Finding

Unsanitized SESSION_ID permits output-path traversal

Content
View full analysis
str: env = os.environ.get("SESSION_ID") if env: return env.strip() if "_auto" not in _LF_SESSION_CACHE: _LF_SESSION_CACHE["_auto"] = ( _lf_time.strftime("%H%M%S", _lf_time.localtime(ts)) + "-" + _lf_secrets.token_hex(3) ) ``` ```python # scripts/_spapi_aplus_common.py:325-340 def emit_result(result, slug=SLUG, inline=False): """Persist the complete response and print either it or a summary.""" serialized = json.dumps(result, ensure_ascii=False, indent=2) ts = _lf_time.time() date_str = _lf_time.strftime("%Y-%m-%d", _lf_time.localtime(ts)) sid = _lf_session_id(ts) root = _lf_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir, exist_ok=True) _lf_ensure_meta(root, session_dir, date_str, sid, ts) data_dir = os.path.join(session_dir, "data") os.makedirs(data_dir, exist_ok=True) out = os.path.join(data_dir, f"{slug}-{int(ts * 1_000_000)}.json") try: with open(out, "w", encoding="utf-8") as f: f.write(serialized) ``` ```python # scripts/onboarding.py:153-159 def session_dir() -> str: ts = time.time() sid = (os.environ.get("SESSION_ID") or "").strip() or ( time.strftime("%H%M%S", time.localtime(ts)) + "-" + secrets.token_hex(3)) path = os.path.join(_linkfox_root(), time.strftime("%Y-%m-%d", time.localtime(ts)), sid) os.makedirs(path, exist_ok=True) return path ``` ### Technical Analysis `SESSION_ID` is accepted directly from the process environment and used as the final component of a filesystem path. The code does not reject path separators, `.. ...[truncated 2132 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_spapi_aplus_common.py:193
Finding

Sensitive API responses may be stored in a shared temporary directory with weak permission controls

Content
View full analysis
str: cached = _LF_SESSION_CACHE.get("_root") if cached: return cached candidates = [] acpx = (os.environ.get("ACPX_WORKSPACES") or "").strip() if acpx: acpx = acpx.split(os.pathsep)[0].strip() if acpx: candidates.append(os.path.join(acpx, "linkfox")) candidates.append(os.path.join(os.getcwd(), "linkfox")) candidates.append(os.path.join(os.path.expanduser("~"), "linkfox")) candidates.append(os.path.join(_lf_tempfile.gettempdir(), "linkfox")) for root in candidates: try: os.makedirs(root, exist_ok=True) probe = os.path.join(root, ".write_probe") with open(probe, "w", encoding="utf-8") as f: f.write("") os.remove(probe) except OSError: continue root = os.path.abspath(root) _LF_SESSION_CACHE["_root"] = root return root ``` ```python # scripts/_spapi_aplus_common.py:325-346 def emit_result(result, slug=SLUG, inline=False): """Persist the complete response and print either it or a summary.""" serialized = json.dumps(result, ensure_ascii=False, indent=2) ts = _lf_time.time() date_str = _lf_time.strftime("%Y-%m-%d", _lf_time.localtime(ts)) sid = _lf_session_id(ts) root = _lf_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir, exist_ok=True) _lf_ensure_meta(root, session_dir, date_str, sid, ts) data_dir = os.path.join(session_dir, "data") os.makedirs(data_dir, exist_ok=True) out = os.path.join(data_dir, f"{slug}-{int(ts * 1_000_000)}.json") try: with ...[truncated 2517 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:468
Finding

Generated API keys are disclosed through standard output

Content
View full analysis
dict: masked = _mask_phone(phone) if not re.fullmatch(r"\d{11}", phone): return {"error": f"login: invalid phone format: {phone}", "phone": masked} if not re.fullmatch(r"\d{4,8}", code): return {"error": f"login: invalid verification-code format: {code}", "phone": masked} lg = _login_v3(phone, code, channel) if "error" in lg: return {"error": lg["error"], "phone": masked} if lg.get("is_new_user"): lbt = _login_by_token(lg["access_token"], lg["refresh_token"]) if "error" in lbt: print(f"{TAG} {lbt['error']}", file=sys.stderr) info = _fetch_user_info_v3(lg["access_token"], lg["user_id"]) if "error" in info: return {"error": info["error"], "phone": masked} tok = _get_or_generate_api_token(lg["access_token"], lg["user_id"], info["group_id"]) if "error" in tok: return {"error": tok["error"], "phone": masked} return { "api_key": tok["api_key"], "phone": masked, "group_id": info["group_id"], "member_id": info["member_id"], "source": tok["source"], "nick_name": lg.get("nick_name", ""), "team_name": info.get("team_name", ""), "is_new_user": lg.get("is_new_user", False), } ``` ```python # scripts/onboarding.py:500, 512-518 def _emit(obj: dict) -> None: print(json.dumps(obj, ensure_ascii=False, indent=2)) def _cmd_login(args) -> int: r = login_and_get_key(args.phone.strip(), args.code.strip(), args.channel) _emit(r) if "api_key" in r: print(f"{TAG} API key obtained successfully (source: {r['source']})", file=sys.stde ...[truncated 1789 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:162
Finding

Onboarding recommends installation of unpinned third-party packages

Content
View full analysis
dict: try: import qrcode except ImportError: err = "Missing qrcode dependency; run: pip install qrcode pillow" print(f"{TAG} render_qr: {err}", file=sys.stderr) return {"png_path": None, "ascii_qr": None, "error": err} os.makedirs(out_dir, exist_ok=True) png_path = os.path.join(out_dir, f"qr-{int(time.time() * 1_000_000)}.png") qr = qrcode.QRCode(border=1) qr.add_data(content) qr.make(fit=True) qr.make_image(fill_color="black", back_color="white").save(png_path) buf = io.StringIO() qr.print_ascii(out=buf, invert=True) return {"png_path": png_path, "ascii_qr": buf.getvalue()} def _require_requests() -> None: if requests is None: raise RuntimeError("Missing requests dependency; run: pip install requests") ``` ### Technical Analysis The onboarding script tells users to install `qrcode`, `pillow`, and `requests` without specifying reviewed versions, hashes, an approved package index, or an isolated environment. A bare `pip install` resolves the newest package version available from the configured index at installation time. The effective dependency code can therefore change after the Skill itself has been audited. Compromised package releases, a malicious configured index, dependency confusion, or incompatible future versions could introduce arbitrary code into the environment. The script does not automatically execute `pip`, so exploitation requires a user or agent to follow the displayed instruction. This lowers immediacy but does not remove the supply-chain risk. ### Attack Path 1. The user invokes functionality requiring a missing package. 2. The script prints a bare `pip install` command. ...[truncated 934 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (43)

Tainted flow: 'req' from os.environ.get (line 79, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The code builds outbound requests using API_BASE_URL derived from environment variables and sends sensitive headers including the API key and session metadata to that destination. If an attacker can influence LINKFOX_TOOL_GATEWAY, STORE_API_BASE_URL, or SPAPI_BASE_URL, they can redirect requests and exfiltrate credentials or business data to an attacker-controlled server.

Content

Scanner excerpt · scripts/_spapi_aplus_common.py (reported line 94)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=timeout) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

Tainted flow: 'url' from os.environ.get (line 235, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The code constructs outbound request destinations from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, API tokens, and user/team identifiers to those endpoints. If an attacker can influence the environment, they can redirect these requests to an attacker-controlled server and exfiltrate credentials or session material; in this skill, that risk is amplified because the file is explicitly an onboarding/login flow handling secrets.

Content

Scanner excerpt · scripts/onboarding.py (reported line 196)May include surrounding context.

python
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""

Tainted flow: 'req' from os.environ.get (line 244, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The gateway request path uses an environment-derived base URL and attaches the Authorization header from LINKFOX_AGENT_API_KEY before calling urlopen. If the base URL is overridden, the agent API key and related account/order data can be sent to an attacker-controlled endpoint, creating direct credential leakage and unauthorized account/billing actions.

Content

Scanner excerpt · scripts/onboarding.py (reported line 246)May include surrounding context.

python
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is Amazon A+ management, but the skill also references onboarding flows involving SMS login, API key generation, user/team info, plan purchase, payment order creation, QR code generation, and payment-status checks. That is a significant scope expansion into authentication and billing, which can expose users to credential and payment-related actions they did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is Amazon A+ management, but the skill also references onboarding flows involving SMS login, API key generation, user/team info, plan purchase, payment order creation, QR code generation, and payment-status checks. That is a significant scope expansion into authentication and billing, which can expose users to credential and payment-related actions they did not request.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

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

md
---

## Display Rules

1. 先展示网关 **`errcode` / `httpStatus`**;成功后再解析 **`developerProxy.body`** 或各脚本附带的 **`*Response`** 字段。
2. 说明 **`contentReferenceKey`** 与前台「A+ ID」不一定一致。

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file instructs the agent to handle unrelated authentication, registration, and billing workflows for a third-party Linkfox service even though the declared skill is Amazon A+ Content management. This unnecessary expansion of scope can lead the agent to collect phone numbers, guide account provisioning, and facilitate payments outside the user’s expected task boundary, creating phishing, abuse, and trust-boundary risks.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill explicitly supports phone-based registration, SMS code handling, plan selection, and payment ordering despite those capabilities being unjustified by the stated Amazon A+ Content purpose. In context, this is especially dangerous because it normalizes collecting sensitive user data and initiating financial workflows under a misleading skill identity, increasing the chance of credential theft, social engineering, or unauthorized purchases.

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/onboarding.md (reported line 14)May include surrounding context.

md
示 JSON 里的 phone/agreements
   - 收到验证码后:`python scripts/onboarding.py login <phone> <code>`
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements LinkFox account onboarding, SMS login, API key retrieval, plan listing, ordering, payment QR generation, and order queries, which are unrelated to the declared Amazon A+ Content management purpose. Such a scope mismatch is dangerous because it can trick users or host systems into invoking credential collection and billing workflows under the guise of a benign Amazon content-management skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The billing and payment logic creates orders, fetches purchasable plans, and renders payment QR codes even though the skill is supposed to manage Amazon A+ content. In context, this is especially risky because an unrelated skill should not have monetization or purchase execution features at all; that creates opportunity for unauthorized charges, social engineering, or abuse of agent trust.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill collects phone numbers and SMS verification codes, performs login, exchanges tokens, and provisions API keys, none of which are necessary for Amazon A+ Content management. In this context, the mismatch is highly dangerous because it enables credential harvesting and secret issuance under false pretenses, and the generated API key could be used for broader account access.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill describes capabilities that imply shell, network, environment-variable access, and file writes, but it does not declare any explicit tool scope or allowed-tools boundaries. That increases the blast radius if the skill is invoked in an agent runtime, because the agent may exercise broader powers than users or reviewers expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger condition is overly broad, saying the skill should activate even when the user does not explicitly mention the A+ API as long as they want to manage branded content modules. Overbroad triggering can cause the agent to invoke a write-capable operational skill in ambiguous product-detail contexts, increasing the chance of unintended API calls or data handling.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to always persist full API responses into session-organized files in the current project directory. Those responses may contain seller identifiers, marketplace data, document content, ASIN relationships, and other business-sensitive information, creating unnecessary data retention and possible cross-task exposure within the workspace.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file instructs users to request a store token with sellerId and then send amzAccessToken through POST /spApi/developerProxy. While it explains the mechanics, it does not include a privacy or security warning that these requests handle sensitive account-linked credentials and should be protected from logging or disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The file documents createContentDocument, updateContentDocument, approval submission, suspension, and ASIN relation replacement operations that can change or suspend visible A+ content. Although some behavior is described, the markdown lacks a consolidated user warning that these actions may alter production storefront data and should be verified before execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

postContentDocumentAsinRelations states that asinSet replaces all ASIN relations and that removed ASINs will have content suspended. This is safety-relevant behavior affecting published content, and the documentation should present it as an explicit user warning rather than only as parameter semantics.

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 · references/api.md (reported line 201)May include surrounding context.


curl 示例(网关层示意)

bash
export LINKFOXAGENT_API_KEY="<your-key>"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The instructions tell users to persist API keys in shell startup files and environment settings without warning about local exposure, shell history, multi-user systems, or least-privilege handling. Persisting secrets this way can leak credentials through dotfile sync, backups, shared accounts, screenshots, or support logs, and the skill provides no safer alternative.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/_spapi_aplus_common.py (reported line 43)May include surrounding context.

python
print(f"DEPENDENCY_MISSING: {json.dumps(payload, ensure_ascii=False)}", file=sys.stderr)
        sys.exit(DEPENDENCY_EXIT_CODE)
    try:
        result = subprocess.run(
            [sys.executable, str(checker)],
            capture_output=True,
            text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code includes natural-language docstrings and stderr output entirely in Chinese, which imposes a specific language on users encountering authentication/setup errors. The file does not provide an opt-in, fallback language, or any indication that the skill is intentionally region-specific, so it violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The helper creates a reusable linkfox root, session directories, metadata, and an index.jsonl across sessions in common filesystem locations such as the current directory, home directory, or temp directory. That design expands the data footprint beyond the immediate task and can expose session history and file locations to other processes or users on the same host.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

emit_result() serializes and persistently stores full API responses to local files, even though those responses may contain seller data, content drafts, publishing records, or other sensitive operational information. This broad data retention exceeds the core need of A+ content management and increases exposure if the filesystem is accessible, backed up, or shared across users or sessions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The helper writes full API responses to disk and may do so without any in-code disclosure, consent, or warning to callers. Undisclosed persistence of potentially sensitive returned data increases privacy and compliance risk and makes accidental retention more likely.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.