Back to skill

Security audit

daily-news-collector

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed news/RSS webpage collector with real security hygiene gaps, but no evidence of hidden, destructive, persistent, or deceptive behavior.

Install only if you are comfortable letting the skill fetch configured RSS feeds and webpages and write collected results locally. Use trusted source lists, avoid internal/private URLs, review generated reports before relying on them, and treat fetched article text as untrusted content that should not control the agent.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/collect_webpages.py:15
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/collect_webpages.py:15-22, scripts/collect_webpages.py:105-114, and scripts/collect_feeds.py:34-45
Vulnerability Type: Server-Side Request Forgery caused by insufficient URL and destination validation
Risk Level: High

Vulnerable Code

scripts/collect_webpages.py:15-22:

python
def fetch_webpage(url: str) -> Optional[str]:
    """抓取网页HTML内容"""
    try:
        import requests
        response = requests.get(url, timeout=30, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        response.raise_for_status()
        return response.text

scripts/collect_webpages.py:105-114:

python
for url in urls:
    if not url.startswith(('http://', 'https://')):
        print(f"警告: 跳过无效URL: {url}")
        continue

    print(f"正在抓取: {url}")
    html = fetch_webpage(url)

    if html:
        content = extract_content(html, url)

scripts/collect_feeds.py:34-45:

python
url = source.get('url')
name = source.get('name', '未知来源')
category = source.get('category', '未分类')

if not url:
    print(f"警告: 来源 {name} 缺少URL配置")
    return []

try:
    feed = parse(url)
    if feed.bozo:

Technical Analysis

Both collectors initiate outbound requests to user-controlled URLs. The webpage collector only verifies that a string begins with http:// or https://. This does not prevent access to loopback addresses, private networks, link-local services, IPv6-local destinations, or cloud instance metadata endpoints.

The RSS collector passes the configured URL directly to feedparser.parse() without even applying the webpage collector's limited scheme check. Depending on the parser's supported behavior and environment, this allows arbitrary configured network destinations to be queried.

Redirects are not explicitly disabled or validated. The `request ...[truncated 1729 chars]

Remediation
View remediation

Remediation Suggestions

  • Permit only explicitly required schemes, normally HTTPS and, where necessary, HTTP.
  • Parse URLs with a standards-compliant URL parser rather than using prefix checks.
  • Resolve hostnames before connecting and reject all loopback, private, link-local, multicast, reserved, unspecified, and metadata-service address ranges for both IPv4 and IPv6.
  • Maintain an allowlist of approved news and feed domains where operationally possible.
  • Disable redirects by default. If redirects are required, revalidate the scheme, hostname, port, and resolved destination address at every redirect hop.
  • Defend against DNS rebinding by ensuring that the validated address is the address used for the connection.
  • Restrict destination ports to those genuinely needed, such as 80 and 443.
  • Apply the same validation policy to both requests.get() and feedparser.parse().
  • Run collectors in a network sandbox that cannot access localhost services, private networks, or cloud metadata endpoints.
  • Avoid including complete sensitive response bodies or detailed internal connection errors in downstream reports.

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:50
Finding

Untrusted Feed and Webpage Content Is Passed to the Agent Without Prompt-Injection Boundaries

Content
View full analysis

Vulnerability Details

File Location: scripts/collect_webpages.py:66-77, scripts/collect_feeds.py:53-61, and SKILL.md:50-54
Vulnerability Type: Indirect prompt injection through attacker-controlled collected content
Risk Level: Medium

Vulnerable Code

scripts/collect_webpages.py:66-77:

python
if not content_text:
    paragraphs = soup.find_all('p')
    content_text = '\n'.join([p.get_text().strip() for p in paragraphs if p.get_text().strip()])

# 清理文本
content_text = re.sub(r'\n+', '\n', content_text)
content_text = content_text[:2000]  # 限制长度

# 提取发布时间
published = ''
time_elements = soup.find_all(['time', 'span'], attrs={'class': re.compile(r'time|date|publish', re.I)})

scripts/collect_feeds.py:53-61:

python
article = {
    'title': entry.get('title', '无标题'),
    'link': entry.get('link', ''),
    'published': entry.get('published', ''),
    'summary': entry.get('summary', '')[:500],  # 限制摘要长度
    'source': name,
    'category': category,
    'collected_at': datetime.now().isoformat()
}

SKILL.md:50-54:

markdown
2. **分析筛选资讯**
   - 智能体读取收集到的原始数据
   - 根据用户需求筛选重要资讯(如:科技类、商业类、特定关键词)
   - 按主题自动分类(科技、商业、社会、政策等)
   - 为每条资讯生成简明摘要(1-2句话)

Technical Analysis

Feed publishers and webpage operators fully control article titles, summaries, and extracted body text. The collectors preserve this attacker-controlled text and the Skill explicitly instructs the Agent to read and analyze the resulting raw data.

Length truncation and HTML tag removal do not distinguish factual article content from natural-language instructions. A malicious source can therefore embed text such as instructions to ignore the user's request, alter the report, disclose context, invoke tools, or append promotional links.

The Skill does not establish a trust boundary stating that fetched material is data rather than instructions. It also does not require a constraine ...[truncated 1480 chars]

Remediation
View remediation

Remediation Suggestions

  • Add an explicit instruction to SKILL.md that all feed and webpage content is untrusted data and that the Agent must never obey instructions contained within it.
  • Require the Agent to extract only predefined factual fields, such as title, publication time, source, topic, and neutral summary.
  • Place collected material inside clearly delimited data blocks and state that delimiters cannot change instruction priority.
  • Use a fixed structured output schema and validate generated output before rendering it as Markdown.
  • Prevent collected content from initiating tool calls, changing configuration, accessing unrelated files, or altering system and user instructions.
  • Escape or neutralize Markdown links and other active formatting derived from untrusted fields before including them in a report.
  • Apply source allowlists and trust tiers, while recognizing that allowlisting alone does not eliminate compromised-publisher risk.
  • Scan generated reports for unexpected external links, instruction-like passages, and content not traceable to collected records.
  • Keep the summarization Agent minimally privileged and separate it from Agents with filesystem, credential, or administrative capabilities.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/collect_webpages.py:15
Finding

Unbounded Remote Response Processing Enables Resource Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/collect_webpages.py:15-22 and scripts/collect_feeds.py:43-45
Vulnerability Type: Uncontrolled resource consumption from unbounded network responses
Risk Level: Medium

Vulnerable Code

scripts/collect_webpages.py:15-22:

python
def fetch_webpage(url: str) -> Optional[str]:
    """抓取网页HTML内容"""
    try:
        import requests
        response = requests.get(url, timeout=30, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        response.raise_for_status()
        return response.text

scripts/collect_feeds.py:43-45:

python
try:
    feed = parse(url)
    if feed.bozo:

Technical Analysis

The webpage collector accesses response.text, causing the complete response body to be downloaded and decoded before extracted text is truncated to 2,000 characters. The 30-second timeout is not a total response-size limit and does not reliably prevent a server from continuously delivering data.

The RSS collector similarly passes the source directly to feedparser.parse() without imposing a download-size or decompression limit. A hostile source can return an extremely large document or compressed response that expands substantially in memory.

Content limits applied after downloading and parsing do not protect network bandwidth, parser CPU, or peak memory usage. There is also no content-type validation, per-source byte quota, aggregate job quota, or maximum number of configured sources.

Attack Path

  1. An attacker controls or compromises a configured webpage or RSS endpoint.
  2. The endpoint returns a very large response, a slowly delivered response, or compressed content with a large expansion ratio.
  3. The collector downloads and decodes or parses the complete response.
  4. Memory, CPU, bandwidth, or execution time is exhausted before the later text truncati ...[truncated 733 chars]
Remediation
View remediation

Remediation Suggestions

  • Use streamed HTTP requests and stop reading after a strict maximum number of bytes.
  • Reject responses whose declared Content-Length exceeds the configured limit, while still enforcing a streaming limit because the header may be absent or false.
  • Restrict accepted media types to expected HTML, XML, RSS, and Atom formats.
  • Set separate connection and read timeouts and enforce an overall request deadline.
  • Limit decompressed response size and reject unsupported or excessive content encodings.
  • Apply equivalent bounded fetching before handing data to feedparser; do not let the parser fetch arbitrary unbounded URLs directly.
  • Limit the number of sources, entries per source, total bytes per collection, and cumulative execution time.
  • Parse content incrementally where practical and terminate processing once configured limits are reached.
  • Run collection in a process or container with memory, CPU, bandwidth, and execution-time quotas.
  • Record limit violations without logging large response bodies.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

该代码块的核心功能是RSS数据采集器,而不是完整的多渠道资讯监控与日报生成系统。它读取配置、调用 feedparser 解析RSS、汇总文章并写入JSON文件。这与描述中的“多个媒体渠道采集 + 智能分析 + 结构化日报 + 每日自动运行”相比存在明显功能缩减和主用途差异。虽然‘结构化’这一点可勉强对应JSON输出,但整体上代码只覆盖了描述中的一小部分,因此应判定为描述与实际行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

声明描述的是一个多渠道资讯采集并分析生成日报的完整系统,而实际代码块只实现了对指定网页URL的内容抓取与简单文本提取。代码没有RSS解析、API调用、新闻聚合分析、摘要/分类/竞品分析、日报生成,也没有任何自动定时触发机制。虽然“从网站收集资讯”与声明中的一部分相符,但整体主功能范围明显比声明窄,属于描述与实际行为不一致。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill instructs the agent to read configuration files, write output files, and access external network resources, but it does not declare any explicit tool scope or permission boundaries. This increases the chance of unintended file and network access because neither users nor the runtime have a clear least-privilege contract for what the skill is allowed to do.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

L003 明确要求“生成结构化日报”,且整份技能文档均以中文描述,没有说明是否支持用户选择输出语言或地区设置。若技能默认强制使用单一语言而无用户选择,属于语言/locale 策略风险。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger conditions are broad enough that the skill could activate for generic requests like collecting information or monitoring updates, leading to unintended network access or scraping behavior. In an agent setting, overbroad activation increases the risk of the skill being invoked without clear user consent for external data collection and file generation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill performs web fetching and RSS collection from external sources but does not clearly disclose this network activity or the associated data flow to users. Lack of transparent notice undermines informed consent and can cause privacy, compliance, or policy violations when the agent retrieves content from third-party sites.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file presents all instructions and examples exclusively in Chinese, which can amount to a language policy violation when no user opt-in, alternative locale, or scope justification is provided. The content does not indicate that the skill is intended only for a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring is entirely in Chinese, and user-facing help/error/output strings throughout the script are also only in Chinese. This imposes a language choice on users without offering an alternative or opt-in, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language docstrings and CLI/help/output text in Chinese only, such as the module docstring and later argparse/help messages. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy concern.

Content

No source excerpt is available for this finding.