Back to skill

Security audit

AIGC品牌基因提取

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly describes brand-style extraction, but it also includes account login, API-key issuance, and payment-order flows with weak scoping and secret-handling risks.

Review carefully before installing. Use only if you expect this brand-extraction skill to interact with LinkFox account services, and avoid the phone/SMS onboarding and payment commands unless you explicitly intend those actions. Do not set LinkFox API base URL override variables unless they point to trusted LinkFox hosts, and prefer a secret manager or temporary environment variable over writing API keys into shell startup files.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:60
Finding

Credential Disclosure Through Unrestricted API Endpoint Overrides

Content
View full analysis

Vulnerability Details

File Location: scripts/onboarding.py, lines 60-78, 173-186, 213-221, and 397-451
Vulnerability Type: Unvalidated credential transmission destination
Risk Level: High

Vulnerable Code

python
def _env_base(name: str, default: str, *fallbacks: str) -> str:
    for n in (name, *fallbacks):
        v = os.environ.get(n)
        if v:
            return v.rstrip("/")
    return default.rstrip("/")


def _agent_base() -> 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 _http_post(url: str, body: dict, headers: dict, timeout: int = 30) -> dict:
    """通用 requests POST,返回 JSON 或 {_error, _body}。"""
    try:
        _require_requests()
    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 = ""
        resp = getattr(e, "response", None)
        if resp is not None:
            try:
                body_text = resp.text[:500]
            except Exception:
                pass
        return {"_error": str(e), "_body": body_text}
python
def _fetch_user_info_v3(access_token: str, user_id: str) -> dict:
    """从 userInfo 拿 group_id / member_id。"""
    resp = _http_post(f"{_login_base()}/linkFoxApp/api/userCenter/userInfo", {},
                      _headers("agent-linkfox-web", "agent.linkfox.com",
                               access_token=access_token, user_id=user_id))
python
def _get_or_generate_api_token(access_token: str, user_id: str, group_id: str) -> d
...[truncated 2632 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove production support for arbitrary authentication endpoint overrides.
  • If overrides are required for development, require an explicit development-mode flag and reject them by default.
  • Enforce HTTPS and validate destinations against an exact allowlist of approved LinkFox hostnames.
  • Resolve and validate the effective hostname before attaching any authorization header or sensitive request body.
  • Disable redirects for credential-bearing requests, or validate every redirect target before forwarding credentials.
  • Separate public login requests from authenticated requests so that credentials cannot accidentally be attached to an untrusted service.
  • Avoid returning raw server response bodies when they may contain tokens or private account information.
  • Add automated tests confirming that HTTP URLs, unapproved hosts, user-info subdomains, and cross-origin redirects are rejected.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_brand_gene.py:46
Finding

Session Identifier Path Traversal Allows Writes Outside the Intended Session Root

Content
View full analysis

Vulnerability Details

File Location: scripts/save_brand_gene.py, lines 46-53 and 134-140; scripts/onboarding.py, lines 117-128
Vulnerability Type: Path traversal through an unsanitized environment variable
Risk Level: Medium

Vulnerable Code

python
def _lf_session_id(ts):
    env = _lf_os.environ.get("SESSION_ID")
    if env:
        return env.strip()
    if "_auto" not in _LF_SESSION_CACHE:
        _LF_SESSION_CACHE["_auto"] = (
            _lf_time.strftime("%H%M%S", _lf_time.localtime(ts)) + "-" + _lf_secrets.token_hex(3)
        )
    return _LF_SESSION_CACHE["_auto"]
python
def _lf_ensure_session(ts):
    date_str = _lf_time.strftime("%Y-%m-%d", _lf_time.localtime(ts))
    sid = _lf_session_id(ts)
    root = _lf_linkfox_root()
    session_dir = _lf_os.path.join(root, date_str, sid)
    _lf_os.makedirs(session_dir, exist_ok=True)
    _lf_ensure_meta(root, session_dir, date_str, sid, ts)
    return root, session_dir
python
def session_dir() -> str:
    ts = time.time()
    sid = (os.environ.get("SESSION_ID") or "").strip() or (
        time.strftime("%H%M%S", time.localtime(ts)) + "-" + secrets.token_hex(3))
    path = os.path.join(_linkfox_root(), time.strftime("%Y-%m-%d", time.localtime(ts)), sid)
    os.makedirs(path, exist_ok=True)
    return path

Technical Analysis

Both scripts use the externally controlled SESSION_ID environment variable directly as a filesystem path component. The value is not checked for absolute paths, parent-directory components, path separators, or platform-specific path syntax.

On POSIX systems, an absolute final component causes os.path.join to discard all preceding components. A value containing .. can similarly escape the expected date and session directories. The scripts then create directories and write metadata, generated brand JSON, or QR image files beneath the resulting attacker-selected l ...[truncated 1148 chars]

Remediation
View remediation

Remediation Suggestions

  • Restrict SESSION_ID to a conservative identifier pattern, such as [A-Za-z0-9_-]{1,64}.
  • Reject empty identifiers, absolute paths, drive-qualified paths, .., path separators, and null characters.
  • Canonicalize both the session root and candidate directory with realpath.
  • Verify containment using os.path.commonpath([root, candidate]) == root before creating directories or files.
  • Apply the same validation helper consistently in both scripts.
  • Create output files with restrictive permissions where supported.
  • Consider opening files with exclusive creation semantics when overwriting is unnecessary.
  • Add tests covering POSIX absolute paths, Windows drive paths, UNC paths, mixed separators, and nested traversal sequences.

T08 · Insecure Dependencies

Warning
Location
scripts/onboarding.py:144
Finding

Unpinned Runtime Dependency Installation Creates Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: scripts/onboarding.py, lines 144-148 and 166-170
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Vulnerable Code

python
def render_qr(content: str, out_dir: str) -> dict:
    try:
        import qrcode
    except ImportError:
        err = "缺少 qrcode 依赖,请运行: pip install qrcode pillow"
        print(f"{TAG} render_qr: {err}", file=sys.stderr)
        return {"png_path": None, "ascii_qr": None, "error": err}
python
def _require_requests() -> None:
    if requests is None:
        raise RuntimeError("缺少 requests 依赖,请运行: pip install requests")

Technical Analysis

When dependencies are absent, the application instructs users to install qrcode, pillow, and requests directly from the active pip index. The instructions do not specify exact versions, hashes, a lockfile, or a trusted package index.

Package resolution therefore depends on mutable repository state and local pip configuration. A compromised package release, malicious package-index mirror, or dependency-resolution attack could result in unreviewed code being installed and imported into the environment used by the Skill.

The script does not automatically execute pip, which reduces immediacy, but the runtime instruction establishes an unsafe and non-reproducible installation path.

Attack Path

  1. One or more required Python packages are missing.
  2. The script emits the installation instruction.
  3. The user runs the suggested unpinned pip install command.
  4. pip resolves packages from the user's configured index or mirror.
  5. A compromised package version or package source installs malicious code.
  6. The malicious component executes during installation or when imported by the onboarding script.

Impact Assessment

A compromised dependency can execute with the privileges of the user running pip or the Skill. It may acce ...[truncated 199 chars]

Remediation
View remediation

Remediation Suggestions

  • Provide a reviewed dependency manifest with exact version pins.
  • Generate and distribute cryptographic hashes for every direct and transitive dependency.
  • Recommend installation with pip install --require-hashes -r requirements.txt.
  • Document and enforce an approved HTTPS package index.
  • Use an isolated virtual environment rather than a shared system environment.
  • Regularly scan pinned dependencies for known vulnerabilities and update them through a controlled review process.
  • Package the Skill with its validated dependencies where the deployment model permits.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (19)

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The POST target URL is derived from environment-controlled base URLs, and this function sends sensitive authentication material such as access tokens, refresh tokens, user identifiers, and SMS-login data to that endpoint. In a skill environment, environment variables are often controllable by the host or deployment wrapper, so an attacker could redirect requests to an arbitrary server and exfiltrate credentials or user PII.

Content

Scanner excerpt · 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 request URL is also built from environment-controlled base configuration and is used with an Authorization header carrying the API key. If an attacker can influence the environment, they can redirect authenticated requests to an attacker-controlled endpoint and capture the API key, account metadata, and order-related data.

Content

Scanner excerpt · 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

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是图像/品牌视觉分析类技能,应处理商品图片、颜色、字体、平台、地区、语言等输入并输出 brandGeneJson。但代码中完全没有任何图像处理、品牌风格提取、视觉语言分析或 brandGeneJson 构造逻辑。相反,代码实现的是账户 onboarding 与商业支付流程:调用登录接口发送短信验证码,完成短信登录,获取团队/API token,读取账户与套餐信息,创建订单,渲染支付二维码,并查询订单状态。这不仅是主要目的完全不同,还涉及账号认证、令牌管理、订单支付和本地文件写入等未声明能力,因此属于明显的描述与行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明的核心功能是“提取”品牌基因并生成结构化结果,但代码的实际职责只是将已有 JSON 结果保存到会话目录,并维护少量会话元数据。虽然这可能是整个技能流水线中的一个辅助持久化步骤,但就所给代码块本身而言,其主行为与声明的主要目的存在明显偏差。代码没有模型调用、图像处理、参数解析与推断逻辑,也没有生成 brandGeneJson,只是接收并落盘现成 payload。因此应判定为描述与代码行为不匹配。

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 14)May include surrounding context.

md
证码后:`python scripts/onboarding.py login <phone> <code>`(workbuddy 宿主加 `--channel workbuddy`)
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `积分/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file implements SMS authentication, account onboarding, API-key retrieval, plan enumeration, ordering, and payment QR generation, which is materially unrelated to the declared brand-gene extraction purpose. This mismatch is dangerous because it hides credential collection and billing behavior inside a skill users would reasonably expect to process images and style parameters only.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Billing and payment-order creation are embedded in a skill that claims to extract brand visual style, creating hidden purchase capabilities unrelated to the advertised function. In context, this substantially increases risk because users or orchestration layers may invoke the skill expecting offline analysis, not actions that can initiate charges and produce payment artifacts.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

SMS login and API token issuance are high-risk account operations that are unrelated to brand-gene extraction and enable acquisition of long-lived credentials. In this skill context, the behavior is especially dangerous because it covertly expands from content processing into identity verification and credential harvesting.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill returns the API key in stdout JSON, which is commonly captured by logs, orchestration frameworks, transcripts, shell history, or calling agents. Exposing credentials this way can lead to immediate account compromise, unauthorized API use, and downstream leakage beyond the user’s control.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
79% confidence
Finding

The skill invokes environment-dependent behavior, writes files into session directories, and calls a downstream textgen component over a network/API path, yet it declares no explicit tool scope or allowed-tools boundary. Without least-privilege restrictions, the runtime may grant broader capabilities than required, increasing the blast radius if the skill or a downstream dependency is compromised or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The invocation list includes the phrase "品牌视觉", which is broad and can plausibly appear in ordinary discussion about branding rather than as an intentional request to run this specific skill. Although other examples are more specific, this phrase lacks scope constraints or negative examples to distinguish when the skill should or should not activate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file sets language to default to "英文" when the user does not provide a value. This imposes a specific language/locale behavior without offering user choice or documenting an opt-in, which conflicts with the language/locale policy constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The execution steps direct the skill to fill missing language with "英文" automatically. This is a natural-language locale policy issue because the workflow mandates a specific language choice without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The error-handling section states that when brandKey is empty, all fields are default-filled including language=英文. This repeats and operationalizes a forced language default, making the locale policy violation part of the documented behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The onboarding flow instructs operators to collect a user's phone number and use it for registration, but it provides no privacy notice, consent guidance, retention limits, or handling safeguards. In an agent skill context, this increases the risk of unnecessary collection, disclosure, or insecure handling of personal data by downstream operators or logs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file instructs users to persist an API key in shell startup files and environment variables without warning that these locations may be readable by other local users, inherited by subprocesses, exposed in shell history, or accidentally committed via dotfile syncing. This creates a realistic secret-handling weakness even though the goal is legitimate configuration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code writes payment QR images to disk in a predictable session directory without an in-file warning or cleanup guarantees. While not as severe as credential leakage, this can leave sensitive payment artifacts on shared systems or accessible workspaces, exposing transaction links and user purchasing activity.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · 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 = ""

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This Python file contains user- or maintainer-facing natural-language text exclusively in Chinese, including the module docstring and inline explanatory comments. Under the stated policy, forcing a specific language without opt-in can be a locale/language policy violation when no alternative language choice or justification is provided.

Content

No source excerpt is available for this finding.