Back to skill

Security audit

Rss Reader

Security checks for vulnerabilities and agentic risk

Overview

This RSS skill appears purpose-built rather than malicious, but it needs review because it can repeatedly fetch arbitrary URLs and send API keys plus RSS-derived data to configurable external services.

Install only if you are comfortable with RSS titles, links, summaries, and generated reports being sent to the AI provider and, if configured, to Feishu/Lark. Use only public feed URLs, avoid localhost/private/internal feed addresses, keep OPENAI_BASE_URL fixed to a trusted provider, protect the API key and webhook values, and review the cron command before enabling automatic refreshes.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
rss_reader.py:33
Finding

API Credential Disclosure Through an Unrestricted AI Endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
rss_reader.py:190
Finding

Server-Side Request Forgery Through User-Supplied RSS URLs

Content
View full analysis
[名称]") return url = sys.argv[2] name = sys.argv[3] if len(sys.argv) >= 4 else None print(add_subscription(url, name)) ``` The URL is then fetched without destination validation: ```python def add_subscription(url: str, name: str = None): """添加订阅""" subscriptions = load_json(SUBSCRIPTIONS_FILE, {}) if url in subscriptions: return f"⚠️ 已存在订阅:{subscriptions[url]['name']}" # 解析 RSS 获取名称 try: feed = feedparser.parse(url) if feed.bozo and not feed.entries: return f"❌ 无效的 RSS 地址:{url}" feed_name = name or feed.feed.get("title", url) ``` Stored subscription URLs are fetched again during refresh: ```python def fetch_new_articles(url: str): """获取新文章""" subscriptions = load_json(SUBSCRIPTIONS_FILE, {}) articles = load_json(ARTICLES_FILE, {}) try: feed = feedparser.parse(url) if feed.bozo and not feed.entries: print(f" ⚠️ 解析失败:{url}") return [] ``` ### Technical Analysis The Skill legitimately needs network access to retrieve RSS feeds. However, it passes an unrestricted command-supplied URL to `feedparser.parse()` without enforcing an HTTP(S) scheme or validating the destination hostname and resolved IP address. Consequently, the Skill may be induced to connect to localhost, private network services, link-local services, or cloud metadata endpoints. Redirects and DNS rebinding may also allow an initially acceptable hostname to resolve or redirect to a restricted destination. A successfully added URL is persisted in `subscripti ...[truncated 1721 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Permit Unreviewed Future Releases

Content
View full analysis
=6.0.0 requests>=2.28.0 ``` ### Technical Analysis The dependency names correspond to established packages, and the audit found no evidence of typosquatting, dependency confusion, or an intentionally malicious package. Nevertheless, minimum-only version constraints permit package installers to select any future release satisfying the range. As a result, the installed code may differ from the versions reviewed with this Skill. A compromised, malicious, or incompatible future release could be downloaded and imported without a source-code change in the project. The absence of package hashes also prevents integrity verification against a reviewed artifact. ### Attack Path 1. A user installs the Skill's dependencies with `pip install -r requirements.txt`. 2. The package index resolves each `>=` constraint to a newer release available at installation time. 3. A compromised or otherwise unsafe release satisfies the declared constraint. 4. The package is downloaded and installed without hash verification. 5. Package installation or later import executes code from the unreviewed release in the user's Python environment. This path requires compromise or malicious publication involving a dependency or its distribution channel; no such compromise was identified during this audit. ### Impact Assessment A malicious dependency release could execute code with the privileges of the user installing or running the Skill. That could expose environment variables, including `OPENAI_API_KEY` and `FEISHU_WEBHOOK_URL`, modify local files accessible to the process, or make arbitrary network requests. The current evidence establishes a supply-chain hardening weakness rather than a presently malicious dependency. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tainted flow: 'OPENAI_BASE_URL' from os.getenv (line 34, 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 · rss_reader.py (reported line 349)May include surrounding context.

python
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
    
    try:
        response = requests.post(
            f"{OPENAI_BASE_URL}/chat/completions",
            headers={
                "Authorization": f"Bearer {OPENAI_API_KEY}",

Tainted flow: 'OPENAI_BASE_URL' from os.getenv (line 34, 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 · rss_reader.py (reported line 403)May include surrounding context.

python
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
    
    try:
        response = requests.post(
            f"{OPENAI_BASE_URL}/chat/completions",
            headers={
                "Authorization": f"Bearer {OPENAI_API_KEY}",

Tainted flow: 'FEISHU_WEBHOOK_URL' from os.getenv (line 35, 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 · rss_reader.py (reported line 502)May include surrounding context.

python
}
    
    try:
        response = requests.post(
            FEISHU_WEBHOOK_URL, 
            json=message, 
            timeout=10

Tainted flow: 'api_url' from os.getenv (line 597, 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 · rss_reader.py (reported line 599)May include surrounding context.

python
base_url = os.getenv("OPENAI_BASE_URL", "https://open.bigmodel.cn/api/paas/v4")
        api_url = base_url if base_url.endswith("/chat/completions") else f"{base_url}/chat/completions"
        
        response = requests.post(
            api_url,
            headers={
                "Authorization": f"Bearer {api_key}",

Tainted flow: 'webhook_url' from os.getenv (line 666, 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 · rss_reader.py (reported line 708)May include surrounding context.

python
}
    
    try:
        response = requests.post(webhook_url, json=payload, timeout=10)
        if response.status_code == 200:
            result = response.json()
            if result.get("StatusCode") == 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

This markdown file instructs users to initialize a Git repository and push the entire skill directory to a public hosting service, but it does not warn users to review files for secrets, local data, or generated artifacts before publishing. Because this action can affect privacy and data integrity, a user-facing warning is expected in the documentation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README explicitly documents configuring a Feishu webhook for pushing RSS-derived summaries, but it does not clearly warn users that article content, extracted summaries, or metadata may be transmitted to an external third-party service. In a skill that also performs AI summarization and automated scheduled refreshes, this can lead to unintentional disclosure of internal or sensitive feed content, especially if users subscribe to private or semi-private RSS sources.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation describes capabilities that require environment-variable access, filesystem reads/writes, and network access, but it does not declare any explicit tool scope or permissions boundary. This creates an authorization mismatch: users and platforms cannot easily understand or constrain what the skill may access, increasing the risk of unintended data exposure or over-privileged execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description emphasizes AI summarization and Feishu push, but it does not clearly warn users that article metadata and generated summaries will be transmitted to third-party AI and messaging services. This is dangerous because users may invoke the skill assuming local processing, while the skill can disclose reading interests, selected sources, titles, and summary content to external providers.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger phrases are broad enough to match ordinary conversation about subscriptions, summaries, or RSS-like topics, which can cause the skill to activate unexpectedly. In this skill's context, unintended activation is more dangerous because activation can lead to external network requests, automatic subscription creation, article processing, and possible Feishu/AI transmission without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 43)May include surrounding context.

bash
export OPENAI_API_KEY="sk-xxx"
export OPENAI_BASE_URL="https://api.openai.com/v1"

💡 智谱 AI 优势:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest text, including the description and all declared commands, is exclusively in Chinese. This can amount to a language/locale policy issue because the skill appears to require a specific language without documenting opt-in, alternatives, or a justified region-specific scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill transmits article content and metadata to an external AI provider when generating summaries, but there is no explicit runtime warning or consent gate at the point of execution. In a content-aggregation skill, feeds may include proprietary, internal, or sensitive subscription sources, so silent exfiltration to a third party creates a real privacy and compliance risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This call sends article content to an external AI service. In this skill's context, outbound transmission is core functionality, but it is still a genuine data-exposure surface because RSS items may contain sensitive text and the transfer occurs without minimizing or classifying content sensitivity.

Content

Scanner excerpt · rss_reader.py (reported line 349)May include surrounding context.

python
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
    
    try:
        response = requests.post(
            f"{OPENAI_BASE_URL}/chat/completions",
            headers={
                "Authorization": f"Bearer {OPENAI_API_KEY}",

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The summarization prompt explicitly instructs the model to respond in concise Chinese, and the rest of the CLI/help text is also fixed in Chinese. This imposes a language choice without user opt-in, which matches the policy-violation category for locale or language constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The batch summarization path instructs the model in Chinese and requests concise Chinese summaries for all articles. Because no language preference mechanism is provided, the skill enforces a specific language by default rather than offering user choice.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The batch-summary path transmits multiple article titles and summaries to an external AI service, increasing the volume of exposed data in a single request. Although intended behavior, it represents a real privacy/compliance risk when feeds include non-public or sensitive material.

Content

Scanner excerpt · rss_reader.py (reported line 403)May include surrounding context.

python
prompt += "\n\n请按以下格式输出:\n1. [摘要内容]\n2. [摘要内容]\n..."
    
    try:
        response = requests.post(
            f"{OPENAI_BASE_URL}/chat/completions",
            headers={
                "Authorization": f"Bearer {OPENAI_API_KEY}",

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

This webhook send transmits article title, summary, source, and link to an external collaboration platform. Because the skill automatically distributes content outside the local environment, it creates a real information-sharing risk if feeds or generated summaries contain sensitive or internal material.

Content

Scanner excerpt · rss_reader.py (reported line 502)May include surrounding context.

python
}
    
    try:
        response = requests.post(
            FEISHU_WEBHOOK_URL, 
            json=message, 
            timeout=10

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The daily-report generation sends a consolidated set of article titles and sources to an external AI provider. Aggregated metadata can itself be sensitive because it reveals monitoring interests, internal topics, or research focus, making this more than a harmless network call.

Content

Scanner excerpt · rss_reader.py (reported line 599)May include surrounding context.

python
base_url = os.getenv("OPENAI_BASE_URL", "https://open.bigmodel.cn/api/paas/v4")
        api_url = base_url if base_url.endswith("/chat/completions") else f"{base_url}/chat/completions"
        
        response = requests.post(
            api_url,
            headers={
                "Authorization": f"Bearer {api_key}",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code automatically pushes the generated report, including article titles and links, to Feishu without an explicit execution-time confirmation. This can leak aggregated reading activity or sensitive feed contents to a broader audience than intended, especially because report push happens automatically after refresh/report flows.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

This sends the full generated report to Feishu, potentially exposing aggregated insights, titles, and links to a configured external destination. In this skill, automatic post-refresh/report pushing makes the risk more concrete because distribution can happen without an additional human review step.

Content

Scanner excerpt · rss_reader.py (reported line 708)May include surrounding context.

python
}
    
    try:
        response = requests.post(webhook_url, json=payload, timeout=10)
        if response.status_code == 200:
            result = response.json()
            if result.get("StatusCode") == 0:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

A natural-language policy issue exists because the skill documentation forces a specific language presentation for all users without any opt-in or alternative language path. The file does not indicate that the skill is region-specific or that Chinese is required for compliance or audience constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language instructions, commands, and operational guidance are written entirely in Chinese, including the invocation examples and cron prompt text. There is no indication that the skill is region-specific or that alternative language support is available, which can violate a language-choice policy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Although the file states that 18 feeds are auto-added on first use, it is presented as a feature rather than a caution about modifying the user's subscription state. Since this changes stored user data/configuration automatically, a clearer warning would better disclose the behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The design section explicitly states '单篇摘要 ❌(已移除)' and '不做单篇摘要', indicating the skill no longer performs per-article summaries. However, later documentation reintroduces 'AI 摘要' as an active feature in the feature table, FAQ, changelog, and examples, which contradicts the stated intent and can mislead users about what the skill actually does.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.