Back to skill

Security audit

Rss Digest

Security checks for vulnerabilities and agentic risk

Overview

This RSS digest skill mostly does what it says, but it needs review because feed files can make it fetch arbitrary local or network URLs and the docs include recurring cron automation.

Install only if you trust the OPML/feed sources and are comfortable with the skill making outbound requests and writing digest files. Avoid enabling the cron examples until URL validation, size limits, and an easy removal/monitoring plan are added; run it with least privilege and avoid sensitive local environments.

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
scripts/fetch_feeds.py:95
Finding

Unrestricted Feed URLs Enable Server-Side Request Forgery and Local Resource Access

Content
View full analysis
bytes | None: """Fetch a URL and return raw bytes, or None on error.""" req = Request(url, headers={"User-Agent": "rss-digest/1.0 (OpenClaw agent)"}) try: with urlopen(req, timeout=timeout) as resp: return resp.read() ``` From `scripts/fetch_feeds.py:251-259`: ```python for i, feed_meta in enumerate(feeds, 1): url = feed_meta.get("xmlUrl", "").strip() if not url: continue title = feed_meta.get("title", url) print(f" [{i}/{len(feeds)}] {title} ...", file=sys.stderr) raw = fetch_url(url, args.timeout) ``` ### Technical Analysis Feed URLs are accepted directly from an OPML document or JSON feed list and passed to Python's `urlopen` without validating their scheme, hostname, resolved address, port, or redirect destination. The legitimate function only requires retrieval of public RSS and Atom resources over HTTP or HTTPS. Allowing arbitrary URL schemes and arbitrary network destinations exceeds that requirement. Depending on the runtime handlers available to `urlopen`, an attacker may supply URLs targeting: - Loopback services such as `127.0.0.1` or `::1`. ...[truncated 2242 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch_feeds.py:95
Finding

Unbounded Feed Response Reads Permit Memory and CPU Exhaustion

Content
View full analysis
bytes | None: """Fetch a URL and return raw bytes, or None on error.""" req = Request(url, headers={"User-Agent": "rss-digest/1.0 (OpenClaw agent)"}) try: with urlopen(req, timeout=timeout) as resp: return resp.read() ``` From `scripts/fetch_feeds.py:167-174`: ```python def parse_feed_xml(raw: bytes, feed_meta: dict) -> list[dict]: """Parse raw XML bytes into a list of articles.""" feed_url = feed_meta.get("xmlUrl", "") feed_title = feed_meta.get("title", "") category = feed_meta.get("category", "") try: root = ET.fromstring(raw) ``` ### Technical Analysis The code calls `resp.read()` without a maximum byte count. Consequently, the complete response body is buffered in memory before XML parsing begins. The configured timeout limits network waiting behavior but does not impose a response-size limit or a total resource budget. After the body is buffered, `ET.fromstring(raw)` constructs an in-memory XML tree. This creates further allocations proportional to the document's size and structure. The parser also lacks limits on XML depth, element count, article count, or cumulative text size. An attacker-controlled feed can therefore return an oversized or structurally expensive XML response. Processing several malicious feeds in one run can compound memory and CPU consumption. Because the documentation recommends recurring cron execution, the availability impact may repeat automatically until the malicious subscription is removed. ### Attack Path 1. An attacker controls a URL listed in the victim's OPML file, compromises an existing feed, or persuades the victim to ...[truncated 1256 chars]
Remediation
View remediation
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description says to use the skill when the user asks to "summarize their feeds," "build a news roundup," or "what's in my feeds today," which are broad natural phrases that could match ordinary conversation beyond a clearly scoped skill invocation. The file does not provide exclusion conditions or negative examples to clarify when these phrases should not activate the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill description omits a clear warning that it retrieves untrusted remote content from RSS/Atom feeds and writes generated output to local files, including scheduled writes via cron. Users may invoke it without understanding that it performs network access and persistent filesystem writes, which increases the chance of unsafe use with sensitive environments or untrusted feed sources.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
Reference OPML: `references/opml-example.opml`

All scripts write progress/errors to stderr, data to stdout — safe to pipe.

## Setup

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill explicitly instructs users to install recurring cron jobs, creating persistence that continues network fetching and file writes outside the immediate session. While intended as convenience, persistence changes the risk profile because the task will keep executing automatically against possibly changing remote content and local paths.

Content

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

Cron Schedule

Add to crontab (crontab -e) for a daily digest at 7 AM ET:

cron
0 7 * * * python3 /Users/openclaw/.openclaw/workspace/skills/rss-digest/scripts/parse_opml.py ~/feeds.opml | python3 /Users/openclaw/.openclaw/workspace/skills/rss-digest/scripts/fetch_feeds.py --hours 24 | python3 /Users/openclaw/.openclaw/workspace/skills/rss-digest/scripts/build_digest.py --period Daily --output /Users/openclaw/.openclaw/workspace/vault/daily-recap/rss-$(date +\%Y-\%m-\%d).md

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script fetches arbitrary feed URLs supplied via stdin or a JSON file, causing outbound requests to third-party hosts without any explicit warning, allowlist, or validation. In an agent/automation context this can leak network metadata, contact internal resources if attacker-controlled feed lists are provided, and create unintended SSRF-like behavior even though the code appears intended for normal RSS retrieval.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.