Back to skill

Security audit

TikTok官方-店铺ERP授权

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its TikTok Shop ERP authorization purpose, but it handles credentials and tokens with under-scoped network and local-storage behavior that users should review before installing.

Install only if you trust LinkFox and your execution environment. Protect LINKFOX_AGENT_API_KEY/LINKFOXAGENT_API_KEY, do not set LINKFOX_TOOL_GATEWAY or TIKTOK_SHOP_API_BASE_URL unless you control the destination, and treat the generated linkfox output directory as sensitive because it can retain authorization URLs, seller identifiers, token-related responses, and error details.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_lf_output.py:143
Finding

Sensitive API responses are persisted with unsafe filesystem defaults

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 def emit_result(result, slug=SLUG, inline=False): """落盘完整响应到 linkfox///data/-.json;大响应只打印摘要。无缓存。""" 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) print(f"Saved full response: {out} ({len(serialized)} bytes)") ex ...[truncated 3123 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/authorize_url.py:19
Finding

Gateway overrides can redirect API credentials to an arbitrary network destination

Content
View full analysis
dict: """Call the authorization URL API.""" api_key = get_api_key() data = json.dumps(params).encode("utf-8") req = Request( API_ENDPOINT, data=data, headers={ "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/1.0", }, method="POST", ) try: with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` The same endpoint-selection and authorization-header pattern is used by all four network-facing entry points. ### Technical Analysis The scripts intentionally send a LinkFox API key to the configured gateway because remote authentication and token management are part of the declared Skill functionality. The default endpoint, `https://tool-gateway.linkfox.com`, is consistent with the project documentation. However, `LINKFOX_TOOL_GATEWAY` and `TIKTOK_SHOP_API_BASE_URL` are accepted without validation. The code does not enforce: - HTTPS transport. - A trusted hostname allowlist. - An expected port. - The absence of embedded URL credentials. - An explicit opt-in for non-production gateways. Consequently, a modified process environment can redirect the `Authorization` header and request payload to an attacker-controlled host. A plaint ...[truncated 1647 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request destination is derived from environment-controlled configuration via API_BASE_URL and then sent through urlopen without validating the host or scheme. If an attacker can influence environment variables in the execution context, they can redirect requests containing the Authorization API key to a malicious server, causing secret exfiltration and potentially SSRF-style outbound access.

Content

Scanner excerpt · scripts/authorize_url.py (reported line 60)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=150) 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: 'req' from os.environ.get (line 47, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/authorized_stores.py (reported line 59)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=150) 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: 'req' from os.environ.get (line 52, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The request destination is derived from environment variables via API_BASE_URL, so anyone who can influence the runtime environment can redirect this script to an attacker-controlled endpoint. That would exfiltrate the Authorization API key and the seller openId, and could also return attacker-controlled JSON that the skill treats as a valid response. In an auth/token-management skill, this is especially sensitive because it handles credentials and token refresh operations.

Content

Scanner excerpt · scripts/refresh_token.py (reported line 64)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=150) 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: 'req' from os.environ.get (line 52, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request target is derived from environment variables (LINKFOX_TOOL_GATEWAY / TIKTOK_SHOP_API_BASE_URL) and then used directly in urlopen, so anyone who can influence the runtime environment can redirect this code to an attacker-controlled endpoint. Because the request includes the Authorization API key header and sensitive token-query parameters, this becomes an SSRF/credential-exfiltration risk rather than a harmless configurability feature.

Content

Scanner excerpt · scripts/store_tokens.py (reported line 64)May include surrounding context.

python
)

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented purpose is TikTok Shop ERP authorization and token management, but the described/observed behavior includes generic response capture, local storage management, and arbitrary result persistence rather than narrowly scoped OAuth actions. This mismatch is dangerous because reviewers and downstream agents may trust the declared purpose while the implementation can store sensitive material locally and perform broader actions than expected.

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 118)May include surrounding context.

md
1. `authorized_stores` 选店 → 得到 `openId`
2. 切换到对应 `linkfox-tiktok-shop-*` 业务 skill,脚本只传 `openId`(token 由网关解析)

## Display Rules

1. 只呈现授权/店铺/令牌数据,不做业务建议。
2. 勿明文输出完整 token,仅掩码。

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises network access, local file writing, and environment interaction without declaring an explicit tool scope or permission boundary. In an agent setting, undocumented capabilities increase the chance of unintended data access or persistence, especially because the large-response workflow explicitly writes potentially auth-sensitive responses to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This documentation explicitly exposes token-query and token-refresh endpoints and includes example responses containing full accessToken and refreshToken values. Even though framed as optional/debug functionality, documenting raw token retrieval materially increases the chance that downstream agents, operators, or logs will surface bearer credentials that can be reused to access seller accounts.

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 152)May include surrounding context.


curl Examples

bash
# ERP 授权链接

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The helper serializes and writes the full API response to disk under a predictable local directory tree. In the context of a TikTok Shop ERP OAuth and token-management skill, responses can reasonably contain authorization codes, access tokens, refresh tokens, shop identifiers, or other sensitive account data, so unconditional persistence materially increases the risk of credential leakage and unintended retention.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module writes response data to disk transparently and only prints that a file was saved after the fact, without any explicit consent or warning before persistence. For an auth/token-management skill, silent local storage is especially risky because users and downstream operators may assume ephemeral handling while sensitive OAuth artifacts and shop data are being retained on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code performs an HTTP POST to a remote service using the user's openId and an Authorization header derived from environment variables. Although the module docstring describes the API purpose, the runtime path does not provide a visible disclosure or confirmation before transmitting data and credentials off-box.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The header comment says '无缓存' and the emit_result docstring repeats that claim, yet the module maintains _LF_SESSION_CACHE and reuses cached values for the root path and generated session ID. This is a direct contradiction between documentation and implemented behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The helper inspects ACPX_WORKSPACES and SESSION_ID, probes multiple filesystem locations for write access, and creates cross-session metadata such as index.jsonl. For a skill whose stated purpose is TikTok Shop ERP authorization and authorized-shop lookup, this local environment/session bookkeeping is not directly justified by the manifest.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code includes user-facing text and explanatory comments in Chinese, such as the API key error message, without any opt-in or alternative locale. Under the language/locale policy rule, forcing a specific language in user-visible output can be a natural-language policy violation unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The docstring and stderr message are written in Chinese, including the missing-API-key error shown to users. This imposes a specific language on users without opt-in or justification, which matches the language/locale policy-violation category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The docstring and stderr message use Chinese-language text for authentication guidance and error output, while the file does not offer any locale selection or explain that the skill is intentionally Chinese-only. This creates a natural-language locale policy issue because the skill imposes a specific language on users without opt-in.

Content

No source excerpt is available for this finding.