Back to skill

Security audit

不压库存选品专家

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches Amazon product selection, but it also includes under-documented capabilities that can persistently modify agent instructions and redirect credential-bearing API traffic.

Install only if you trust the publisher and will use it in a controlled LinkFox environment. Review or remove the instruction-patching script before use, avoid custom LINKFOX_* API endpoint overrides outside trusted testing, do not upload private files because upload URLs are public, and create scheduled tasks only after confirming frequency, cost, and notification destinations.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T02 · Agent Memory Poisoning

Error
Location
skills/amazon-asin-dynamic-scoring/scripts/patch_scoring_to_agent.py:142
Finding

Undisclosed Persistent Modification of Agent Instruction Files

Content
View full analysis
bool: """Patch a CLAUDE.md file to add scoring module. Returns True if changes made.""" path = Path(filepath) if not path.exists(): print(f"ERROR: File not found: {filepath}") return False content = path.read_text(encoding="utf-8") # Check if already has the full scoring step (not just the reference line) if "二次评分(动态评分引擎)" in content: print(f"SKIP: {filepath} already has scoring step") return False # Check if it uses amazon-product-scout-agent if "amazon-product-scout-agent" not in content: print(f"SKIP: {filepath} does not use amazon-product-scout-agent") return False original = content changes = [] # 1. Add skill reference line after amazon-product-scout-agent line pattern_ref = r"(主脚本:call skill `amazon-product-scout-agent`[^\n]*)" if re.search(pattern_ref, content) and SKILL_REF_LINE not in content: content = re.sub( pattern_ref, r"\1\n" + SKILL_REF_LINE, content ) changes.append("skill 引用行") # Additional transformations omitted here modify triggers, workflow steps, # interaction behavior, and output rules. if content == original: print(f"NO CHANGE: {filepath} (patterns not matched, may need manual edit)") return False path.write_text(content, encoding="utf-8") print(f"PATCHED: {filepath}") print(f" Changes: {', '.join(changes)}") return True ``` ```python if sys.argv[1] == "--all": # Auto-find all CLAUDE.md files in agents directory agents_dir = Path("/root/.linkfox/workspaces/agents") targets = sorted(agents_dir.glob("*/CLAUDE.m ...[truncated 2224 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skills/amazon-product-scout-agent/scripts/response_io.py:67
Finding

Arbitrary Local Python Execution with Full Inherited Environment

Content
View full analysis
Path: p = Path(script_arg).expanduser() if not p.is_absolute(): # Resolve relative to the current working directory the agent invoked from. p = (Path.cwd() / p).resolve() else: p = p.resolve() if not p.is_file(): _err(f"--script path not found: {p}") return p ``` ```python # Force the child process to emit UTF-8 regardless of the host console # encoding. child_env = os.environ.copy() child_env["PYTHONIOENCODING"] = "utf-8" timed_out = False try: proc = subprocess.run( [sys.executable, str(main_script), params_str], capture_output=True, text=True, encoding="utf-8", errors="replace", env=child_env, timeout=args.timeout, ) stdout_text = proc.stdout or "" stderr_text = proc.stderr or "" returncode = proc.returncode except subprocess.TimeoutExpired as e: timed_out = True stdout_text = ( e.stdout.decode("utf-8", errors="replace") if isinstance(e.stdout, bytes) else (e.stdout or "") ) or "" stderr_text = ( e.stderr.decode("utf-8", errors="replace") if isinstance(e.stderr, bytes) else (e.stderr or "") ) or "" returncode = 124 ``` ```python p_run.add_argument( "--script", required=True, help="Path to the main script to execute, e.g. scripts/my_api.py", ) ``` ### Technical Analysis The `--script` option accepts any existing file path. `_resolve_script()` canonicalizes the path but does not restrict it to the current Skill, an approved scripts directory, or an allowlist of trusted programs. The selected file is then executed by ...[truncated 1697 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
skills/linkfox-aigc-textgen/scripts/onboarding.py:77
Finding

Credential and Personal-Data Redirection Through Unrestricted API Endpoint Overrides

Content
View full analysis
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_AGENT_USER_API_URL", "https://agent-api.linkfox.com", ) ``` ```python def _headers(source: str, origin_host: str, *, access_token: str = "", user_id: str = "", group_id: str = "") -> dict: """Build browser-style headers and attach authorization and uid.""" h = { "Accept": "application/json, text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "Origin": f"https://{origin_host}", "Referer": f"https://{origin_host}/", "source": source, "User-Agent": UA, } if access_token: h["authorization"] = acce ...[truncated 3751 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skills/linkfox-report-generator/scripts/inject_report.py:161
Finding

Unsanitized HTML and JavaScript Injection in Generated Reports

Content
View full analysis
str: # Extract ECharts and Canvas blocks. echarts_code = "" m = _ECHARTS_BLOCK_RE.search(content) if m: echarts_code = m.group(1).strip() echarts_code = _SCRIPT_OPEN_RE.sub("", echarts_code) content = _ECHARTS_BLOCK_RE.sub("", content).strip() canvas_code = "" m = _CANVAS_BLOCK_RE.search(content) if m: canvas_code = m.group(1).strip() canvas_code = _SCRIPT_OPEN_RE.sub("", canvas_code) content = _CANVAS_BLOCK_RE.sub("", content).strip() # Replace document-level placeholders. html = template.replace("{{TITLE}}", title or "LinkFox Analysis Report") html = html.replace("{{LANG}}", language) # Inject main content between template markers. html = re.sub( r".*?", "\n" + content + "\n", html, flags=re.DOTALL, ) # Insert chart initialization code into executable template regions. if echarts_code: html = html.replace( "// ECHARTS_INIT_START\n // ECHARTS_INIT_END", "// ECHARTS_INIT_START\n " + echarts_code + "\n // ECHARTS_INIT_END", ) if canvas_code: html = html.replace( "// CANVAS_INIT_START\n // CANVAS_INIT_END", "// CANVAS_INIT_START\n " + canvas_code + "\n // CANVAS_INIT_END", ) return html ``` ```python final_html = _inject( template, content, args["title"], args["language"], ) try: with open(out_path, "w", encoding="utf-8") as f: ...[truncated 2575 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 (147)

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

Critical
Category
Data Flow
Confidence
97% confidence
Finding

download_media performs arbitrary outbound HTTP(S) requests to caller-controlled URLs with no allowlist, destination validation, or private-address blocking. In an agent/runtime context this is a classic SSRF primitive that can be used to probe internal services, access cloud metadata endpoints, or fetch attacker-chosen content into the workspace.

Content

Scanner excerpt · skills/amazon-product-scout-agent/scripts/linkfox_paths.py (reported line 504)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

Tainted flow: 'req' from os.environ.get (line 335, 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 · skills/linkfox-aigc-textgen/scripts/aigc_textgen.py (reported line 237)May include surrounding context.

python
req = _lf_Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with _lf_urlopen(req, timeout=timeout) as resp:
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")
                if "mp4" in ct:

Tainted flow: 'req' from os.environ.get (line 335, 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 · skills/linkfox-aigc-textgen/scripts/aigc_textgen.py (reported line 337)May include surrounding context.

python
}
    req = Request(url, data=data, headers=headers, method="POST")
    try:
        with urlopen(req, timeout=HTTP_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 POST destination is derived from environment-controlled base URLs, and the function sends sensitive data including phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those endpoints. If an attacker can influence environment variables in the agent/runtime, they can redirect authentication and credential material to an attacker-controlled server, causing credential theft and account compromise.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/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
94% confidence
Finding

The gateway request URL is built from environment-controlled base configuration and is used with an Authorization header containing the agent API key. An attacker who can set the base URL can exfiltrate that API key and manipulate account, package, and order operations through a malicious endpoint.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/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 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

download_media() accepts an arbitrary url and fetches it with urlopen after only checking for http:// or https://. This enables server-side request forgery behavior, allowing the skill to contact attacker-chosen internal or external hosts and write the response to disk, which is especially risky because the skill's stated purpose does not require unrestricted network retrieval.

Content

Scanner excerpt · skills/linkfox-file-upload/scripts/linkfox_paths.py (reported line 524)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The code performs outbound HTTP(S) fetches from a caller-supplied URL and writes the response to disk with only a scheme check. This is a real SSRF-style capability: if an attacker can influence the URL, the skill can be used to contact arbitrary remote hosts, probe internal services reachable from the runtime, or retrieve attacker-controlled content into local storage.

Content

Scanner excerpt · skills/linkfox-report-generator/scripts/linkfox_paths.py (reported line 524)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The POST target URL is derived from environment-controlled base URLs and the request may include SMS login data, access tokens, refresh tokens, generated API keys, and user identifiers in headers/body. If an attacker can influence environment variables, they can redirect these authenticated requests to an attacker-controlled host and exfiltrate credentials and session material.

Content

Scanner excerpt · skills/linkfox-sellersprite-product-search/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
94% confidence
Finding

The gateway URL is also environment-derived and is used for authenticated urllib requests carrying the API key in the Authorization header. A manipulated environment can redirect order, account, or package requests to an attacker-controlled endpoint, leaking the API key and enabling unauthorized account actions.

Content

Scanner excerpt · skills/linkfox-sellersprite-product-search/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 73, 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 · skills/linkfox-sellersprite-product-search/scripts/sellersprite_product_search.py (reported line 80)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 274, 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 · skills/amazon-product-scout-agent/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 274, 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 · skills/linkfox-file-upload/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 274, 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 · skills/linkfox-report-generator/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 274, 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 · skills/linkfox-task-scheduler/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The function accepts an arbitrary caller-supplied URL and performs a network fetch with no hostname allowlist, IP-range validation, or redirect controls. In an agent/runtime context this enables SSRF-style access to internal services or unintended outbound requests, and the downloaded content is then persisted locally, increasing abuse potential.

Content

Scanner excerpt · skills/linkfox-task-scheduler/scripts/linkfox_paths.py (reported line 524)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

Tainted flow: 'req' from os.environ.get (line 249, 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 · skills/linkfox-task-scheduler/scripts/task_scheduler.py (reported line 264)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            body = response.read().decode("utf-8")
            if not body.strip():
                # delete 等接口可能无返回体

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Task creation and webhook-based notification management are not inherently unsafe, but when hidden inside a product-selection skill they can be abused for persistence, automated external signaling, or unreviewed repeated execution. Writing full API responses to local files further increases the chance of storing secrets or sensitive metadata.

Content

No source excerpt is available for this finding.