T01 · Skill Instruction Hijacking
- Location
skills/linkfox-tsearch-search/SKILL.md:140- Finding
Silent Transmission of Conversation-Derived Feedback
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches a LinkFox photo-generation workflow, but it includes under-controlled paid external calls, public uploads, credential-bearing configurable endpoints, and automatic feedback reporting.
Install only if you are comfortable sending product images, prompts, reference images, search terms, and account credentials through LinkFox services and publishing selected local files as public URLs. Use it in a trusted environment, keep LinkFox endpoint environment variables pointed at official HTTPS hosts, and confirm costs and uploads before generation.
skills/linkfox-tsearch-search/SKILL.md:140Silent Transmission of Conversation-Derived Feedback
skills/linkfox-aigc-imagegen/SKILL.md:119Forced Paid Image-Generation Execution Without Confirmation
skills/linkfox-aigc-imagegen/scripts/aigc_imagegen.py:38API Credentials and Context Identifiers Can Be Redirected to an Arbitrary Gateway
skills/linkfox-aigc-imagegen/scripts/onboarding.py:68Onboarding Phone, Verification Codes, and Access Tokens Can Be Redirected
skills/linkfox-file-upload/scripts/linkfox_paths.py:289Gateway-Controlled OSS Endpoint Can Receive STS-Authenticated Uploads
skills/pinterest-image-finder/scripts/find_inspiration_image.py:76Unrestricted Fetching of API-Supplied URLs Enables SSRF and Disk Exhaustion
skills/linkfox-report-generator/scripts/inject_report.py:158Report Content Is Injected Without HTML Sanitization
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
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:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
req = Request(url, data=data, headers=headers, 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 ""
The script builds request destinations from environment variables such as LINKFOX_LOGIN_API_URL and LINKFOX_AGENT_USER_API_URL, then sends sensitive authentication material including phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those URLs. In an agent-skill environment where env vars may be controlled by the host or a malicious wrapper, this enables credential exfiltration and SSRF-like redirection to attacker infrastructure.
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 = ""
The gateway URL is also sourced from environment configuration and used in urlopen with the Authorization header carrying the LinkFox API key. If the base URL is redirected through environment control, the script will transmit the API key and order/account requests to an attacker-controlled service, exposing billing and account access.
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
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
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:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
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 ""
The code builds request destinations from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, group identifiers, and generated API tokens to those endpoints. If an attacker can influence environment variables in the runtime, this becomes a server-side exfiltration path that can redirect authentication and billing traffic to attacker-controlled infrastructure.
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 = ""
The gateway URL is also derived from environment variables and used by urllib to send authenticated requests with the API key in the Authorization header. An attacker who controls the environment can redirect package lookup, order creation, or account queries to an attacker endpoint and capture credentials and transactional metadata.
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
download_media accepts an arbitrary caller-supplied http/https URL and fetches it with urlopen, with no allowlist, destination validation, or private-network blocking. In an agent/runtime context this creates an SSRF primitive that can be used to reach internal services, cloud metadata endpoints, or attacker-chosen hosts and store the response as local media.
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", "")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
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:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
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:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
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", "")
The code builds request destinations from environment variables such as LINKFOX_LOGIN_API_URL and LINKFOX_AGENT_USER_API_URL, 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, they can redirect authentication traffic to a malicious server and capture credentials or session tokens, effectively enabling credential exfiltration and account compromise.
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 = ""
The gateway URL is also sourced from environment variables and used in urlopen with the Authorization header containing the LinkFox API key. An attacker who controls the environment can redirect billing, account, or package-management requests to an attacker-controlled host and harvest the API key or manipulate downstream behavior.
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
The request URL and multiple headers are influenced by environment variables such as LINKFOX_TOOL_GATEWAY, SESSION_ID, MESSAGE_ID, MODE_ID, and APP_NAME before being sent via urlopen. If an attacker can control the environment, they can redirect requests to an attacker-owned endpoint and exfiltrate the API key and request payload, making this a real SSRF/credential-leakage risk rather than a harmless configuration pattern.
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 ""
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
req = Request(api_url, data=data, headers=headers, method="POST")
try:
with urlopen(req, timeout=120) as response:
result = json.loads(response.read().decode("utf-8"))
return result
except (HTTPError, URLError, Exception) as e:
The script fetches page_url values returned by an external search service without validating scheme, host, or address range. If the search backend can be influenced or returns malicious URLs, this creates an SSRF-style outbound fetch primitive that can be used to probe internal services or access unexpected network locations from the agent environment.
"""尝试直接请求页面,从 HTML 中提取图片 URL"""
try:
req = Request(page_url, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})
with urlopen(req, timeout=timeout) as response:
html = response.read().decode("utf-8", errors="ignore")
# 提取 i.pinimg.com 图片 URL
pinimg_pattern = r'https://i\.pinimg\.com/[^\s"<>\'\\]+\.(?:jpg|jpeg|png|webp)'
声明描述的是一个较完整的商品摄影生成流水线,包含多步前处理与特定模型/效果控制;但代码仅负责把调用方提供的参数原样提交给生图网关,等待任务完成并下载结果。虽然“生成图片”这一大方向部分相关,但核心宣称能力基本都不在该代码中出现,因此描述明显夸大且与实际行为不符。代码还会把结果与媒体文件写入本地会话目录,不过这属于支持性实现细节,不是主要失配点。
声明描述的是一个图像生成工作流,核心能力应包括图片分析、灵感图检索、prompt 构造、调用图像模型生成照片等。但该代码完全没有处理商品图、参考图、摄影要素提取、JSON prompt 生成或 BANANA_PRO 出图逻辑。相反,它实现的是独立的账号登录、令牌获取、套餐购买和支付查询 CLI。其主要目的与声明严重不符,且包含多个未声明的账号认证与支付能力,因此应判定为明显不匹配。
声明描述的是一个以商品照片生成和图像工作流为核心的技能,但代码清晰地实现的是通用 AIGC 文本生成异步调用脚本。其主要外部接口路径就是 /aigc/textGenAsync 和 /aigc/textTaskQuery,说明目标是文本生成任务而非图像生成。代码没有任何图像输入处理、参考图检索、视觉分析、摄影参数抽取、BANANA_PRO 模型调用、图片保存/返回等逻辑。相反,它重点实现了文本结果轮询、content 提取、换行压平、本地 JSON 落盘与会话元数据管理。这属于主要用途的实质性不一致,应判定为描述与行为不匹配。
声明描述的是一条图像生成工作流,涉及商品图分析、灵感图检索、JSON prompt 构造、调用 BANANA_PRO 模型出图,以及角色一致性管理。但代码完全没有任何图像处理、提示词生成、模型调用、搜索灵感图或照片生成相关逻辑。相反,代码实现的是 LinkFox 平台的账号 onboarding 和商业支付流程 CLI,包含短信登录、Token/API key 获取、套餐查询、下单与支付二维码渲染、订单状态查询等功能。这是主功能和能力层面的明显不一致,属于实质性描述-行为不匹配。
声明的核心能力是图像分析、灵感图检索、JSON prompt 构造和图片生成调度,属于商品摄影风格生成链路。实际代码没有任何图像分析、参考图搜索、prompt 生成、模型调用或角色一致性管理逻辑,而是专注于将本地文件上传到 OSS。其主要目的、所访问的资源(本地文件系统与 OSS/STS 接口)以及产生的结果(公开文件链接)都与声明严重不符,因此属于明显的描述与行为不一致。
声明描述的是一个以图像分析、灵感检索、prompt 生成和图像生成为核心的摄影生成技能;但提供的代码完全没有商品图分析、灵感图搜索、JSON prompt 生成、BANANA_PRO 模型调用或角色一致性逻辑。相反,它实现的是与这些目标无直接对应关系的基础设施功能:路径解析、会话落盘、元数据管理、OSS 上传和媒体下载。虽然这类工具代码可能作为更大系统的配套组件存在,但就该代码块本身而言,其实际行为与声明的核心用途存在明显且实质性的偏差,因此应判定为描述与行为不匹配。
声明描述的是一个图像生成工作流,核心能力应包括图片分析、灵感图搜索、摄影风格抽取、JSON prompt 生成以及模型出图调度。但给定代码完全没有图像处理、搜索、prompt 构造或模型调用逻辑。相反,它仅执行 HTML 模板拼装和报告落盘,是一个报告生成/封装工具。其主要目的、输入输出形式、处理对象和副作用都与声明严重不符,因此属于明显的 description-behavior mismatch。
声明描述的是一个图像生成工作流技能,核心能力应包括商品图分析、灵感图检索、摄影风格提取、JSON prompt 构造和图像模型调度。但提供的代码完全没有任何图像分析、提示词生成、模型调用、角色一致性管理或摄影要素处理逻辑。相反,它实现的是与该声明无关的基础设施功能:管理 session 文件路径、记录 _meta.json 和 index.jsonl、通过 LINKFOX_TOOL_GATEWAY 获取 OSS 临时凭证、上传文件到阿里云对象存储、下载媒体资源,以及对文本换行做占位符转换。这些都属于显著不同的主要用途,并且包含未在声明中体现的网络访问与文件上传/下载能力。因此描述与实际行为明显不符。