Back to skill

Security audit

AIBase-News-Get

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a straightforward AIBase news scraper, but it needs review because untrusted page links can drive requests to arbitrary URLs and its documentation overstates summarization behavior.

Review this skill before installing. It does not show hidden persistence, credential theft, destructive actions, or code execution, but run it only in an environment where outbound HTTP is restricted and where writing to the current working directory is acceptable. Treat scraped titles and article bodies as untrusted text, and do not allow a summarizing agent to follow instructions found inside articles.

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

Error
Location
scrapers/aibase.py:67
Finding

Server-Side Request Forgery Through Unvalidated Article URLs

Content
View full analysis

Vulnerability Details

File Location: scrapers/aibase.py:67-83, scrapers/base.py:53-58, and request invocation at scrapers/base.py:91
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: High

Vulnerable Code

scrapers/aibase.py:67-83:

python
url = link_elem.get("href", "")
# 保存原始URL用于去重
original_url = url
if not url.startswith("http"):
    # 确保使用中文版URL获取内容
    if "/zh" not in url:
        url = "/zh" + url
    url = "https://www.aibase.com" + url
    # 原始URL用于去重
    original_url = "https://www.aibase.com" + original_url
else:
    # 如果是完整URL,确保也获取中文版本
    if "/zh" not in url:
        url = url.replace("www.aibase.com/news", "www.aibase.com/zh/news")
    original_url = url

scrapers/base.py:53-58:

python
try:
    resp = self.session.get(url, timeout=timeout)
    resp.raise_for_status()
    resp.encoding = resp.apparent_encoding
    return resp.text
except Exception as e:

The resulting URL is requested during detail-page processing at scrapers/base.py:91:

python
detail_html = self.fetch(item["url"])

Technical Analysis

Article URLs are extracted from the remotely supplied listing page. Relative URLs are attached to the expected AIBase origin, but absolute URLs beginning with http are accepted without validating their scheme, hostname, port, or resolved IP address.

Calling str.replace() for the expected AIBase path is not an origin validation mechanism. An absolute URL hosted on an unrelated domain remains usable if the target substring is absent. Furthermore, requests.Session.get() follows HTTP redirects by default, and redirect destinations are not validated.

Consequently, an attacker who can influence a listing link or an intermediate redirect can cause the scraper to issue requests from the environment in which the Skill runs. Potential targets include loopback services, private network addresses, link-l ...[truncated 1385 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse every URL with urllib.parse.urlsplit() and permit only https.
  2. Require the normalized hostname to exactly match an explicit allowlist, such as www.aibase.com. Do not use substring or suffix checks that can be bypassed by domains such as www.aibase.com.attacker.example.
  3. Reject URLs containing unexpected credentials, ports, malformed hostnames, or nonstandard schemes.
  4. Resolve the hostname and reject every result belonging to loopback, private, link-local, multicast, unspecified, or reserved IP ranges. Apply equivalent checks to IPv4 and IPv6.
  5. Disable automatic redirects with allow_redirects=False, or validate the scheme, hostname, port, and resolved addresses of every redirect destination before following it.
  6. Repeat validation immediately before each request to reduce DNS rebinding and time-of-check/time-of-use risk.
  7. Apply strict response-size limits to prevent untrusted endpoints from causing excessive memory consumption.
  8. Where possible, enforce outbound network restrictions outside the application so the process cannot reach metadata, loopback, or private-network services.

other

Warning
Location
scrapers/aibase.py:149
Finding

Indirect Prompt Injection Through Untrusted News Content

Content
View full analysis

Vulnerability Details

File Location: scrapers/aibase.py:149-183, scripts/crawl.py:76-83, and SKILL.md:111-115
Vulnerability Type: Indirect Prompt Injection
Risk Level: Medium

Vulnerable Code

scrapers/aibase.py:149-183:

python
if article:
    # 移除脚本和样式
    for tag in article.find_all(["script", "style"]):
        tag.decompose()

    # 获取文本
    texts = article.get_text(separator="\n", strip=True)
    # 清理多余空白
    lines = [line.strip() for line in texts.split("\n") if line.strip()]
    result["content"] = "\n\n".join(lines)

# 提取发布时间 - 支持多种格式
time_elem = soup.find("time") or soup.find(class_="publish-time") or soup.find(class_="date")
if time_elem:
    time_str = time_elem.get_text(strip=True)
    # 尝试解析时间 - 支持多种格式
    time_formats = [
        "%Y-%m-%d %H:%M:%S",
        "%Y-%m-%d",
        "%Y/%m/%d",
        "%b %d, %Y",        # Mar 16, 2026
        "%B %d, %Y",        # March 16, 2026
        "%d %b %Y",         # 16 Mar 2026
        "%d %B %Y",         # 16 March 2026
    ]
    parsed = False
    for fmt in time_formats:
        try:
            result["publish_time"] = datetime.strptime(time_str, fmt).strftime("%Y-%m-%d %H:%M:%S")
            parsed = True
            break
        except ValueError:
            continue
    if not parsed:
        # 如果都失败,保留原始文本
        result["publish_time"] = time_str

# 如果没有提取到正文,尝试从整个页面获取
if not result["content"]:
    body = soup.find("body")
    if body:
        for tag in body.find_all(["script", "style", "nav", "header", "footer"]):
            tag.decompose()
        result["content"] = body.get_text(separator="\n", strip=True)[:5000]

scripts/crawl.py:76-83:

python
item = {
    "title": news.get("title", ""),
    "url": news.get("original_url") or news.get("url", ""),
    "publish_time": news.get("publish_time", ""),
    "source": news.get("source", ""),
    "key
...[truncated 2487 chars]
Remediation
View remediation

Remediation Suggestions

  1. Update SKILL.md to state explicitly that titles, article bodies, metadata, and fetched pages are untrusted external data.
  2. Require downstream prompts to treat article content only as quoted material to summarize and to ignore any instructions, requests, links, or tool directives contained within it.
  3. Place source content inside an explicit structured field or delimiter and keep task instructions outside that boundary.
  4. Use a narrowly scoped summarization prompt that prohibits tool calls, secret disclosure, changes to system behavior, and execution of actions requested by source text.
  5. Run summarization with no tools and no unnecessary access to secrets or prior conversation context whenever possible.
  6. Constrain and validate the model output against the expected schema, such as a short summary and a bounded list of keywords.
  7. Apply length limits and detect common model-directed phrases as a defense-in-depth signal. Detection should not replace explicit trust-boundary controls.
  8. Preserve source provenance so users and downstream systems can distinguish fetched material from trusted Skill instructions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

该代码的核心行为与“AI 新闻采集、内容聚合”基本一致:它解析 AIBase 新闻列表和详情页,抽取标题、URL、发布时间、正文等信息,没有发现越权访问、额外触发器、数据外传或其他未声明的敏感行为。但描述中明确提到“支持自动生成新闻总结”,而代码中没有任何摘要生成、NLP、调用模型或总结逻辑,因此存在描述与实际能力不符。此外,描述听起来像面向多个 AI 新闻网站的通用爬取,而此代码块仅实现了 AIBase 单站点爬虫,不过这点属于范围收窄,严重性低于“自动总结”缺失。综合判断为存在不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises substantive functionality: crawling AI news websites, generating summaries, and supporting aggregation/monitoring use cases. However, the supplied code chunk is effectively empty aside from a comment in scripts/init.py. There is no implemented behavior matching the declared purpose, nor any alternative behavior. This is a material description-to-code mismatch because the code does not actually perform the advertised capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

核心抓取AI新闻网站这一点与声明基本一致,但“支持自动生成新闻总结”与实际行为不符:代码只是读取/保留summary字段,输出中甚至明确提示‘如需生成一句话总结,可读取JSON文件内容进行生成’,说明摘要生成并未在该代码块内实现。因此描述夸大了已实现能力。另一个次要差异是注释和部分函数提到Markdown保存,但main流程只写入JSON,不影响主判断。整体上属于描述与实际能力存在实质性不一致。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises behavior that implies network access plus local file read/write, but it does not declare any tool scope or permissions boundary. That makes the operational trust model unclear and can lead an agent to grant broader capabilities than a user expects, especially because the skill also states that the AI will choose the save directory automatically.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill says files are saved in a directory chosen by the AI and supports force overwrite, but it does not provide a clear warning about local file creation or overwrite risk. This can lead to accidental data loss or writes into unexpected locations, which is more dangerous in an agent setting where filesystem actions may happen without the user noticing the exact target path.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file consistently specifies Chinese-language behavior, including extracting Chinese content, but does not state that this is an optional user-selected setting or a region-specific limitation. That can violate language/locale choice expectations when the skill is presented as a general news scraper.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The Accept-Language header forces requests to prefer zh-CN/zh content, which is a natural-language locale constraint. The file does not offer a user opt-in or configurable language choice, and no region-specific justification is documented here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Comments and logic explicitly enforce use of the Chinese version of the site, including rewriting URLs to /zh/news, rather than preserving the source locale. This is a natural-language locale policy concern because the skill imposes a specific language choice without any visible user opt-in or justification in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's natural-language content, including module and class docstrings and user-facing log messages, is written exclusively in Chinese, which imposes a specific language on users or operators without any opt-in or fallback. The policy allows locale constraints only when choice or clear justification is provided, neither of which appears here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring, CLI description, help text, and runtime output are written in Chinese only, effectively forcing a specific language for interaction. The file does not offer a language choice or document that the skill is intentionally region-specific, which can violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The top-level docstring states the script performs '生成AI摘要和关键词' and '保存为Markdown格式'. In the actual main execution path, the code saves a JSON file via save_to_json and prints a note telling the user to generate summaries later; save_news exists but is never called. This is an active contradiction between documentation and runtime behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest says the skill 'supports automatic generation of news summaries', and the module docstring also lists '生成AI摘要和关键词'. However, crawl_and_return_json only returns scraped news for a model to summarize later, and save_to_json/save_news persist placeholder summary values rather than invoking any summarization logic. This is a semantic mismatch between the advertised capability and the actual behavior in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill performs outbound requests to external news sites but does not clearly warn about network access, remote content retrieval, or the integrity/privacy implications of contacting third-party servers. In an agent environment, undocumented network activity can surprise users and may expose metadata such as IP, timing, or browsing targets.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a minimum version only, which makes builds non-reproducible and allows installation of different releases over time. That increases supply-chain risk and makes it hard to verify whether vulnerable or breaking versions of requests may be pulled into the environment.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
# 新闻爬虫依赖

requests>=2.28.0
beautifulsoup4>=4.11.0
openpyxl>=3.0.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The manifest does not pin requests, and the package has multiple known advisories across versions. In a news-scraper skill that makes outbound HTTP requests, an affected requests release could expose credentials, weaken request verification, or introduce other client-side security issues depending on the resolved version.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using an unpinned beautifulsoup4 version permits uncontrolled upgrades and non-reproducible installations. While not an immediate exploit by itself, it weakens supply-chain assurance and can unexpectedly introduce vulnerable or incompatible versions.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
# 新闻爬虫依赖

requests>=2.28.0
beautifulsoup4>=4.11.0
openpyxl>=3.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The openpyxl requirement is not pinned, so deployments may resolve to different versions at different times. Because openpyxl has had historical security issues, leaving the version open makes it difficult to ensure affected releases are excluded.

Content

Scanner excerpt · requirements.txt (reported line 5)May include surrounding context.

text
requests>=2.28.0
beautifulsoup4>=4.11.0
openpyxl>=3.0.0

Unverifiable Dependency: openpyxl has 2 known advisory(ies) (CVE-2017-5992 (Improper Restriction of XML External Entity Reference in Openpyxl); CVE-2017-5992 (Openpyxl 2.4.1 resolves external entities by default, which allows remote attack)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

openpyxl has known historical advisories, including XML external entity-related issues, and the unpinned requirement means an unsafe version could be installed. If this skill processes untrusted spreadsheet content now or in the future, a vulnerable release could enable file-based attacks or unintended data exposure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code contains all user-facing natural-language text in Chinese, including the module description, function docstring, and error message. The file does not offer a language choice or document that the skill is intended only for a Chinese-speaking or region-specific context, which may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code creates a local News directory and saves crawled article data into a JSON file, which is a file-write operation affecting user storage. Although the CLI path logs the save directory, the reusable function crawl_and_return_json performs the write without a user-facing warning, confirmation, or docstring disclosure that it will persist data to disk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.