T01 · Skill Instruction Hijacking
- Location
SKILL.md:45- Finding
Untrusted RSS Content Can Hijack Agent Instructions During Summarization
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches an RSS digest purpose, but it needs review because it processes untrusted feed text without clear safeguards, writes to an unsafe temporary path, and may install an unpinned package at runtime.
Install only if you are comfortable with the skill fetching the bundled RSS feeds, writing digest files in your home directory, and creating a temporary JSON file. Prefer running it in an isolated environment, pin feedparser before use, and treat article titles/descriptions as untrusted text that should not be allowed to issue instructions or trigger tools.
SKILL.md:45Untrusted RSS Content Can Hijack Agent Instructions During Summarization
scripts/format_digest.py:49Unescaped Feed Metadata Allows Markdown Content and Link Injection
scripts/fetch_feeds.py:136Predictable Shared Temporary File Allows Symlink-Based File Overwrite
SKILL.md:76Runtime Installation Uses an Unpinned Third-Party Dependency
The code clearly implements only the feed-ingestion portion of the declared skill: it parses a feed-sources.md file, fetches RSS/Atom entries with feedparser, filters by publication time, and emits a JSON object containing articles and errors. This partially aligns with 'Fetch RSS feeds, parse articles.' However, the declared description also claims the skill will generate AI summaries and compile a daily digest report in Markdown, and no such behavior appears in the code. Instead, the output is raw/truncated article metadata in JSON, written both to stdout and to /tmp/openclaw-rss-articles.json. Additionally, the code reads a local feeds file and writes a temporary output file, while the declared permissions list is empty. That file access is an undeclared resource usage, though it is supportive of the feed-fetching purpose rather than a separate malicious capability. Overall, the description materially overstates what the code does and omits its file I/O behavior.
The skill instructs the agent to read from local files and write a digest report to the user's home directory, but it does not declare any tool scope or permissions for those file operations. This creates an authorization and transparency gap: a host system or reviewer cannot reliably constrain or audit the skill's filesystem access, increasing the risk of unintended data exposure or misuse if the skill is invoked broadly.
The trigger phrases are broad and map to common user intents such as 'news digest,' 'daily briefing,' and 'tech news roundup,' which can cause the skill to activate in many ordinary conversations. In combination with file access and network-fetch behavior, overly broad invocation increases the chance of the agent performing external retrieval and local writes when the user did not clearly request this specific skill.
The module docstring and other user-facing text are written only in Chinese, which imposes a specific language/locale choice without offering an alternative or opt-in. Under the stated policy, forcing a specific language is a natural-language policy violation unless the skill offers user choice or clearly documents a justified locale restriction.
The script writes aggregated feed contents to a predictable fixed path in /tmp, which can expose fetched data to other local processes or users depending on system permissions and execution environment. A fixed temporary filename also creates risks around symlink attacks, file clobbering, or unintended cross-run data leakage when multiple invocations share the same host.
This code contains natural-language strings in Chinese describing the skill's purpose and behavior, which imposes a specific language/locale without any opt-in or alternative. Under the policy, language-specific behavior should either be user-selectable or clearly justified as region-specific.
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
for entry in feed.entries[:20]: # 每个源最多 20 篇
published = None
for time_field in ['published_parsed', 'updated_parsed']:
t = getattr(entry, time_field, None)
if t:
from calendar import timegm
published = datetime.fromtimestamp(
No suspicious patterns detected.