Back to skill

Security audit

Linkfox 亚马逊选品

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate Amazon research integration, but it needs review because it handles credentials, persists full responses locally, and includes fallback instructions to install a remote skill package.

Install only if you trust LinkFox and are comfortable sending product research queries, images, phone-based onboarding data, and API credentials to its services. Do not set LINKFOX_TOOL_GATEWAY or related endpoint variables to untrusted hosts. Use the skill in a private workspace, watch for saved files under linkfox directories, and do not let an agent auto-install the remote onboarding ZIP unless you separately verify and approve it.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • 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
Findings (111)

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

Critical
Category
Data Flow
Content
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 ""
Confidence
94% confidence
Finding
The request destination and headers are partly influenced by environment variables, especially LINKFOX_TOOL_GATEWAY, SESSION_ID, MODE_ID, and APP_NAME. Because the script also sends the API key in the Authorization header, an attacker who can control the execution environment can redirect requests to an arbitrary host and exfiltrate credentials and request data.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
91% confidence
Finding
The request sent via urlopen includes multiple environment-derived values in headers, and the destination base URL is also controllable through LINKFOX_TOOL_GATEWAY. In an agent/runtime context, this can exfiltrate sensitive runtime metadata and the API key to an attacker-controlled endpoint if environment variables are poisoned or the skill is run in an untrusted workspace.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
96% confidence
Finding
The request sent via urlopen includes multiple attacker-controllable environment-derived values, most importantly the gateway base URL from LINKFOX_TOOL_GATEWAY and the Authorization API key header. If an attacker can influence environment variables in the agent runtime, they can redirect requests to an arbitrary host and exfiltrate the API key and request data, creating a server-side request forgery and credential leakage path.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
93% confidence
Finding
The request URL and outbound headers are partly derived from environment variables, especially LINKFOX_TOOL_GATEWAY and session metadata, and then sent via urlopen without allowlisting or validation. In an agent/runtime context where environment values may be attacker-influenced, this can redirect authenticated traffic to an arbitrary host and leak the API key and contextual identifiers to that host.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
93% confidence
Finding
The request sent to urlopen includes headers populated from environment variables, and the destination host is also overrideable via LINKFOX_TOOL_GATEWAY. That means sensitive session/app metadata and the API key can be transmitted to an attacker-controlled endpoint if the environment is influenced, creating a real exfiltration risk rather than a purely theoretical taint flow.

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

Critical
Category
Data Flow
Content
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 = ""
Confidence
89% confidence
Finding
The POST target URL is derived from environment-controlled base URLs and then used to send sensitive login material, including phone numbers, SMS codes, access tokens, refresh tokens, and generated API tokens. In a skill/agent environment, env vars are often user- or host-configurable, so this creates an SSRF/exfiltration path where secrets can be redirected to an attacker-controlled endpoint.

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

Critical
Category
Data Flow
Content
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
Confidence
84% confidence
Finding
The gateway URL is built from environment input and used in urlopen with the Authorization header populated from LINKFOX API keys. If an attacker can influence LINKFOX_AGENT_API_URL or related fallback variables, requests containing bearer credentials can be sent to an arbitrary server, enabling credential theft and internal network access attempts.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
96% confidence
Finding
The request URL and headers are partly derived from environment variables, especially LINKFOX_TOOL_GATEWAY and multiple metadata headers, and are sent directly via urlopen without validation. In an agent/runtime setting where environment can be influenced, this enables exfiltration of the API key and session metadata to an attacker-controlled endpoint, effectively creating an SSRF-style outbound credential leak.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
95% confidence
Finding
The request sent to urlopen includes values derived from environment variables, notably the API endpoint base URL and identifying headers such as SESSION_ID, MODE_ID, and APP_NAME. Because LINKFOX_TOOL_GATEWAY is fully environment-controlled, an attacker who can influence the runtime environment can redirect requests and exfiltrate both the API key and user-supplied research parameters to an attacker-controlled server.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
92% confidence
Finding
The request sent via urlopen includes attacker-influenced environment-derived values such as LINKFOX_TOOL_GATEWAY, SESSION_ID, MODE_ID, APP_NAME, and the API key header. Because the gateway base URL is overrideable by environment variable, a compromised runtime can redirect requests and exfiltrate credentials and session metadata to an arbitrary host, making this more than a normal outbound API call.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
93% confidence
Finding
The request URL and several headers are influenced by environment variables, including LINKFOX_TOOL_GATEWAY, SESSION_ID, MODE_ID, and APP_NAME, and are sent to a remote endpoint without validation or allowlisting. In an agent/runtime context, a malicious or compromised environment can redirect requests to an attacker-controlled server and exfiltrate the API key and task metadata via the Authorization and custom headers.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
95% confidence
Finding
The request ultimately uses attacker-controllable environment data in security-sensitive network fields: the destination base URL can be overridden via LINKFOX_TOOL_GATEWAY, and headers include several environment-derived values. In an agent/runtime context, this can redirect authenticated requests to an arbitrary server and leak the API key in the Authorization header, creating a credible SSRF/credential-exfiltration path.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
95% confidence
Finding
The request URL and outbound headers are partly derived from environment variables, including LINKFOX_TOOL_GATEWAY and identifiers such as SESSION_ID, MODE_ID, and APP_NAME, and are sent directly via urlopen without validation. If an attacker can influence the environment, they can redirect requests to an arbitrary server and exfiltrate the API key and request payload, which is especially dangerous because this script is an agent skill that may run in shared or semi-trusted execution contexts.

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

Critical
Category
Data Flow
Content
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 ""
Confidence
94% confidence
Finding
The request sent via urlopen includes multiple headers populated directly from environment variables, and the destination host is also overrideable through LINKFOX_TOOL_GATEWAY. That creates a tainted flow where secrets and contextual identifiers can be exfiltrated to an attacker-controlled endpoint if the environment is manipulated, which is especially risky in an agent/runtime context where env vars often carry sensitive tokens and session metadata.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill documents access to environment variables, outbound network calls, and local file writes, but does not declare permissions in a machine-readable way. That creates a trust gap: an agent or reviewer may underestimate the skill's ability to exfiltrate secrets, make external requests, or persist data locally. In this context the risk is amplified because the skill explicitly reads API keys from the environment and writes response data to disk.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to download and install another skill from a remote ZIP if onboarding content is missing, which expands trust to unverified external content during normal error handling. This creates a supply-chain and prompt-injection risk because a missing local file can trigger retrieval and installation of arbitrary remote instructions unrelated to the immediate ABA query task.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The remote installation guidance is not necessary for an ABA data-query skill and therefore widens the attack surface without functional justification. Embedding unrelated installation behavior in a query skill makes it easier for adversarial content to pivot from data access into environment modification or loading additional unreviewed capabilities.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The skill instructs the agent to download and install another skill from a remote URL when authentication or quota issues occur. That behavior exceeds the scope of generating an Amazon opportunity report and creates a supply-chain risk, because a documentation-triggered fallback could introduce unreviewed code or capabilities into the environment.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to download and install an additional skill from an external URL when authentication or quota problems occur. That expands the tool's trust boundary from a product-database query skill into dynamic capability acquisition, which can enable supply-chain compromise, unexpected code/content execution paths, or privilege expansion if an agent follows the instruction automatically.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill documentation instructs the agent to resolve auth/billing issues by locating or loading another skill, and if absent, to download and install a remote ZIP package from an external URL. That behavior exceeds the stated purpose of a Keepa product lookup skill and creates a supply-chain risk: a compromised or replaced package could introduce arbitrary new capabilities or unsafe instructions into the agent environment.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
Telling the agent to download and install a remote package is an unjustified capability escalation for a product-detail query skill. Even if intended as onboarding help, it can be abused for supply-chain compromise, persistence, or introduction of hidden behaviors unrelated to the requested API lookup.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The module documentation promises that data will not be written to `/tmp` and that an unwritable current directory will cause an error, but `_linkfox_root()` silently falls back to `~/linkfox` and then the system temp directory. This can cause sensitive API responses to be persisted in less controlled locations than users expect, undermining operator trust and potentially exposing data through shared temp storage or backups.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The module docstring explicitly says writing to /tmp is forbidden, but _linkfox_root() can fall back to tempfile.gettempdir()/linkfox when earlier locations are not writable. This mismatch can cause sensitive API responses to be persisted in a shared or less-controlled temporary directory contrary to the documented security model.

Intent-Code Divergence

Medium
Confidence
83% confidence
Finding
The module documentation promises that writing to /tmp is forbidden and that non-writable current directories should cause an error, but the implementation silently falls back to other locations including ~/linkfox and the system temp directory. In an agent context, this can cause sensitive API responses to be written to unexpected or less controlled locations, weakening data handling guarantees and making forensic expectations inaccurate.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The docstring explicitly states writing to /tmp is forbidden, but the implementation falls back to tempfile.gettempdir() when other locations are not writable. This mismatch can cause sensitive API responses to be stored in a less controlled temporary location, violating operator expectations and increasing exposure risk on shared systems.

Static analysis

No suspicious patterns detected.