WeChat Article Parser - 微信公众号文章解析

Security checks across malware telemetry and agentic risk

Overview

The parser is mostly ordinary, but its Feishu save helper can automatically change table fields and delete existing rows without clear disclosure or confirmation.

Review save_to_feishu.py before installing. Use a dedicated Feishu app and a backed-up or disposable table, and disable the automatic empty-row cleanup unless you explicitly want the skill to read and delete records in the configured table.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"--max-chars", "5000"
        ]
        
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
86% confidence
Finding
result = subprocess.run( cmd, capture_output=True, text=True, timeout=30 )

Tainted flow: 'api_url' from os.getenv (line 360, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
"fields": fields
    }
    
    response = requests.post(api_url, headers=headers, json=data)
    result = response.json()
    
    if result.get("code") == 0:
Confidence
90% confidence
Finding
response = requests.post(api_url, headers=headers, json=data)

Tainted flow: 'api_url' from os.getenv (line 360, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
created_count = 0
    for field_name, field_def in required_fields.items():
        if field_name not in existing:
            response = requests.post(api_url, headers=headers, json=field_def)
            result = response.json()
            if result.get("code") == 0:
                created_count += 1
Confidence
84% confidence
Finding
response = requests.post(api_url, headers=headers, json=field_def)

Tainted flow: 'api_url' from os.getenv (line 360, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
if page_token:
                params["page_token"] = page_token

            response = requests.get(api_url, headers=headers, params=params)
            result = response.json()

            if result.get("code") != 0:
Confidence
88% confidence
Finding
response = requests.get(api_url, headers=headers, params=params)

Tainted flow: 'delete_url' from os.getenv (line 287, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
# 飞书批量删除最多500条
            for i in range(0, len(empty_ids), 500):
                batch = empty_ids[i:i+500]
                response = requests.post(delete_url, headers=delete_headers, json={"records": batch})
                delete_result = response.json()
                if delete_result.get("code") == 0:
                    print(f"   🗑️  批量删除 {len(batch)} 个空白行")
Confidence
95% confidence
Finding
response = requests.post(delete_url, headers=delete_headers, json={"records": batch})

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill documentation advertises capabilities that imply environment access, file writes, network access, and shell execution, yet it declares no permissions. This creates a transparency and governance gap: users and the platform may not realize the skill can fetch remote content, read secrets from .env, write local files, and invoke scripts, increasing the chance of unintended data access or execution.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
A description-behavior mismatch is a real security concern because users may consent to a narrow WeChat parsing tool while the implementation also handles other platforms, writes local files, manipulates Feishu tables, and deletes records. Hidden or under-disclosed behaviors increase the risk of unexpected data exfiltration, destructive actions, and overbroad trust in the skill.

Description-Behavior Mismatch

Medium
Confidence
81% confidence
Finding
The skill advertises itself as a WeChat article parser, but the code handles multiple unrelated content platforms. This scope expansion is a trust and safety issue because users may grant permissions or invoke the skill expecting narrower behavior than what is actually implemented.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The implementation includes schema management and record deletion capabilities that are not directly necessary for 'parse article and optionally save' behavior. In context, this extra capability materially increases the blast radius from content-saving into broader modification of the user's Feishu data.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill description says saving to Feishu is optional, but this function's normal flow automatically obtains credentials, ensures fields, cleans rows, and writes records once invoked. That mismatch is dangerous because it obscures side effects and may cause users to trigger external writes and deletions unintentionally.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The script implements local file-writing via save_to_file() and exposes it through CLI flags, while the stated skill scope only mentions optional saving to Feishu tables. This expands the data-handling surface beyond the declared behavior, which can surprise users, create unintended local persistence of scraped content, and increase the risk of sensitive data being stored on disk without appropriate disclosure or controls.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill tells users it can save parsed article data locally and to Feishu but does not clearly warn that content will persist beyond the current session and may be transmitted to a third-party service. This undermines informed consent and can expose sensitive article contents, notes, or metadata to unintended storage locations.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The auto-invocation wording suggests that merely sending a link will trigger remote fetching and possibly downstream storage actions without an explicit warning. In conversational systems, this can lead users to disclose URLs or content they did not intend to have fetched, processed, or retained.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The Feishu save instructions focus on configuration and usage but omit a clear warning that parsed article content and metadata will be sent to Feishu and stored in a third-party system. This matters because users may assume processing is local when it actually results in external transmission and retention.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The function sends fetched article content and metadata to Feishu without any explicit user-facing warning or confirmation at the point of transmission. In a content-parsing skill, silent third-party upload is a meaningful privacy and consent issue, especially when full article bodies are included.

External Transmission

Medium
Category
Data Exfiltration
Content
created_count = 0
    for field_name, field_def in required_fields.items():
        if field_name not in existing:
            response = requests.post(api_url, headers=headers, json=field_def)
            result = response.json()
            if result.get("code") == 0:
                created_count += 1
Confidence
85% confidence
Finding
requests.post(api_url, headers=headers, json=

External Transmission

Medium
Category
Data Exfiltration
Content
# 飞书批量删除最多500条
            for i in range(0, len(empty_ids), 500):
                batch = empty_ids[i:i+500]
                response = requests.post(delete_url, headers=delete_headers, json={"records": batch})
                delete_result = response.json()
                if delete_result.get("code") == 0:
                    print(f"   🗑️  批量删除 {len(batch)} 个空白行")
Confidence
96% confidence
Finding
requests.post(delete_url, headers=delete_headers, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"fields": fields
    }
    
    response = requests.post(api_url, headers=headers, json=data)
    result = response.json()
    
    if result.get("code") == 0:
Confidence
92% confidence
Finding
requests.post(api_url, headers=headers, json=

VirusTotal

63/63 vendors flagged this skill as clean.

View on VirusTotal