Back to skill

Security audit

feed-diet

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it should be reviewed because it can fetch arbitrary OPML feed URLs and send reading data to LLM services without a clear runtime opt-in.

Install only if you are comfortable with the skill fetching HN/RSS content over the network and potentially sending item titles and URLs to an LLM provider when an LLM tool or API key is available. Use trusted OPML files only, avoid internal/private feed URLs unless you intend them to be fetched, and prefer a local-only classification mode if handling sensitive subscriptions or work-related links.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/opml-parse.sh:33
Finding

OPML-Controlled Server-Side Request Forgery Through Feed URLs and Redirects

Content
View full analysis
/dev/null) # Validate URL scheme — only allow http/https to prevent SSRF case "$FEED_URL" in http://*|https://*) ;; *) warn "Skipping non-HTTP feed URL: $FEED_URL" continue ;; esac # Fetch the RSS/Atom feed with timeout FEED_XML=$(curl -sf --max-time 10 -L "$FEED_URL" 2>/dev/null) || { warn "Could not fetch feed: $FEED_TITLE ($FEED_URL)" continue } ``` ### Technical Analysis The OPML `xmlUrl` attribute is attacker-controlled and is passed to `curl` after validation of only the textual URL scheme. Allowing `http://` and `https://` does not prevent SSRF. The implementation does not reject: - Loopback destinations such as `127.0.0.1` and `::1` - RFC1918 private networks - Link-local addresses - Cloud metadata services - Reserved or multicast address ranges - Internal DNS names - DNS names that resolve or rebind to internal addresses - Unexpected destination ports The `-L` option instructs `curl` to follow redirects. Even if the initial address is public, a public endpoint can redirect the request to an internal service, and the redirected destination is not revalidated. Fetching remote RSS feeds is necessary for the declared functionality, but unrestricted access to arbitrary HTTP destinations exceeds the minimum network privileges required to retrieve ordinary public feeds. ### Attack Path 1. An attacker supplies or convinc ...[truncated 1705 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/feed-diet.sh:187
Finding

Untrusted Feed Content Is Rendered as Unescaped Markdown

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/opml-parse.sh:18
Finding

Predictable Shared Cache File Allows Symlink Clobbering and Cross-Run Corruption

Content
View full analysis
"$CACHE_FILE" ``` ```bash if [ -n "$ITEMS" ]; then ITEM_COUNT=$(echo "$ITEMS" | grep -c '^{' || echo 0) TOTAL_ITEMS=$((TOTAL_ITEMS + ITEM_COUNT)) echo "$ITEMS" >> "$CACHE_FILE" fi done <<< "$FEEDS" progress_done if [ "$TOTAL_ITEMS" -eq 0 ]; then err "No items fetched from any feeds. Check feed URLs and connectivity." exit 1 fi info "Fetched ${TOTAL_ITEMS} items from ${FEED_COUNT} feeds" cat "$CACHE_FILE" ``` A related predictable path is used in `scripts/hn-fetch.sh:15,58`: ```bash CACHE_FILE="${CACHE_DIR}/hn_${USERNAME}_items.jsonl" ``` ```bash > "$CACHE_FILE" ``` ### Technical Analysis The OPML fetcher always uses the same cache filename and truncates it through shell redirection. It does not verify that the path is a regular file, reject symbolic links, establish ownership, acquire a lock, or create a unique per-run file. If an attacker can modify the cache directory or pre-create the cache entry as a symbolic link, the redirection follows the link and truncates the target with the privileges of the Skill process. The effect is limited to files writable by that process. The shared fixed filename also creates a race between concurrent audits. One invocation can truncate or append to another invocation's cache, causing mixed, missing, or attacker-influenced report data. The cache directory is created without an explicit restrictive mode. Its actual accessibility depends on the user's umask, pre-existing directory state, and `XDG_CACHE_HOME` configuration. ### Attack Path #### Symlink clobbering 1. A local attacker with write access to the selected cache directory creates: ```ba ...[truncated 1084 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code chunk only implements a classification stage: it ingests content items, extracts title/url, sends batched prompts to an LLM or applies local heuristics, and emits categorized items. It does not generate the promised 'beautiful reports,' category breakdown reports, ASCII charts, or personalized recommendations. It also can call external services (Anthropic/OpenAI or openclaw) even though no permissions are declared. While classification could support a larger feed-audit workflow, this code by itself materially underdelivers relative to the declared purpose and includes undeclared network/API usage.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code only retrieves and filters Hacker News stories for a given username via the HN Firebase API, then emits raw JSON lines. It does not analyze content consumption, combine HN with RSS feeds, classify categories, generate reports or charts, or produce recommendations. Its primary behavior is data collection from HN submissions, which is materially narrower and different from the declared analytics/reporting purpose. Additionally, it performs network access to the HN API, which is not reflected in the declared permissions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description promises an analysis/reporting tool focused on auditing a user's information diet across HN and RSS feeds, with presentation features and recommendations. The supplied code instead implements a feed-ingestion utility: it reads an OPML file, extracts feed URLs, fetches feed XML via curl, parses RSS/Atom entries, writes them to a cache file, and emits JSON lines. While RSS feed collection could support a later audit pipeline, this chunk does not perform the advertised analysis, visualization, or recommendation behavior, and it introduces undeclared capabilities such as OPML parsing, remote network retrieval, and local caching. Therefore the code's actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/classify.sh` — Batch content classifier (LLM + fallback)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/hn-fetch.sh (reported line 86)May include surrounding context.

sh
# Process results
  for TMPFILE in "${TMPFILES[@]}"; do
    [ "$STORY_COUNT" -ge "$MAX_ITEMS" ] && rm -f "$TMPFILE" && continue
    
    if [ -s "$TMPFILE" ]; then
      ITEM_JSON=$(cat "$TMPFILE")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explicitly states that batches of reading-history items are sent to an external LLM API, but it does not clearly warn users that their feed contents, interests, and possibly personally identifying reading patterns will leave the local environment. In a tool that audits personal consumption habits, that omission creates a real privacy risk because users may enable API-backed classification without understanding the data-sharing implications.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to use shell commands, network access, and environment-dependent API keys, but it declares no explicit tool scope or permissions. This weakens containment and reviewability, making it easier for the skill to invoke capabilities the user or platform may not expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Overly broad trigger phrases can cause the skill to activate during ordinary conversation about reading habits, leading to unintended data access workflows or shell/network execution. In an agent ecosystem, accidental invocation increases the chance of surprise external requests and processing of user-supplied files or usernames.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill directs the agent to fetch user-related external data and optionally send content to third-party LLM services via API keys, but it does not clearly disclose this to the user or require consent. This creates privacy and data-governance risk, especially because feed contents and reading history may reveal sensitive interests, work topics, or personal habits.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script’s documented role is a stdin/stdout batch classifier, but it conditionally transmits item metadata to third-party LLM services using locally available API keys. Even if intended as a feature, this expands the trust boundary and can leak sensitive feed titles and URLs to external providers without being obvious from the interface or usage comment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script sends feed item titles and URLs to external APIs without any user-facing consent or warning, which creates a privacy and data-handling risk. Information-diet tools may process private RSS feeds, internal links, or sensitive article titles, so silent transmission is more dangerous in this skill context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This curl call transmits prompt content containing item titles and URLs to Anthropic’s API, creating external data exfiltration from local input. In the context of feed auditing, inputs may include private subscriptions or sensitive browsing interests, so sending them off-box is a meaningful confidentiality risk.

Content

Scanner excerpt · scripts/classify.sh (reported line 92)May include surrounding context.

sh
max_tokens: 1024,
        messages: [{role: "user", content: $prompt}]
      }')
    RESULT=$(printf '%s' "$request_body" | curl -sf --max-time 30 \
      -H "x-api-key: ${ANTHROPIC_API_KEY}" \
      -H "anthropic-version: 2023-06-01" \
      -H "content-type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The hardcoded Anthropic endpoint confirms direct external transmission capability in a script that otherwise appears to be a local pipeline component. This makes the skill context more sensitive because feed-analysis tooling often handles personal or proprietary reading data that users may not expect to leave their machine.

Content

Scanner excerpt · scripts/classify.sh (reported line 97)May include surrounding context.

sh
-H "anthropic-version: 2023-06-01" \
      -H "content-type: application/json" \
      -d @- \
      https://api.anthropic.com/v1/messages 2>/dev/null | jq -r '.content[0].text // empty' 2>/dev/null) || RESULT=""
  fi

  # Method 3: Use OPENAI_API_KEY

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This curl call sends the same batch content to OpenAI’s API, again exporting local feed metadata to a third party. The issue is not transport security but the unannounced transfer itself, which may violate user expectations or organizational data-handling requirements.

Content

Scanner excerpt · scripts/classify.sh (reported line 110)May include surrounding context.

sh
max_tokens: 1024,
        messages: [{role: "user", content: $prompt}]
      }')
    RESULT=$(printf '%s' "$request_body" | curl -sf --max-time 30 \
      -H "Authorization: Bearer ${OPENAI_API_KEY}" \
      -H "content-type: application/json" \
      -d @- \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The OpenAI endpoint similarly evidences outbound data transfer to a third party as part of normal classification behavior. In this skill, even seemingly low-sensitivity fields like article titles and URLs can reveal confidential projects, personal interests, or internal resources.

Content

Scanner excerpt · scripts/classify.sh (reported line 114)May include surrounding context.

sh
-H "Authorization: Bearer ${OPENAI_API_KEY}" \
      -H "content-type: application/json" \
      -d @- \
      https://api.openai.com/v1/chat/completions 2>/dev/null | jq -r '.choices[0].message.content // empty' 2>/dev/null) || RESULT=""
  fi

  # Method 4: Rule-based fallback (keyword matching)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

In audit mode, fetched Hacker News or RSS/OPML-derived content is piped into classify.sh, and the help text indicates that classification may use Anthropic or OpenAI APIs. That means potentially sensitive reading habits, feed contents, titles, URLs, or metadata are sent to a third-party network service without an explicit warning or consent check at the moment of execution, creating a real privacy/data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

In digest mode, the script fetches recent HN or OPML/RSS items and then classifies them before generating a personalized digest based on user goals. This can disclose not only the fetched content but also user-interest profiling data to an external LLM provider without an execution-time warning, which is a meaningful privacy issue in a tool specifically designed to analyze personal information-consumption patterns.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README asks users to export third-party API keys but does not include any guidance about secure credential handling, such as avoiding committing keys, using scoped secrets storage, or understanding that those keys authorize paid external API use. This is a lower-severity but valid security hygiene issue because inexperienced users may expose secrets while following installation instructions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code fetches each feed URL over the network using curl, which transmits system/network metadata to external servers. While the script logs progress and fetch failures, it does not clearly disclose in a user-facing warning or usage text that providing an OPML file will trigger outbound requests to every listed feed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.