Back to skill

Security audit

Feed Watcher

Security checks for vulnerabilities and agentic risk

Overview

This RSS feed watcher is mostly coherent, but it can be configured to repeatedly fetch arbitrary internal or local URLs without safeguards.

Review before installing. Only add trusted public feed URLs, avoid private or internal endpoints, and do not enable cron until feeds are verified. If using WEBHOOK_URL, remember that feed names, article titles, links, and dates are sent to that external service. Prefer pinning dependencies and adding URL validation before routine use.

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

T09 · Insecure Skill Coding Practices

Error
Location
index.js:42
Finding

Unrestricted Feed URLs Enable Server-Side Request Forgery (SSRF)

Content
View full analysis
{ const parsedUrl = new URL(url); const protocol = parsedUrl.protocol === 'https:' ? https : http; const req = protocol.get(url, { headers: { 'User-Agent': 'feed-w0', 'atcher/1.Accept': 'application/rss+xml, application/atom+xml, application/xml, text/xml' } }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); req.on('error', reject); req.setTimeout(10000, () => { req.destroy(); reject(new Error('Request timeout')); }); }); } ``` The URL reaches the vulnerable function directly when a feed is added: ```js await addFeed(args[1], args[2]); ``` Stored feed URLs are fetched again during later checks: ```js const xml = await fetchFeed(feed.url); const items = parseFeed(xml, feed.url); ``` ### Technical Analysis The `add` command accepts an arbitrary URL from the command line, and `addFeed()` passes it to `fetchFeed()` without validating its destination. The URL is also persisted in `~/.feed-watcher/feeds.json`, allowing later `check` or `scan` operations to repeat the request. The implementation does not reject: - Loopback destinations such as `127.0.0.1` or `[::1]` - RFC 1918 private networks - IPv6 unique-local or link-local networks - IPv4 link-local destinations such as `169.254.0.0/16` - Cloud instance metadata endpoints - Internal hostnames that resolve to protected addresses - Plaintext HTTP destinations Consequently, the process can be induced to make HTTP requests using its own network position. This violates least privilege because public-fee ...[truncated 2064 chars]
Remediation
View remediation
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents use of environment variables such as WEBHOOK_URL and USER_AGENT, but it does not declare an explicit tool scope or permissions boundary for env access. This creates ambiguity about what sensitive configuration the skill may read at runtime and weakens least-privilege guarantees, especially in agent environments where undeclared env access can expose secrets unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code posts feed names, item titles, links, and publication dates to a user-supplied webhook URL in sendNotification, which transmits data off-system. Although the CLI help mentions WEBHOOK_URL as optional, it does not clearly warn that enabling it will send monitored feed content to an external endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill encourages sending feed update data to third-party webhook endpoints such as Discord, Telegram, and Slack, but it does not warn users that article titles, links, timestamps, and possibly feed choices will be transmitted outside their local environment. This can lead to accidental disclosure of monitoring interests or internal feed metadata, particularly if users watch private or sensitive feeds.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency uses a caret range, which allows newer minor/patch releases to be installed over time. This weakens build reproducibility and increases supply-chain risk because a compromised or breaking upstream release could be pulled in without review.

Content

Scanner excerpt · package.json (reported line 26)May include surrounding context.

json
"author": "",
  "license": "MIT",
  "dependencies": {
    "rss-parser": "^3.13.0",
    "dotenv": "^16.3.1",
    "node-fetch": "^2.7.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dotenv dependency is not pinned to an exact version, so installs may resolve to different package contents over time. This creates a low-severity supply-chain and reproducibility issue, even if there is no evidence of active exploitation here.

Content

Scanner excerpt · package.json (reported line 27)May include surrounding context.

json
"license": "MIT",
  "dependencies": {
    "rss-parser": "^3.13.0",
    "dotenv": "^16.3.1",
    "node-fetch": "^2.7.0"
  },
  "engines": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The node-fetch dependency is declared with a floating caret range, allowing unreviewed upstream changes to be installed. In a network-facing feed watcher that fetches untrusted remote content, dependency drift is more concerning because parsing and HTTP behavior directly affect external input handling.

Content

Scanner excerpt · package.json (reported line 28)May include surrounding context.

json
"dependencies": {
    "rss-parser": "^3.13.0",
    "dotenv": "^16.3.1",
    "node-fetch": "^2.7.0"
  },
  "engines": {
    "node": ">=14.0.0"

Unverifiable Dependency: node-fetch has 3 known advisory(ies) (CVE-2022-0235 (node-fetch forwards secure headers to untrusted sites); CVE-2022-2596 (node-fetch Inefficient Regular Expression Complexity ); CVE-2020-15168 (The `size` option isn't honored after following a redirect in node-fetch)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The manifest does not pin node-fetch, and the package family has known advisories affecting some releases, including header forwarding on redirects and resource-handling issues. Because this skill actively performs outbound HTTP requests to potentially untrusted feeds and webhooks, an affected version could increase risk of credential leakage on redirects or denial-of-service from malicious responses.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.