Back to skill

Security audit

Podcast Discovery

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with podcast link discovery, but its helper can fetch arbitrary RSS URLs from the agent environment without destination or size limits and installs unpinned Python packages.

Install only if you are comfortable with the agent making web requests to Clawsica and podcast RSS hosts from your environment. Prefer running it in a restricted virtual environment or container, avoid supplying arbitrary or private-network RSS URLs, and ask the publisher to add URL validation, response-size limits, dependency pins, and a separate test requirements file.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/search_feed_episodes.py:98
Finding
Unrestricted RSS Feed Fetch Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/search_feed_episodes.py:98-100`, with attacker-influenced input accepted at `scripts/search_feed_episodes.py:255-256` **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unbounded network response **Risk Level**: High ### Vulnerable Code ```python def fetch_feed(rss_url: str, timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS) -> Any: request = Request(rss_url, headers={"User-Agent": DEFAULT_UA}) with urlopen(request, timeout=timeout_seconds) as response: data = response.read() return feedparser.parse(data) ``` The destination is supplied directly through a command-line argument: ```python parser.add_argument("--rss-url", required=True) ``` It is then forwarded to the vulnerable function without validation: ```python mode = args.mode rss_url = args.rss_url ... parsed_feed = fetch_feed(rss_url) ``` ### Technical Analysis The `--rss-url` value is passed directly to `urllib.request.urlopen`. The implementation does not validate: - The URL scheme - The destination hostname or port - Whether DNS resolves to a public IP address - Loopback, private, link-local, reserved, or cloud metadata addresses - Redirect destinations - The maximum response size Downloading an RSS feed is necessary for the declared podcast-search functionality. However, unrestricted access to arbitrary network destinations exceeds the minimum network privileges needed to retrieve public podcast feeds. An attacker who can influence the supplied RSS URL can make the process send requests to services reachable from the execution environment. This may include loopback services, private network systems, or infrastructure metadata endpoints. A malicious public server could also redirect the request to such a destination. Although the code does not deliberately transmit stored credentials or local files, internal response data may be parsed into feed fields and included in command output. Parser and network error ...[truncated 1578 chars]
Remediation
## Remediation Suggestions 1. Permit only explicitly required schemes, preferably `https`; allow `http` only when compatibility requirements justify it. 2. Parse the URL before use and reject user information, fragments, malformed hosts, and unexpected ports. 3. Resolve the hostname and reject all loopback, private, link-local, multicast, unspecified, documentation, and reserved IPv4 and IPv6 ranges. 4. Disable automatic redirects or validate every redirect target using the same scheme, hostname, port, and resolved-address policy. 5. Re-resolve and validate the destination at connection time to reduce DNS rebinding and time-of-check/time-of-use risks. 6. Prefer accepting only RSS URLs obtained from the trusted Clawsica result workflow rather than arbitrary command-line destinations. 7. Stream the response in chunks and stop after a conservative maximum feed size. 8. Apply both connection and read timeouts. 9. Avoid returning low-level internal connection details to untrusted users. 10. Add security tests covering loopback addresses, RFC 1918 networks, IPv6 local addresses, link-local metadata endpoints, encoded IP representations, redirects, DNS rebinding, unsupported schemes, unusual ports, and oversized responses.

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding
Unpinned Third-Party Dependencies Create Non-Reproducible Supply-Chain Exposure## Vulnerability Details **File Location**: `scripts/requirements.txt:1-3` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Medium ### Vulnerable Code ```text feedparser rapidfuzz pytest ``` The documented installation command in `SKILL.md:182` installs these unconstrained packages: ```bash pip install -r scripts/requirements.txt ``` ### Technical Analysis None of the declared packages has an exact version or integrity hash. Consequently, the code installed by the documented command can change over time without any modification to the audited project. A future compromised, malicious, or incompatible package release could execute code during installation or when imported by the script. The package manager's configured index and resolver state determine what is installed, so installations are not reproducible from the repository alone. The manifest also includes `pytest`, a development and testing dependency, in the same installation set as runtime dependencies. This unnecessarily increases the number of packages installed in environments that only need to execute the podcast search tool. No evidence was found that the currently named packages are typosquatted or intentionally malicious. The finding concerns the absence of version and integrity controls. ### Attack Path 1. A user follows the documented `pip install -r scripts/requirements.txt` instruction. 2. The package manager resolves the latest versions available from its configured package index. 3. If a selected release or package-index account has been compromised, attacker-controlled package code is downloaded. 4. Malicious code may execute during package installation or later when `feedparser` or `rapidfuzz` is imported. 5. That code executes with the permissions of the user running the installation or Skill. ### Impact Assessment A compromised resolved dependency could potentially: - Execute arbitrary code with the installing user's privileges - Read files and envi ...[truncated 343 chars]
Remediation
## Remediation Suggestions 1. Pin every runtime dependency to an explicitly reviewed version. 2. Generate and retain hashes for approved distributions, then install with `pip --require-hashes`. 3. Use a reproducible lock file produced by a dependency-management tool. 4. Separate runtime dependencies from development dependencies; move `pytest` to a dedicated test requirements file or development dependency group. 5. Configure installations to use a trusted package index and prohibit unintended supplemental indexes. 6. Regularly scan direct and transitive dependencies for known vulnerabilities. 7. Review and deliberately update the lock file rather than automatically resolving the newest available releases. 8. Run installation and execution in a minimally privileged virtual environment or container.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The implementation is a local RSS feed utility. It fetches one RSS URL over the network, parses entries, scores episodes against a query, optionally reranks semantically, and emits JSON for search/newest/overview modes. This partially overlaps with podcast episode discovery, but the declared description specifically mentions finding shows and episodes and generating wherever.audio links. The code does not construct wherever.audio links at all, and it does not perform show-level discovery; instead it requires an explicit RSS feed URL and works only within that feed. Therefore the description materially overstates/differs from the actual behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill explicitly instructs the agent to perform network access to a public endpoint and to read local files/scripts, but it declares no tool scope or permissions boundary. In agents that rely on manifest-declared capabilities for policy enforcement or user transparency, this creates an authority gap where the skill may invoke more capability than reviewers or runtime policy expect.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The trigger guidance includes broad phrases like 'latest episodes', 'show link', and named entities, which can cause the skill to auto-invoke on loosely related user requests. Unintended invocation can lead to unnecessary network access, incorrect task routing, or disclosure of external-query behavior when the user did not clearly ask for podcast lookup.

Unpinned Dependencies

Low
Category
Supply Chain
Content
feedparser
rapidfuzz
pytest
Confidence
93% confidence
Finding
The dependency `feedparser` is unpinned, which makes builds non-reproducible and allows future installs to silently pull a different version than the one originally tested. Because `feedparser` has known historical advisories and no version is constrained here, consumers cannot verify whether installation will resolve to a patched or vulnerable release.

Unverifiable Dependency: feedparser has 10 known advisory(ies) (CVE-2011-1157 (feedparser Cross-site Scripting vulnerability); CVE-2009-5065 (feedparser Cross-site Scripting vulnerability); CVE-2011-1158 (feedparser Cross-site Scripting vulnerability) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding
`feedparser` has known advisories, and because the manifest does not specify a version, it is impossible to determine whether deployments will install a safe or vulnerable release. In a podcast-discovery skill, `feedparser` likely processes untrusted RSS/Atom feed content, which makes dependency flaws more relevant because attacker-controlled feeds may reach the parsing logic.

Unpinned Dependencies

Low
Category
Supply Chain
Content
feedparser
rapidfuzz
pytest
Confidence
88% confidence
Finding
The dependency `rapidfuzz` is unpinned, so installations may resolve to different versions over time, introducing unexpected code changes or supply-chain risk. While no specific advisory is cited here, lack of version pinning weakens build integrity and makes security review difficult.

Unpinned Dependencies

Low
Category
Supply Chain
Content
feedparser
rapidfuzz
pytest
Confidence
91% confidence
Finding
The dependency `pytest` is unpinned, which permits uncontrolled version drift and may introduce vulnerable or incompatible releases into the environment. Even though `pytest` is typically a development dependency, unpinned test tooling can still affect CI/CD integrity and developer environments.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
80% confidence
Finding
`pytest` has known advisories and is unpinned, so the project cannot demonstrate that installed versions are unaffected. The practical risk is lower because `pytest` is generally test-only, but vulnerable test tooling can still impact CI runners, local developer machines, or release pipelines if exercised there.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The file-level docstring states this is tooling for a 'clawpod skill', while the provided manifest identifies the skill as 'podcast-discovery' for Wherever.Audio. This is an active documentation mismatch about the skill's intended identity and can mislead maintainers about which skill this code belongs to.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This code performs an outbound HTTP(S) request to a user-supplied RSS URL, which transmits system network activity and the configured User-Agent. While the operation is core to the tool's purpose, the file itself provides no docstring, comment, or user-facing output explaining that it will contact remote servers to fetch feed data.

Static analysis

No suspicious patterns detected.