Back to skill

Security audit

Multi Writing Skills Main

Security checks for vulnerabilities and agentic risk

Overview

The skill’s publishing and AI features are coherent, but it handles session cookies/API keys and can send or publish user content with weak disclosure and unsafe credential handling.

Review before installing. Use only with content you are willing to send to the configured publishing and AI services, avoid passing cookies or API keys directly on the command line, prefer isolated/limited accounts or environment variables, and verify whether Zhihu/Toutiao operations create drafts or public posts before using them on real accounts.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
src/multi_writing_skills/config.py:13
Finding

Automatic Overbroad Reading of a Shared Credential File

Content
View full analysis
bool: """检测是否在 openclaw 环境中运行""" openclaw_dir = Path.home() / ".openclaw" return openclaw_dir.exists() and openclaw_dir.is_dir() def load_openclaw_env() -> dict[str, str]: """从 ~/.openclaw/.env 加载环境变量""" env_file = Path.home() / ".openclaw" / ".env" env_vars = {} if env_file.exists(): with open(env_file, encoding="utf-8") as f: for line in f: line = line.strip() if line and not line.startswith("#"): if "=" in line: key, value = line.split("=", 1) env_vars[key.strip()] = value.strip() return env_vars ``` ```python def load(self) -> None: """从文件和环境变量加载配置""" # 如果在 openclaw 环境中,先加载 ~/.openclaw/.env openclaw_env = {} if is_openclaw_env(): openclaw_env = load_openclaw_env() ``` ```python @app.callback() def main() -> None: """初始化""" init_registry() ``` The callback invokes `init_registry()`, which calls `settings.load()`. Consequently, ordinary CLI commands trigger the credential-file access rather than only commands that require credentials. ### Technical Analysis The application automatically detects whether `~/.openclaw` exists and, if so, parses every assignment in `~/.openclaw/.env` into a dictionary. Only a limited set of values—such as `WECHAT_APP_SECRET`, `ZHIHU_COOKIE`, `TOUTIAO_COOKIE`, and `AI_API_KEY`—is needed for the declared publishing and AI features, but the loader reads and retains all entries in the shared file. This violates least-privilege and data-minimization principles. A shared OpenClaw environment file may conta ...[truncated 1620 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/multi_writing_skills/config.py:153
Finding

Plaintext Credential Storage and Command-Line Secret Exposure

Content
View full analysis
None: """保存配置到文件""" self.config_dir.mkdir(parents=True, exist_ok=True) config_file = self.get_config_file() data = { "wechat": self.wechat.model_dump(), "zhihu": self.zhihu.model_dump(), "toutiao": self.toutiao.model_dump(), "ai": self.ai.model_dump(), "api_endpoint": self.api_endpoint, "default_theme": self.default_theme, } with open(config_file, "w", encoding="utf-8") as f: yaml.dump(data, f, allow_unicode=True, default_flow_style=False) ``` The CLI accepts the secret as an ordinary positional argument and then persists it: ```python @config_app.command("set") def config_set( key: str = typer.Argument(..., help="配置键,格式: section.key"), value: str = typer.Argument(..., help="配置值"), ) -> None: ``` Examples of sensitive assignments include: ```python if section == "wechat": if subkey == "app_id": settings.wechat.app_id = value elif subkey == "app_secret": settings.wechat.app_secret = value ``` ```python elif section == "zhihu": if subkey == "cookie": settings.zhihu.cookie = value ``` ```python elif section == "toutiao": if subkey == "cookie": settings.toutiao.cookie = value ``` ```python elif section == "ai": if subkey == "provider": settings.ai.provider = value elif subkey == "api_key": settings.ai.api_key = value ``` The command concludes by writing the resulting configuration: ```python settings.save() console.print(f"[green]已设置 {key}[/green]") ``` ### Technical Analysis `Settings.save()` serializes complete Pydantic configuration objects directly to Y ...[truncated 2600 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (91)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/multi_writing_skills/config.py (reported line 21)May include surrounding context.

python
def load_openclaw_env() -> dict[str, str]:
    """从 ~/.openclaw/.env 加载环境变量"""
    env_file = Path.home() / ".openclaw" / ".env"
    env_vars = {}
    if env_file.exists():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/multi_writing_skills/config.py (reported line 91)May include surrounding context.

python
def load_openclaw_env() -> dict[str, str]:
    """从 ~/.openclaw/.env 加载环境变量"""
    env_file = Path.home() / ".openclaw" / ".env"
    env_vars = {}
    if env_file.exists():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/multi_writing_skills/config.py (reported line 22)May include surrounding context.

python
def load_openclaw_env() -> dict[str, str]:
    """从 ~/.openclaw/.env 加载环境变量"""
    env_file = Path.home() / ".openclaw" / ".env"
    env_vars = {}
    if env_file.exists():
        with open(env_file, encoding="utf-8") as f:

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 · src/multi_writing_skills/converter/css_theme.py (reported line 47)May include surrounding context.

python
if properties:
            rules.append(CSSRule(selector=selector, properties=properties))

    return rules


def css_to_inline_style(rules: list[CSSRule]) -> Dict[str, str]:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Most of the substantive guidance in this file is written in Chinese, including the project overview, command comments, architecture descriptions, and design patterns. This imposes a specific language on users or agents without any opt-in or justification that the skill is intended only for a Chinese-language context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documentation promotes automatic image upload and multi-platform publishing without clearly warning that article content and media will be transmitted to third-party services. Users may unknowingly send proprietary, private, or regulated content to external platforms or AI/image providers, creating confidentiality and compliance risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to copy Zhihu and Toutiao browser cookies for authentication, which are sensitive session credentials that can grant account access if mishandled. Omitting warnings about secure storage, limited sharing, rotation, and the risks of reusing active session cookies increases the chance of credential leakage and account compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises publishing to WeChat, Zhihu, Toutiao, and use of AI/image services, but it does not warn that content may be transmitted to third-party platforms or that drafts/posts could affect linked accounts. This lack of disclosure is risky because users may unknowingly send sensitive content externally or trigger actions with account and privacy consequences.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill declares broad auto-trigger conditions based on generic natural-language requests such as publishing, converting, writing, and image generation. In an agent environment, this can cause unintended invocation for loosely related prompts, increasing the chance of accidental external actions or data handling without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The config set command accepts secrets such as wechat.app_secret, zhihu.cookie, toutiao.cookie, and ai.api_key directly as positional CLI arguments. This exposes sensitive values to shell history, process listings, and potentially terminal logs, which can lead to credential theft on shared or monitored systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

When draft publishing is enabled in convert, the tool sends generated article content and metadata to external publishing platforms without an explicit warning or confirmation. Users may unintentionally transmit confidential, proprietary, or regulated content to third parties, especially when using multi-platform publishing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The publish command reads HTML from a local file and uploads it to external platforms with no explicit privacy/safety prompt. This can cause accidental disclosure of sensitive embedded data, links, tracking pixels, or internal content because the action is a direct exfiltration path to third-party services.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The write, rewrite, and humanize flows send user prompts or full article contents to external AI providers, but the CLI does not clearly disclose this data transfer at the point of use. For rewrite/humanize in particular, users may submit sensitive drafts or internal documents and unknowingly expose them to third-party APIs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The image generation command sends prompts to external providers and may subsequently download data from a returned remote URL without warning the user. This creates both a privacy issue for prompt disclosure and a trust boundary issue where the tool fetches unverified remote content that could be unexpected, large, or maliciously controlled.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The save() method serializes sensitive values including API keys, app secrets, and platform cookies directly into a YAML file under the user's home directory. Storing long-lived credentials on disk without permission checks, encryption, or a clear warning increases the risk of credential disclosure through local compromise, backups, or accidental sharing of the config directory.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · src/multi_writing_skills/converter/__init__.py (reported line 41)May include surrounding context.

python
"""Markdown 转换器"""

    # mdnice API 端点
    MDNICE_API = "https://api.mdnice.com/api/v1/markdown"

    def __init__(self, options: Optional[ConvertOptions] = None) -> None:
        self.options = options or ConvertOptions()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

When use_api is enabled, the converter sends the full markdown content to a remote endpoint, which may include sensitive unpublished text, embedded secrets, or internal URLs. There is no built-in disclosure, consent flow, allowlist, or restriction on custom api_endpoint values, so users may unknowingly exfiltrate content to a third party or attacker-controlled service.

Content

No source excerpt is available for this finding.

Ssd 1

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The optional user-controlled prompt fully replaces the default conversion instructions, allowing callers to redirect the model to perform arbitrary tasks or produce unsafe output instead of constrained Markdown-to-HTML conversion. In this context, that weakens policy boundaries and can amplify prompt injection or data exfiltration behaviors when combined with remote model calls.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This code posts user content to the OpenAI API endpoint, which is an external network transmission of potentially sensitive data. In a content-conversion skill, that is security-relevant because users may not expect their Markdown to leave the local environment or be processed by a third party.

Content

Scanner excerpt · src/multi_writing_skills/converter/ai.py (reported line 72)May include surrounding context.

python
async def _call_openai(self, system_prompt: str, user_content: str) -> str:
        """调用 OpenAI API"""
        base_url = self.config.base_url or "https://api.openai.com/v1"

        response = await self._client.post(
            f"{base_url}/chat/completions",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code sends full user-supplied Markdown and prompts to third-party AI providers without any disclosure, consent, minimization, or redaction controls in this execution path. If the Markdown contains sensitive, proprietary, or personal data, it will be externally transmitted by design, creating a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This path sends user-provided content to Anthropic's external API, exposing any embedded secrets or sensitive text to a third-party service. The skill context does not mitigate the risk, because Markdown documents commonly contain internal notes, tokens, customer data, or unpublished material.

Content

Scanner excerpt · src/multi_writing_skills/converter/ai.py (reported line 97)May include surrounding context.

python
async def _call_anthropic(self, system_prompt: str, user_content: str) -> str:
        """调用 Anthropic API"""
        response = await self._client.post(
            "https://api.anthropic.com/v1/messages",
            headers={
                "x-api-key": self.config.api_key,
                "anthropic-version": "2023-06-01",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The converter sends the full markdown content, title, and theme to a configurable external HTTP endpoint, which can expose potentially sensitive user-authored content to third-party services. In a skill/library context, this is risky because the transmission happens as a normal implementation detail without any explicit consent flow, privacy warning, endpoint allowlisting, or data classification controls.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The presence of a built-in third-party endpoint indicates that user content may be transmitted off-system to an external service. In this file, that risk is real because the convert method posts markdown and title directly to the selected endpoint, so sensitive content could leave the trust boundary when the preset is used.

Content

Scanner excerpt · src/multi_writing_skills/converter/api.py (reported line 88)May include surrounding context.

python
# 预设的 API 端点
BUILTIN_ENDPOINTS = {
    "mdnice": "https://api.mdnice.com/api/v1/markdown",
    "wechat": "https://api.weixin.qq.com/cgi-bin/media/upload",  # 示例
}

External Transmission

Medium
Category
Data Exfiltration
Confidence
78% confidence
Finding

This preset similarly enables sending content to an external WeChat API endpoint, creating the same trust-boundary crossing and potential data exposure concerns. Although the comment says it is an example, shipping it as a built-in endpoint can still encourage use without adequate review of what data is disclosed and whether credentials or content handling are appropriate.

Content

Scanner excerpt · src/multi_writing_skills/converter/api.py (reported line 89)May include surrounding context.

python
# 预设的 API 端点
BUILTIN_ENDPOINTS = {
    "mdnice": "https://api.mdnice.com/api/v1/markdown",
    "wechat": "https://api.weixin.qq.com/cgi-bin/media/upload",  # 示例
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The function accepts arbitrary http:// and https:// URLs and fetches them server-side, which can enable SSRF-style behavior if untrusted input controls css_path. In a skill/converter context this is more dangerous because theme-loading may be exposed as a convenience feature and could be triggered against internal services or used for unwanted outbound network access.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.