Back to skill

Security audit

Linkfox OS

Security checks for vulnerabilities and agentic risk

Overview

This is a real e-commerce integration, but it handles login codes, API keys, uploads, and public task links with safeguards that users should review before installing.

Install only if you trust LinkFox and are comfortable sending prompts, local uploaded files, phone/SMS login data, payment choices, and API keys through this workflow. Use official LinkFox endpoints only, avoid custom URL environment overrides, avoid submitting confidential material, and prefer a secure secret store over shell rc files for the API key. Treat generated share links as public links that may expose the task process and results for up to one year.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/linkfox_os.py:803
Finding

Automatic Download of Unvalidated Server-Supplied URLs

Content
View full analysis
str: """将 resource_link 的 HTTPS URL 下载到 output_dir,返回本地路径。 若 uri 是 file:// 协议则跳过(无法远程下载)。失败时打印警告并返回空字符串。 """ if not uri or uri.startswith("file://"): return "" try: # 用 name 作为文件名兜底,从 URL 末尾取原始文件名 url_filename = uri.rstrip("/").split("/")[-1].split("?")[0] filename = url_filename or (name.replace(" ", "_") + ".bin") local_path = os.path.join(output_dir, filename) urlretrieve(uri, local_path) return local_path except Exception as e: print(f"Warning: 下载文件失败 [{name}] {uri}: {e}", file=sys.stderr) return "" ``` Server-provided URLs are passed to this function automatically from task event data: ```python uri = item.get("uri") or item.get("url") or "" name = item.get("name") or item.get("title") or "data" if uri and not uri.startswith("file://") and uri not in _seen_rl_uris: _seen_rl_uris.add(uri) task_dir = ensure_task_dir(msg_id) local = _download_resource_link(uri, name, task_dir) ``` ### Technical Analysis The implementation treats remote task results as trusted download instructions. It rejects only `file://` URLs and does not: - Require HTTPS. - Restrict downloads to approved LinkFox or S3 domains. - Reject loopback, private, link-local, or reserved destination addresses. - Validate the destination after redirects. - Limit the downloaded response size. - Validate the expected content type. - Stream the response with a strict byte limit. `urlretrieve()` follows the supplied URL and writes the complete response to disk. If an attacker can influence the LinkFox task result, compromise a configured API endpoint, or inject a malicious `resource_link`, the client can be induced to acces ...[truncated 1486 chars]
Remediation
View remediation

other

Warning
Location
scripts/linkfox_os.py:1030
Finding

Public Task Share Links Are Created Automatically Without Explicit Consent

Content
View full analysis
dict: """任务终态后调用 /agent-studio/task/getShareUrl 换取工作台公开分享链接。 仅在 stopReason 非空后调用;后端会二次校验(任务归属 + 终态),失败时返回 带 error 字段的 dict,调用方按需展示或忽略。 """ if not message_id: return {"error": "missing messageId"} return api_request(SHARE_URL_ENDPOINT, {"messageId": message_id}) ``` The Skill documentation states that the generated link is public, does not require authentication, and remains valid for one year. ### Technical Analysis Public sharing is not required to submit, execute, poll, or retrieve a task. Nevertheless, every terminal task causes an automatic request to create or retrieve a public share URL. There is no command-line opt-in, consent prompt, confidentiality check, or warning before the public link is generated. Task records may contain: - Confidential prompts and business questions. - Tool execution traces. - Generated market or product reports. - References to user-uploaded files. - Remote event messages and resource links. The generated public URL is printed to output and pe ...[truncated 965 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:145
Finding

Remote Service Content Is Required to Be Relayed Verbatim as Trusted Agent Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/linkfox_os.py:55
Finding

Authentication Secrets Can Be Redirected to Unrestricted Environment-Controlled Endpoints

Content
View full analysis
dict: """Make a POST request to the linkfox-os API.""" api_key = get_api_key() # rstrip/lstrip 兼容环境变量值带或不带末尾斜杠 url = f"{LINKFOXAGENT_BASE_URL.rstrip('/')}/{endpoint.lstrip('/')}" data = json.dumps(payload).encode("utf-8") req = Request( url, data=data, headers={ "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "linkfox-os-skill/1.0", }, method="POST", ) try: with urlopen(req, timeout=30) as response: result = json.loads(response.read().decode("utf-8")) ``` The same pattern applies to authentication and onboarding destinations: ```python def _get_login_base() -> str: return ( os.environ.get("LINKFOX_LOGIN_API_URL") or "https://api.linkfox.com" ).rstrip("/") def _get_agent_user_base() -> str: return ( os.environ.get("LINKFOX_AGENT_USER_API_URL") or "https://agent-api.linkfox.com" ).rstrip("/") ``` Credential-bearing requests then send access tokens to those destinations: ```python headers = { "Accept": "application/json, text/plain, */*", "Content-Type": "application/json;charset=UTF-8", "Origin": "https://ai.linkfox.com", "Referer": "https://ai.linkfox.com/", "source": "agent-linkfox-web", "authorization": access_token, "uid": build_uid_header(access_token, user_id), } ``` ### Technical Analysis The Skill permits several service origins to be replaced through environment variables without validating: - The ...[truncated 1859 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
references/onboarding.md:94
Finding

Onboarding Instructions Persist Bearer API Keys in Plaintext Startup Configuration

Content
View full analysis
> ~/.zshrc # or echo 'export LINKFOXAGENT_API_KEY="your-key"' >> ~/.bashrc source ~/.zshrc # or source ~/.bashrc ``` The surrounding guidance tells the Agent to help the user apply this configuration after obtaining the generated API key. ### Technical Analysis The API key is a bearer credential. Persisting it directly in `.zshrc`, `.bashrc`, or the Windows user environment leaves it available indefinitely in plaintext. Shell startup files and user environment settings may be: - Readable by other software running under the same account. - Included in backups or diagnostic archives. - Synchronized between devices. - Accidentally copied into support requests. - Disclosed through terminal or command history. - Loaded into every child process launched from the shell. The instructions do not verify file permissions, avoid command history, establish expiration, or describe key rotation and revocation. Repeated appends may also leave obsolete credentials in the same file. This persistence is user-authorized configuration rather than a system backdoor, but it creates avoidable secret-management risk. ### Attack Path 1. The onboarding script generates or retrieves an API key. 2. The user or Agent follows the documented startup-file command. 3. The bearer token remains in plaintext in a shell configuration file or persistent user environment. 4. Local software, a backup, a diagnostic collection, or an accidental disclosure obtains the token. 5. The attacker uses the token to authenticate to LinkFox APIs. ### Impact Assessment Exposure grants the privileges assigned to the API key, potentially including task submission, task retrieval, access to account-relat ...[truncated 152 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
Findings (62)

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

Critical
Category
Data Flow
Confidence
97% confidence
Finding

The request destination is derived from LINKFOXAGENT_BASE_URL, an environment variable, and the code sends the Authorization API key to whatever host that variable names. In an agent/skill context, environment variables are part of the execution trust boundary, so a malicious workspace or launcher can redirect traffic to an attacker-controlled endpoint and exfiltrate credentials and submitted prompts.

Content

Scanner excerpt · scripts/linkfox_os.py (reported line 134)May include surrounding context.

python
)

    try:
        with urlopen(req, timeout=30) as response:
            result = 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 241, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The request target is derived from environment variables and the function sends login material plus a fixed/custom uid header to that destination. If an attacker can influence LINKFOX_LOGIN_API_URL, they can redirect authentication traffic to an arbitrary server and capture verification/login data, making this an SSRF-plus-credential-exfiltration issue rather than a benign configurable endpoint.

Content

Scanner excerpt · scripts/onboarding/setup_common.py (reported line 103)May include surrounding context.

python
if with_uid:
        headers["uid"] = uid or _LOGIN_FIXED_UID
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=30)
        return r.json()
    except Exception as e:
        return {"_error": str(e), "_body": getattr(e, 'response', None) and e.response.text[:500] if hasattr(e, 'response') else ""}

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

Critical
Category
Data Flow
Confidence
97% confidence
Finding

This function posts Authorization, uid, and optional team identifiers to a base URL taken from environment variables. If LINKFOX_AGENT_USER_API_URL is attacker-controlled, the code will exfiltrate bearer tokens and identity headers to an arbitrary host, directly exposing account or team API access.

Content

Scanner excerpt · scripts/onboarding/setup_common.py (reported line 132)May include surrounding context.

python
if group_id:
        headers["tid"] = group_id
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=30)
        return r.json()
    except Exception as e:
        return {"_error": str(e), "_body": getattr(e, 'response', None) and e.response.text[:500] if hasattr(e, 'response') else ""}

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

gateway_post builds the destination from environment-controlled base URL data and always includes the API key in the Authorization header. An attacker who can set LINKFOX_AGENT_API_URL or LINKFOX_TOOL_GATEWAY can redirect these authenticated POST requests to infrastructure they control, causing secret exfiltration and potentially enabling arbitrary use of the stolen API key.

Content

Scanner excerpt · scripts/onboarding/setup_common.py (reported line 217)May include surrounding context.

python
},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                raw = resp.read().decode()
            return json.loads(raw)
        except urllib.error.HTTPError as e:

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The GET helper sends the Authorization header to a URL assembled from environment input without verifying the destination. This permits redirection of authenticated requests to attacker-controlled servers, exposing the API key and allowing unauthorized reuse of that credential.

Content

Scanner excerpt · scripts/onboarding/setup_common.py (reported line 250)May include surrounding context.

python
time.sleep(1 << (attempt - 1))
        req = Request(url, method="GET", headers={"Authorization": api_key})
        try:
            with urlopen(req, timeout=30) as resp:
                raw = resp.read().decode()
            return json.loads(raw)
        except urllib.error.HTTPError as e:

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The code builds the POST target from LINKFOXAGENT_BASE_URL, which is read from the environment, and sends the Authorization API key to that URL. If an attacker can influence the environment or runtime configuration, they can redirect requests to an attacker-controlled server and capture the API key and request payloads.

Content

Scanner excerpt · scripts/upload/upload_common.py (reported line 63)May include surrounding context.

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

Tainted flow: 'req' from os.environ.get (line 56, 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/upload/upload_common.py (reported line 205)May include surrounding context.

python
"""执行签好名的 PUT。失败抛 RuntimeError 带上响应体前 300 字。"""
    req = Request(url, method="PUT", data=body, headers=headers)
    try:
        with urlopen(req, timeout=60) as resp:
            if resp.status // 100 != 2:
                raise RuntimeError(f"S3 PUT 非 2xx: {resp.status}")
    except urllib.error.HTTPError as e:

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 13)May include surrounding context.

md
---

## 0. Output Rules (MANDATORY)

**禁止输出任何 emoji / 表情符号 / 图形字符**(包括但不限于笑脸、勾叉、纸夹、文件夹、灯泡、警告标志、旗帜、动物等 Unicode emoji)。

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The workflow explicitly instructs the agent to collect a user's phone number and one-time SMS code, then use them to authenticate and retrieve account credentials on the user's behalf. This is highly sensitive because SMS codes are authentication factors, and routing them through an agent normalizes credential interception patterns and can enable account takeover if mishandled or abused.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill directs the agent to obtain the user's API key from the login flow and then help place that secret into environment-variable commands, which risks exposing the key in conversational transcripts, tool logs, terminal history, and persistent config files. Because the agent is both retrieving and rendering the credential, the workflow centralizes secret handling in an unsafe channel.

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/onboarding.md (reported line 110)May include surrounding context.

�量:LINKFOX_AGENT_API_URL 或回退 LINKFOX_TOOL_GATEWAY)。

Windows(PowerShell,永久写入用户环境变量):

powershell
setx LINKFOXAGENT_API_KEY "你的key"

配置后重启 PowerShell 或 Claude Code 会话生效。

macOS / Linux(zsh / bash,写入 shell rc):

bash
echo 'export LINKFOXAGENT_API_KEY="你的key"' >> ~/.zshrc   # macOS 默认 zsh
# 或
echo 'export LINKFOXAGENT_API_KEY="你的key"' >> ~/.bashrc  # Linux 默认 bash
source ~/.zshrc   # 或 source ~/.bashrc

注意:>> 是追加,仅首次配置执行一次;重复执行会在 rc 文件里产生重复行(不影响功能但污染文件,可用文本编辑器删除多余行)。

如使用 fish shell,请自行配置等价的环境变量。

入口 2:计费不足充值

  1. 列套餐:调 python <skill>/scripts/onboarding/list_plans.py,输出 JSON 套餐清单(含 plan_id、name、price、currency、credits、description、`available_meth

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/linkfox_os.py (reported line 101)May include surrounding context.

python
def get_api_key() -> str:
    """Get API key from environment. Reads LINKFOXAGENT_API_KEY only."""
    key = os.environ.get("LINKFOXAGENT_API_KEY")
    if not key:
        print(

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest description says to use the skill for 'any multi-step e-commerce workflow,' which is an open-ended catch-all rather than a narrowly bounded trigger. Although examples are provided, this phrasing leaves unclear where the skill should not activate and risks overmatching many routine commerce-related requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

These lines impose mandatory output rules in Chinese-tagged format and categorically forbid alternate presentation styles, regardless of user preference. This is a natural-language policy concern because the skill forces a fixed locale/style convention instead of offering user choice or documenting a justified locale-specific constraint.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill requires verbatim forwarding of all progress step labels and especially all [文件] lines, including resource URLs and local file paths, without filtering. If upstream tasks handle sensitive user uploads, private artifacts, or internal paths, this creates a built-in disclosure channel that can expose data unnecessarily to the user or to unintended viewers of the chat transcript.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

At L250 the document states 'There is no ShareURL in the linkfox-os API.' However, L272-L278 says the script automatically calls /agent-studio/task/getShareUrl and appends a public share link section that must be forwarded to the user. This is an active contradiction in the skill's own intent/documentation, not merely an omission.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The result rules mandate outputting all data-file entries and any generated public share link to the user. Because the share URL is described as a public link valid for a long duration and data files are exposed via public download URLs, this can unintentionally disclose task artifacts, uploaded materials, and derived reports beyond the minimum necessary scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation explicitly states that getShareUrl returns a public URL that can be sent to others and viewed without login, but it does not prominently warn about privacy, data exposure, or the sensitivity of the full task history and results being disclosed. Even with ownership and terminal-state checks, an authorized user can still unintentionally expose confidential prompts, outputs, tool traces, or linked resources by sharing the URL.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The example prompt explicitly specifies '美国站英语' for listing generation, and the file otherwise presents agent behavior as normative reference material. This can violate language/locale policy when the skill is framed to require a specific language rather than offering a user-selectable locale or documenting the constraint as optional.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The '带货口播' section states default values of language=英语 and salesRegion=美国. A fixed default locale in policy-facing documentation can create a language/locale policy violation unless the skill clearly offers user choice or explains the constraint as region-specific behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documented flow enables SMS-based account login/registration, retrieval of team identifiers, and generation of long-lived API tokens that become LINKFOXAGENT_API_KEY. This is a sensitive account-management and credential-provisioning capability; if exposed through a broadly callable skill without strict authorization, consent, and secret-handling controls, it could let the skill obtain or mint credentials for user accounts and then use them for downstream paid operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown instructs handling of phone numbers, SMS verification codes, access tokens, refresh tokens, and generated API keys, but it does not include user-facing privacy, consent, retention, or redaction requirements. In an agent context, this omission is dangerous because operators may collect secrets and personal data in prompts, logs, or transcripts, increasing the risk of credential leakage, account takeover, and privacy violations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The onboarding instructions, prompts, and example user-facing text are entirely in Chinese, and the flow directs the agent to use that wording without presenting an opt-in or alternative language. Under the stated policy, forcing a specific language without user choice is a natural-language policy violation unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The workflow instructs the agent to solicit a user's phone number and then an SMS verification code, but it does not require a clear warning that these are sensitive authentication factors. In this context, the agent is effectively acting as an intermediary in an account login flow, which increases phishing and account-takeover risk if users are not explicitly informed about what is being collected and why.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill tells the agent to append an API key to shell startup files, which persists the secret on disk and may expose it to other local users, backups, shell history mishandling, or accidental sharing of dotfiles. Although persistence may be operationally convenient, the instructions omit a clear warning about the security tradeoff of long-lived plaintext secret storage.

Content

No source excerpt is available for this finding.