Back to skill

Security audit

小红书内容引擎

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed Xiaohongshu content analysis and generation workflow, with real privacy and cost considerations around configured external services.

Install only if you are comfortable sending XHS links, prompts, brand context, and generated media requests to your configured crawler, Ofox/OpenRouter, and Ark providers. Keep .env files and BASE_URL settings under your control, avoid untrusted custom endpoints, review generated reports for sensitive prompt content, and do not use --no-confirm unless you intentionally want paid Seedance jobs to start without the countdown.

Vulnerability Patterns
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (18)

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

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            data = json.loads(resp.read())
    except urllib.error.HTTPError as e:
        err_body = e.read().decode("utf-8", errors="replace")[:500]
Confidence
94% confidence
Finding
The request target is derived from a configurable base URL that can come from the environment, and the code sends both the full prompt and bearer token to that endpoint without validating or allowlisting the destination. If an attacker can influence OFOX_BASE_URL or the base_url parameter, they can redirect requests to an arbitrary server and exfiltrate prompts and API credentials, which is especially sensitive in a content-generation skill that may handle proprietary brand assets and internal strategy.

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

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            data = json.loads(resp.read())
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")[:500]
Confidence
97% confidence
Finding
The request destination is derived from `base_url`, which can come from the `ARK_BASE_URL` environment variable, and the request includes the Bearer API key in the `Authorization` header. If an attacker can influence environment variables or call this function with a custom `base_url`, they can redirect requests to an arbitrary host and exfiltrate the Ark credential or proxy sensitive prompts/tasks to an untrusted endpoint. In an agent skill context, this is more dangerous because skills often run with ambient secrets and network access.

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

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")[:500]
Confidence
97% confidence
Finding
This query path has the same issue as submission: `base_url` is attacker-controllable via environment or function parameter, while the request carries the API key in the `Authorization` header. A malicious endpoint could harvest the secret and also return crafted task metadata that misleads downstream logic. In this skill, shared graph/workflow automation increases the blast radius because compromised polling can affect later automated steps.

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

Critical
Category
Data Flow
Content
out_path.parent.mkdir(parents=True, exist_ok=True)
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "curl/8.7.1"})
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            out_path.write_bytes(resp.read())
    except urllib.error.HTTPError as e:
        raise SeedanceError(f"HTTP {e.code} downloading video from {url[:80]}") from e
Confidence
89% confidence
Finding
`download_video` fetches an arbitrary URL returned by the remote API without validating the scheme, host, or destination network range. If the upstream service is compromised, misconfigured, or replaced via the earlier `base_url` issue, this becomes an SSRF-style primitive that can make the agent connect to internal services or download unexpected content to disk. The skill context makes this more relevant because it automatically downloads remote artifacts immediately after generation.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The client permits the base URL, endpoint paths, auth header, and even absolute endpoint URLs to be fully overridden from environment or `.env` sources. In an agent setting, this enables SSRF-like arbitrary outbound requests and can cause the client to send its bearer token to attacker-controlled hosts if configuration is poisoned.

Vague Triggers

Medium
Confidence
86% confidence
Finding
The trigger phrases include broad everyday requests such as '研究一下' or '分析一下这条为什么火', which can cause the skill to activate in contexts where the user did not intend network scraping, local file writes, or external API usage. Because this skill performs shell commands, downloads remote media, and may incur paid API calls in later modes, accidental invocation has meaningful privacy and cost consequences.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The generate-mode examples are also broad and can map normal brainstorming requests onto a workflow that fetches external content, reads graph state, writes files, and potentially calls paid image/video providers. In this context, unintended activation is more dangerous because generate mode can trigger downstream LLM, image, and Seedance actions with cost and data-exposure implications.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The client transmits arbitrary prompt content and the bearer API key to a third-party endpoint without any in-code user-facing notice, consent gate, or data classification check. In this skill’s context, prompts may contain brand strategy, unpublished campaign content, or other sensitive business data, so silent outbound transfer increases confidentiality and compliance risk even if HTTPS is used.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The code automatically reads credentials from environment variables and multiple .env locations without explicit user disclosure or scope restriction. While this is common implementation behavior, in an agent skill it can surprise users and expand trust boundaries by silently consuming secrets from the current working directory or shared config paths.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
When no existing card is found, the function automatically triggers `extract_xhs.py` and writes files without an explicit confirmation step at the decision point. In an agent setting, this can cause unintended network access, scraping, local file creation, and external side effects from a simple lookup-style request, which is especially risky because the skill is designed to process untrusted user-supplied links.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
Using ffmpeg with -y forces overwrite of existing files in the output path without confirmation. If an attacker can influence video_path/outdir or if the directory already contains valuable files, this can silently destroy or replace data, making the issue more relevant in an automation pipeline that processes many jobs.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The partial report writes full failed-shot prompts, task IDs, local file paths, and error details to a markdown file without any redaction or user warning. In this skill context, prompts may contain proprietary campaign strategy, brand instructions, unpublished creative concepts, or sensitive API/provider error details, so persisting them to disk can create unintended disclosure through logs, shared workspaces, backups, or downstream sync tools.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- 顺序提交到火山方舟 Seedance 2.0(异步任务 + 轮询,单 shot 通常 1-3 分钟)
- 失败的 shot 不阻断其他 shot,只在 `partial-video.md` 里写明哪几个失败 + 失败 shot 的 prompt 方便手补
- 成功的 shot 用 ffmpeg concat 拼成 `final-video.mp4`
- 开关:`--no-real-video`(仅出 prompt 不调 API)/ `--async`(仅提交不等结果)/ `--no-confirm`(跳过 3 秒倒数)

### Step 8:质检 validator(v0.2.1 起内置)
- **硬错** → 自动重跑相应步骤(最多 1 次):禁忌词命中 / 文件为空 / tags < 5 / 图片过小(疑似生成失败)
Confidence
81% confidence
Finding
The documented '--no-confirm' switch removes the user interruption window before submitting paid Seedance video jobs, and the workflow also permits automatic retries in validation. In a skill that can invoke external paid APIs and process user or brand data, reducing confirmation around autonomous actions increases the risk of unwanted spending and unintended data transfer.

Credential Access

High
Category
Privilege Escalation
Content
# Token 自动查找路径(按优先级,第一个找到即用)
_TOKEN_SEARCH_PATHS = [
    lambda: Path.cwd() / ".env",                # 1. 当前工作目录
    lambda: _xdg_config_dir() / ".env",         # 2. XDG 标准位置
    lambda: _skill_root_dir() / ".env",         # 3. Skill 根目录
]
Confidence
84% confidence
Finding
The client searches for secrets in `Path.cwd()/.env`, XDG config, and the skill root, which broadens the trust boundary and may pick up attacker-planted `.env` files from the working directory or repository. Combined with configurable outbound destinations, this can leak tokens or cause the client to authenticate to untrusted endpoints.

Credential Access

High
Category
Privilege Escalation
Content
_TOKEN_SEARCH_PATHS = [
    lambda: Path.cwd() / ".env",                # 1. 当前工作目录
    lambda: _xdg_config_dir() / ".env",         # 2. XDG 标准位置
    lambda: _skill_root_dir() / ".env",         # 3. Skill 根目录
]
Confidence
79% confidence
Finding
Searching the skill root for `.env` causes the code to trust repository-local secrets/configuration, which is risky in shared, cloned, or agent-managed environments where project files may be modified. This increases the chance of credential misuse or configuration poisoning, especially because request destinations and auth behavior are also overrideable.

Credential Access

High
Category
Privilege Escalation
Content
fix=(
            "v2 生成模式需要 Ofox API key(聚合 LLM + Nano Banana 出图):\n"
            "  1) 注册:https://ofox.ai\n"
            "  2) 在 .env 加:OFOX_API_KEY=ofox-...\n"
            "  3) 兼容:OPENROUTER_API_KEY 也会被识别"
        ),
    )
Confidence
83% confidence
Finding
This preflight code loads an API key and displays a masked portion of it to the user. Although partially masked, exposing secret fragments in logs or terminal output can aid secret correlation, screenshot leakage, and operational disclosure, especially in shared CI logs or multi-user environments.

Credential Access

High
Category
Privilege Escalation
Content
"真生视频需要火山方舟 API key(Seedance 2.0):\n"
            "  1) 注册:https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey\n"
            "  2) ⚠️ 不要用 IAM AK/SK(两者格式都是 UUID 但不通用)\n"
            "  3) 在 .env 加:ARK_API_KEY=...\n"
            "  4) 在「开通管理 → 视觉模型」开通 Doubao-Seedance-2.0-fast"
        ),
    )
Confidence
83% confidence
Finding
The associated credential check for ARK also loads the secret and emits a masked token value. Even partial secret disclosure is unnecessary and increases exposure risk if logs are collected, shared, or retained.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
- 顺序提交到火山方舟 Seedance 2.0(异步任务 + 轮询,单 shot 通常 1-3 分钟)
- 失败的 shot 不阻断其他 shot,只在 `partial-video.md` 里写明哪几个失败 + 失败 shot 的 prompt 方便手补
- 成功的 shot 用 ffmpeg concat 拼成 `final-video.mp4`
- 开关:`--no-real-video`(仅出 prompt 不调 API)/ `--async`(仅提交不等结果)/ `--no-confirm`(跳过 3 秒倒数)

### Step 8:质检 validator(v0.2.1 起内置)
- **硬错** → 自动重跑相应步骤(最多 1 次):禁忌词命中 / 文件为空 / tags < 5 / 图片过小(疑似生成失败)
Confidence
84% confidence
Finding
Allowing '--no-confirm' in a workflow that invokes external tooling and paid APIs is a form of parameter abuse risk: a caller can suppress a safety interlock designed to prevent unintended job submission. The danger is amplified here because the skill can launch multi-step media generation and ffmpeg processing with real cost and external data handling.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/configuration.md:41

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:555