Back to skill

Security audit

Catfee飞书群聊总结

Security checks for vulnerabilities and agentic risk

Overview

The skill does summarize Feishu group chats, but it also exports identifiable chat logs and uses an external helper in a way that can expose extra secrets.

Install only if you are comfortable granting Feishu message-read and document-create permissions, exporting identifiable group-chat content, and relying on a locally installed feishu-docs helper. Run it with narrowly scoped Feishu credentials, a clean minimal environment, and a trusted working directory; review generated documents and any local backup files for sensitive content.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/summarize.py:265
Finding

PATH-Resolved External Tool Receives Feishu Credentials and the Full Process Environment

Content
View full analysis

Vulnerability Details

File Location: scripts/summarize.py, lines 265-269 and 293-297
Vulnerability Type: PATH-based executable hijacking and excessive environment disclosure
Risk Level: Medium

Vulnerable Code

python
result = subprocess.run(
    ["feishu-docs", "create", title, "--auth", "tenant"],
    capture_output=True, text=True, timeout=30,
    env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}
)
python
update_result = subprocess.run(
    ["feishu-docs", "update", doc_id, "--auth", "tenant", "--body", tmp_md],
    capture_output=True, text=True, timeout=60,
    env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}
)

Technical Analysis

The code invokes feishu-docs by name rather than through a verified absolute path. The operating system therefore resolves the executable using the invoking process's PATH. If an attacker can place a malicious executable named feishu-docs earlier in that search path, the malicious program will run with the privileges of the user executing the Skill.

Both invocations explicitly pass a copy of the entire process environment to the external executable. This includes FEISHU_APP_ID, FEISHU_APP_SECRET, and any unrelated credentials or tokens inherited by the Python process. During the update invocation, the external process also receives the path to the temporary file containing the complete chat transcript.

Although using an external Feishu document client is consistent with the declared document-creation feature, resolving an unpinned executable through PATH and exposing the entire environment exceed the minimum privileges required for that operation.

Attack Path

  1. An attacker obtains the ability to write to a directory that appears before the legitimate client in the victim's PATH.
  2. The attacker creates a malicious executable named feishu-docs in that directory.

...[truncated 1259 chars]

Remediation
View remediation

Remediation Suggestions

  1. Resolve the expected executable once from a trusted installation location and invoke it through an absolute path.
  2. Pin the supported feishu-docs version and document installation from an authenticated official source.
  3. Where feasible, verify the executable's ownership, permissions, and cryptographic digest before execution.
  4. Replace the inherited environment with a minimal allowlist. Pass only variables strictly required by the client, such as the Feishu credentials and a controlled runtime PATH.
  5. Avoid passing unrelated environment variables to child processes.
  6. Prefer direct use of the official Feishu document API from the existing Python process, removing the additional executable trust boundary.
  7. Run the Skill under a dedicated, minimally privileged account and use narrowly scoped Feishu application permissions.
  8. Store application secrets in a dedicated secret manager where available and rotate them if an untrusted feishu-docs executable may have run.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/summarize.py:257
Finding

Complete Chat Transcripts Are Written to Predictable and Insufficiently Protected Local Files

Content
View full analysis

Vulnerability Details

File Location: scripts/summarize.py, lines 257-261 and 382-387
Vulnerability Type: Unsafe temporary file handling and plaintext sensitive-data retention
Risk Level: Medium

Vulnerable Code

python
# 写入临时 markdown 文件
tmp_md = "tmp_chat_summary.md"
with open(tmp_md, "w", encoding="utf-8") as f:
    f.write(content_md)
python
# 备份到本地文件
backup_file = f"chat_summary_{datetime.now().strftime('%Y%m%d%H%M%S')}.md"
with open(backup_file, "w", encoding="utf-8") as f:
    f.write(full_content)
print(f"已备份到本地: {backup_file}")

Technical Analysis

The complete chat transcript is initially written to the fixed relative filename tmp_chat_summary.md. Opening the file with mode "w" follows symbolic links and truncates an existing target. The file is created using permissions derived from the process umask rather than an explicitly restrictive mode.

The finally block normally deletes this file, but it cannot guarantee cleanup after abrupt termination, process crashes, forced termination, or system failure. As a result, a plaintext transcript may remain in the working directory.

If Feishu document creation fails, the program automatically creates another plaintext file whose name is based on the current timestamp. This backup contains sender identities, user IDs, timestamps, summary data, and message content. It is created without explicit user consent, exclusive creation, restrictive permissions, encryption, or a retention policy. This fallback behavior is also not documented in SKILL.md.

Attack Path

Symbolic-link overwrite scenario:

  1. An attacker with write access to the working directory creates tmp_chat_summary.md as a symbolic link to another file writable by the victim.
  2. The victim runs the Skill from that directory.
  3. open(tmp_md, "w") follows the symbolic link and truncates the linked target.
  4. The Skill writes the generated cha ...[truncated 1216 chars]
Remediation
View remediation

Remediation Suggestions

  1. Create temporary files using tempfile.NamedTemporaryFile or tempfile.mkstemp in a trusted temporary directory.
  2. Use unpredictable filenames, exclusive creation, and file permissions restricted to the current user, such as mode 0600.
  3. Ensure the selected temporary-file API prevents symlink races and pre-existing-file replacement.
  4. Continue cleanup in a finally block, while recognizing that secure temporary storage is still required for abnormal termination.
  5. Avoid writing the full transcript to disk where the document API can accept in-memory content or a protected stream.
  6. Do not create a persistent fallback transcript automatically. Require explicit user consent before storing it.
  7. If a backup is requested, use a user-selected protected directory, exclusive creation, restrictive permissions, and a documented retention period.
  8. Clearly document local storage, cleanup behavior, transcript sensitivity, and failure-mode retention in SKILL.md.
  9. Consider data minimization options, such as generating only aggregate statistics or redacting sender IDs and message content unless a full transcript is explicitly requested.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Tainted flow: 'APP_ID' from os.environ.get (line 18, credential/environment) → requests.post (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/summarize.py (reported line 33)May include surrounding context.

python
def get_token() -> str:
    resp = requests.post(AUTH_URL, json={
        "app_id": APP_ID,
        "app_secret": APP_SECRET
    })

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The description says the skill pulls group chat messages, generates complete records with sender ID, nickname, timestamp, and content, and creates a Feishu document, but it does not prominently warn users that this involves bulk access to potentially sensitive personal and organizational communications. Without a clear privacy warning and consent boundary, users may invoke it without understanding that identifiable chat logs will be copied into a persistent document, increasing the risk of privacy breaches and over-collection.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
93% confidence
Finding

Passing {**os.environ, ...} to a child process exposes the entire environment to that process, not just the Feishu credentials. In an agent-skill setting, environment variables frequently contain API keys, tokens, and infrastructure secrets, so this broad inheritance materially increases the chance of secret disclosure if the external executable is untrusted, swapped, or logs its environment.

Content

Scanner excerpt · scripts/summarize.py (reported line 269)May include surrounding context.

python
result = subprocess.run(
            ["feishu-docs", "create", title, "--auth", "tenant"],
            capture_output=True, text=True, timeout=30,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}
        )
        
        if result.returncode != 0:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
93% confidence
Finding

This second env handoff repeats the same high-risk secret exposure pattern during document update. Because the script already handles chat data and auth material, giving a subprocess all ambient environment state makes the skill context more dangerous by combining sensitive content processing with excessive secret sharing.

Content

Scanner excerpt · scripts/summarize.py (reported line 298)May include surrounding context.

python
update_result = subprocess.run(
            ["feishu-docs", "update", doc_id, "--auth", "tenant", "--body", tmp_md],
            capture_output=True, text=True, timeout=60,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}
        )
        
        if update_result.returncode != 0:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases include broad everyday language such as '最近一个月' and '帮我看看这几天', which can match ordinary conversation and unintentionally activate a skill that reads group chat history. In this context, accidental activation is more dangerous because the skill accesses private chat messages and can export identifiable records into a document.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring presents this as a 'Feishu group chat summary script' with usage centered on summarization. However, later code persists the collected chat content by creating a remote Feishu document via CLI and, on failure, writing a local markdown backup, which are material side effects not reflected in the documentation.

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/summarize.py (reported line 33)May include surrounding context.

python
def get_token() -> str:
    resp = requests.post(AUTH_URL, json={
        "app_id": APP_ID,
        "app_secret": APP_SECRET
    })

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Because no manifest is available, the only stated intent comes from the script naming and documentation, which emphasize summarizing chat content. Spawning an external 'feishu-docs' command with inherited environment and credentials adds a separate execution capability beyond straightforward summarization and remote API reads.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script collects chat content and republishes it into another Feishu document without explicit consent, warning, or data-minimization controls. In practice this can expose sensitive conversation data to a different audience, retention model, or sharing configuration than the original chat.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/summarize.py (reported line 266)May include surrounding context.

python
try:
        # 调用 feishu-docs CLI 创建文档
        result = subprocess.run(
            ["feishu-docs", "create", title, "--auth", "tenant"],
            capture_output=True, text=True, timeout=30,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}

Tainted flow: 'APP_ID' from os.environ.get (line 18, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
89% confidence
Finding

The code passes the full parent environment into an external CLI subprocess, including all ambient secrets, and explicitly re-injects Feishu credentials. If the feishu-docs binary is malicious, compromised, or replaced via PATH hijacking, it can read and exfiltrate far more environment data than needed.

Content

Scanner excerpt · scripts/summarize.py (reported line 266)May include surrounding context.

python
try:
        # 调用 feishu-docs CLI 创建文档
        result = subprocess.run(
            ["feishu-docs", "create", title, "--auth", "tenant"],
            capture_output=True, text=True, timeout=30,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/summarize.py (reported line 295)May include surrounding context.

python
doc_url = f"https://feishu.cn/docx/{doc_id}"
        
        # 更新文档内容
        update_result = subprocess.run(
            ["feishu-docs", "update", doc_id, "--auth", "tenant", "--body", tmp_md],
            capture_output=True, text=True, timeout=60,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}

Tainted flow: 'APP_ID' from os.environ.get (line 18, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
89% confidence
Finding

This second subprocess call repeats the same unsafe pattern of handing a child process the entire inherited environment plus credentials. In a skill context that processes chat data and secrets, broad environment inheritance increases blast radius if the external tool is untrusted or compromised.

Content

Scanner excerpt · scripts/summarize.py (reported line 295)May include surrounding context.

python
doc_url = f"https://feishu.cn/docx/{doc_id}"
        
        # 更新文档内容
        update_result = subprocess.run(
            ["feishu-docs", "update", doc_id, "--auth", "tenant", "--body", tmp_md],
            capture_output=True, text=True, timeout=60,
            env={**os.environ, "FEISHU_APP_ID": APP_ID, "FEISHU_APP_SECRET": APP_SECRET}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

On failure, the script writes full chat records to a local markdown file automatically, creating an unannounced persistence channel for potentially sensitive data. Local filesystem storage can broaden access to the transcript, bypass expected chat retention controls, and leave recoverable artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script’s natural-language interface, usage text, and operational messages are entirely in Chinese, which effectively fixes the user interaction language without any opt-in or alternative locale support. Under the language/locale policy, this can be a violation when the skill does not offer users a choice or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.