Back to skill

Security audit

Linkfox Tiktok选品与带货视频

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with TikTok product research and video publishing, but it gives broad credential-bearing API access with weak endpoint and credential-storage controls.

Install only if you trust LinkFox and the runtime environment. Do not set LINKFOX_TOOL_GATEWAY or related API URL variables to untrusted hosts, avoid sharing full API keys in chat or shell history, prefer a scoped secret store over .bashrc/.zshrc/setx, and treat video posting and payment/order commands as user-approved actions only.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_tiktok_video_common.py:15
Finding

Credential and TikTok Access-Token Exfiltration Through Unvalidated Gateway Overrides

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", }, method="POST", ) try: with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` ```python def developer_proxy_call( tts_access_token: str, path: str, method: str, region: Optional[str] = None, query_string: Optional[str] = None, body: Optional[str] = None, content_type: str = "application/json", ) -> dict: assert_path_allowed(path) proxy: dict[str, Any] = { "path": path.lstrip("/"), "method": method, "ttsAccessToken": tts_access_token, } if region: proxy["r ...[truncated 4561 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/onboarding.md:8
Finding

API Keys and Authentication Material Are Exposed Through Command Arguments, Standard Output, Shell History, and Plaintext Startup Files

Content
View full analysis
` - After receiving the code: `python scripts/onboarding.py login ` - After obtaining `api_key`, forward the following platform configuration to the user: - Windows PowerShell: `setx LINKFOX_AGENT_API_KEY ""` - macOS zsh: `echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.zshrc && source ~/.zshrc` - Linux bash: `echo 'export LINKFOX_AGENT_API_KEY=""' >> ~/.bashrc && source ~/.bashrc` ``` The login function returns the complete API key: ```python def login_and_get_key(phone: str, code: str, channel: str) -> dict: ... 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), } ``` The command handler then emits the complete object to standard output: ```python 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} Successfully obtained API key", file=s ...[truncated 2705 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:160
Finding

Unpinned Third-Party Packages and Unverified Remote Skill Archives Create a Supply-Chain Execution Risk

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} ``` ```python def _require_requests() -> None: if requests is None: raise RuntimeError("Missing requests dependency; run: pip install requests") ``` `response_io.py` similarly recommends: ```python f"Install with: pip install jmespath" ``` Multiple reference files also direct the user to download and install a mutable archive without a checksum or signature. For example: ```markdown - Download https://agent-files.linkfox.com/skills/linkfox-onboarding/release.zip, extract it, and install this skill. ``` ### Technical Analysis The package names shown are established packages and there is no evidence in the audited repository that they are intentionally malicious. The weakness is the absence of deterministic version and integrity controls. Commands such as: ```bash pip install requests pip install qrcode pillow pip install jmespath ``` resolve whatever versions the package index serves at installation time. The audited Skill therefore does not define the code that will ultimately execute in the user environment. A compromised package index, compromised maintainer account, malicious future release, dependency-resolution manipulation, or alternate con ...[truncated 1990 chars]
Remediation
View remediation
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (111)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request URL is derived from the LINKFOX_TOOL_GATEWAY environment variable, so anyone who can influence the runtime environment can redirect this script to an attacker-controlled host. Because the script also sends the Authorization API key in the outbound request, this creates a realistic secret-exfiltration/SSRF-style risk rather than a purely theoretical issue.

Content

Scanner excerpt · scripts/authorize_url.py (reported line 54)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 41, 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_accounts.py (reported line 53)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 72, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The request sent via urlopen includes multiple environment-derived values in headers, and the destination base URL is also environment-controlled through LINKFOX_TOOL_GATEWAY. In an agent/runtime context, environment variables are often influenced by the host orchestration layer, so this creates a clear exfiltration path for session metadata and the API key to an attacker-controlled endpoint if the gateway variable is overridden.

Content

Scanner excerpt · scripts/echotik_list_product.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request sent via urlopen includes headers populated from environment variables, and the destination host is also overrideable through LINKFOX_TOOL_GATEWAY. In an agent/runtime context, untrusted or attacker-influenced environment variables can therefore redirect requests and exfiltrate sensitive values such as the API key and session metadata to an arbitrary server, which is a real SSRF/credential-leak risk.

Content

Scanner excerpt · scripts/echotik_list_product_video.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request sent to urlopen includes a destination derived from LINKFOX_TOOL_GATEWAY and forwards several environment-derived headers such as SESSION_ID, MODE_ID, APP_NAME, and the API key. Because the gateway base URL is fully overrideable by environment variable, an attacker who can influence the execution environment can redirect authenticated requests and attached metadata to an arbitrary host, causing credential and session-data exfiltration.

Content

Scanner excerpt · scripts/fastmoss_product_rank_top_selling.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, 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/echotik_batch_product_detail.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, 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/echotik_get_video_download_url.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, 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/echotik_list_new_product_rank.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, 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/fastmoss_product_search.py (reported line 79)May include surrounding context.

python
method="POST",
    )
    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 72, 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/video_proxy.py (reported line 83)May include surrounding context.

python
method="POST",
    )
    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: 'url' from os.environ.get (line 235, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The code sends authentication material and other sensitive workflow data to URLs derived from environment-controlled base endpoints via requests.post. If an attacker can influence LINKFOX_LOGIN_API_URL or LINKFOX_AGENT_USER_API_URL, they can redirect login tokens, refresh tokens, phone-based auth flows, and generated API keys to an attacker-controlled server, enabling credential exfiltration and account compromise.

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
97% confidence
Finding

The gateway request uses urllib to contact a base URL sourced from environment variables and attaches the API key in the Authorization header. If LINKFOX_AGENT_API_URL or its fallback is modified, the CLI can be tricked into sending API credentials and order-related operations to attacker infrastructure or internal network targets, creating both credential leakage and SSRF-style risks.

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

Tainted flow: 'req' from os.environ.get (line 42, 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/account_tokens.py (reported line 54)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 42, 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/refresh_token.py (reported line 54)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
94% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The described implementation appears to act as a generic proxy over creator/video APIs rather than a narrowly scoped business workflow. Generic proxy layers are risky because they often become a capability-escalation surface, enabling access to more upstream operations than the user or reviewer expects.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.