Back to skill

Security audit

Save Article With Images

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly performs article archiving, but it needs review because it can fetch web content, persist it locally, and send generated files to Feishu without tight scope or confirmation.

Install only if you are comfortable with this skill contacting external sites, saving article contents and images on disk, and potentially sending generated files to Feishu. Avoid using it on private or authenticated pages unless you explicitly want that content persisted and shared. Review or remove the external ~/.agent-reach tool reference and add confirmation gates for Feishu delivery, large image downloads, and untrusted article sources.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_wechat.py:142
Finding

Unsanitized Remote Article HTML Is Embedded in a Locally Opened Document

Content
View full analysis
{title} * {{ margin: 0; padding: 0; box-sizing: border-box; }} body {{ font-family: -apple-system, BlinkMacSystemFont, "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; line-height: 1.8; color: #333; max-width: 100%; padding: 1cm; }} .header {{ text-align: center; padding: 30px 0; border-bottom: 2px solid #eaeaea; margin-bottom: 30px; }} .title {{ font-size: 24px; font-weight: bold; color: #1a1a1a; margin-bottom: 15px; }} .meta {{ font-size: 14px; color: #888; }} .content {{ font-size: 16pt; line-height: 1.8; }} .content p {{ margin-bottom: 24px; text-align: justify; }} .content h1 {{ font-size: 20px; font-weight: 600; color: #cf5148; margin: 30px 0 15px 0; text-align: center; }} /* Prevent image overflow - CRITICAL */ img {{ max-width: 90%; ...[truncated 3392 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_wechat.py:16
Finding

Article-Controlled Image URLs Permit Server-Side Request Forgery and Unbounded Downloads

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code substantially overlaps with the WeChat-saving portion of the description: it downloads a WeChat article, saves images locally, and generates Markdown plus HTML output. However, key declared behavior is missing or narrower than described. It does not convert to PDF; it only says 'next step: open HTML to generate PDF'. It is also not a general 'save web articles locally' implementation, because it targets a single hard-coded WeChat URL rather than accepting arbitrary article input. The claimed 'subagent isolation' is not present in this code chunk. These are material gaps between declared purpose and actual behavior, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill clearly instructs use of network access (curl, browser fetch, requests) and file writes (creating directories, saving Markdown/PDF/images), but it declares no explicit tool scope or permission boundaries. That makes the effective capability broader and less auditable, increasing the risk of unintended data access, remote retrieval, or local persistence when the skill is invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrases such as 'save article' and 'download article' are broad and likely to match ordinary user requests. In a skill that performs network fetches, local writes, and optional outbound sending, overbroad activation increases the chance of unintended execution and data handling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description emphasizes saving articles locally but omits a clear warning that the workflow may send saved files to Feishu. That omission undermines informed consent and can lead users to expose content externally when they believed processing was purely local.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The triggers section lacks constraints describing when the skill should not run, what content sources are in scope, and whether sharing/export is disabled by default. Without those boundaries, the agent may apply the workflow to unintended content, including private or authenticated pages, and persist or transmit the results.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill's stated purpose is local article saving, but it additionally instructs sending generated files to Feishu. That introduces an outbound exfiltration path for saved content, which may contain sensitive information, without making that behavior central and explicit in the skill description or requiring clear per-use consent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

The workflow persistently stores fetched articles, images, intermediate HTML, and optional PDFs under workspace directories. Persistent storage of remotely fetched or potentially private content increases exposure if the workspace is later accessed by other tools, users, or subsequent sessions.

Content

Scanner excerpt · SKILL.md (reported line 37)May include surrounding context.

Articles With Images

text
1. Create directory reports/{article-name}/
2. Create images/ subdirectory
3. Download all images to images/
4. Generate Markdown (relative path references)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs execution of an external local toolchain under ~/.agent-reach/tools/wechat-article-for-ai, which expands trust to code outside the skill itself. This creates supply-chain and execution-boundary risk because the referenced tool may perform additional network, file, or browser actions not disclosed in the manifest.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script makes outbound requests to fetch article HTML and then downloads all embedded images from remote URLs without an upfront warning or consent gate. In a skill setting, that increases risk because invoking the skill can silently contact third-party infrastructure, leak network metadata such as IP and user agent, and retrieve large or unexpected content from attacker-controlled URLs embedded in the article.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script automatically creates directories and writes multiple files to a hard-coded workspace location without any interactive confirmation, dry-run mode, or explicit disclosure before performing those actions. In an agent-skill context, this can lead to unexpected persistence of remote content on disk, storage abuse, or unreviewed overwrites if the skill is triggered unintentionally or on attacker-chosen content.

Content

No source excerpt is available for this finding.

Tainted flow: 'md_path' from requests.get (line 131, network input) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/save_wechat.py (reported line 132)May include surrounding context.

python
md_content += f"---\n\n*保存时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n"
    
    md_path = article_dir / f'{title}.md'
    with open(md_path, 'w', encoding='utf-8') as f:
        f.write(md_content)
    
    print(f"✅ Markdown: {md_path}")

Tainted flow: 'html_path' from requests.get (line 234, network input) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/save_wechat.py (reported line 235)May include surrounding context.

python
</html>'''
    
    html_path = article_dir / f'{title}.html'
    with open(html_path, 'w', encoding='utf-8') as f:
        f.write(html_content)
    
    print(f"✅ HTML: {html_path}")

Tainted flow: 'meta_path' from requests.get (line 249, network input) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/save_wechat.py (reported line 250)May include surrounding context.

python
'directory': str(article_dir)
    }
    meta_path = article_dir / 'meta.json'
    with open(meta_path, 'w', encoding='utf-8') as f:
        json.dump(meta, f, ensure_ascii=False, indent=2)
    
    print(f"\n📊 完成!")

Static analysis

No suspicious patterns detected.