Back to skill

Security audit

潜力市场专家

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Amazon product-scouting purpose, but it bundles under-scoped tools that can persistently alter agent instructions and send credentials to environment-selected endpoints.

Install only if you trust the publisher and the runtime environment. Keep LinkFox gateway environment variables fixed to trusted HTTPS hosts, avoid running the CLAUDE.md patch utility unless you intentionally want persistent agent-instruction changes, treat onboarding output as secret material, and confirm any scheduled task or public file upload before use.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

T02 · Agent Memory Poisoning

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

Persistent Cross-Agent Instruction Modification

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 = [] # Add new instructions, triggers, workflow steps, and interaction behavior. # ... 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 def main(): if len(sys.argv) < 2: print("Usage: python3 patch_scoring_to_agent.py [ ...]") print(" python3 patch_scoring_to_agent.py --all (auto-find all agents)") sys.exit(1) 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.md")) # Also check workspace root root_claude = Path("/root/.linkfox/workspaces/CLAUDE.md") if root_claude.exists(): targets.append(root_clau ...[truncated 2029 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
skills/linkfox-aigc-textgen/scripts/aigc_textgen.py:74
Finding

API Credentials Can Be Redirected to an Arbitrary Gateway

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skills/linkfox-file-upload/scripts/linkfox_paths.py:57
Finding

Unsanitized Session Identifier Enables Path Traversal

Content
View full analysis
str: """Use SESSION_ID, otherwise generate a stable identifier.""" env = os.environ.get("SESSION_ID") if env: return env.strip() if "_auto" not in _SESSION_CACHE: _SESSION_CACHE["_auto"] = ( time.strftime("%H%M%S", time.localtime(ts)) + "-" + secrets.token_hex(3) ) return _SESSION_CACHE["_auto"] def _ensure_session(ts: float) -> tuple[str, str]: """Return the LinkFox root and session directory.""" date_str = time.strftime("%Y-%m-%d", time.localtime(ts)) sid = _session_id(ts) root = _linkfox_root() session_dir = os.path.join(root, date_str, sid) os.makedirs(session_dir, exist_ok=True) _ensure_meta(root, session_dir, date_str, sid, ts) return root, session_dir ``` ### Technical Analysis `SESSION_ID` is accepted without a character allowlist or path-containment check and is inserted directly into `os.path.join()`. An absolute `sid` causes Python to discard the preceding `root` and `date_str` components. A relative value containing `..` can traverse outside the intended date or LinkFox directory. Subsequent functions crea ...[truncated 1481 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skills/linkfox-aigc-textgen/scripts/onboarding.py:491
Finding

Generated API Key Is Exposed 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), } 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 acquired successfully", file=sys.stderr) return 0 return 1 ``` ### Technical Analysis The SMS onboarding flow re ...[truncated 1497 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
skills/linkfox-report-generator/scripts/inject_report.py:164
Finding

Generated Reports Permit Active HTML and JavaScript Injection

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 the main fragment without sanitization. html = re.sub( r".*?", "\n" + content + "\n", html, flags=re.DOTALL, ) # Inject extracted text directly into JavaScript execution contexts. 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 ``` ### Technical Analysis The generator treats the supplied content file as trusted HTML and inserts it directly into the output template. It also ex ...[truncated 1913 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 (142)

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

The code builds request destinations from environment-controlled base URLs and then sends sensitive data, including phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys, to those endpoints. If an attacker can influence the environment, this becomes SSRF/exfiltration: credentials and authentication material may be redirected to attacker-controlled infrastructure.

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

The gateway client uses an environment-derived base URL and attaches the API key in the Authorization header before calling urlopen. An attacker who can set LINKFOX_AGENT_API_URL or its fallback can cause authenticated requests to be sent to a malicious server, exposing API keys and enabling further unauthorized actions.

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

The download_media function performs arbitrary outbound HTTP(S) requests to a caller-supplied URL and writes the response to disk with no host allowlist, IP-range restrictions, or redirect controls. This creates a classic SSRF primitive that can be used to reach internal services, cloud metadata endpoints, or other sensitive network locations, which is especially risky because this shared utility is reusable by any skill.

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

The code sends an Authorization token from LINKFOX_AGENT_API_KEY to a network endpoint whose base URL is fully overrideable by the LINKFOX_TOOL_GATEWAY environment variable. In a compromised runtime or multi-tenant environment, an attacker who can set that variable can redirect the request to an attacker-controlled host and capture the API key or STS voucher response.

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

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The script builds request destinations from environment variables and then sends authentication material, access tokens, and API-token generation traffic to those URLs via requests.post. If an attacker can influence the environment, they can redirect login and token flows to an attacker-controlled endpoint and capture SMS-login tokens, user identifiers, refresh tokens, or generated API keys.

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

The gateway URL is also derived from environment variables and used in urllib.request.urlopen while attaching the API key in the Authorization header. An attacker who can set the environment can redirect these requests to an external server and exfiltrate the agent API key and related account/order data.

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

The request sent via urlopen includes multiple headers populated directly from environment variables, and the destination base URL is also environment-controlled via LINKFOX_TOOL_GATEWAY. In an agent runtime, this creates an exfiltration path where attacker-influenced environment data and the API key can be sent to an arbitrary endpoint if the gateway variable is overridden.

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

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This skill explicitly includes creation and management of scheduled tasks and webhook-capable reminders through another skill, yet no authorization, destination validation, or user-consent safeguards are described. In context, automation and notification features increase risk because they can repeatedly invoke external actions, persist workflows, or send data to third-party endpoints beyond the immediate scouting session.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
skills/linkfox-task-scheduler/references/api.md:58