Back to skill

Security audit

中文播客雷达

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate Chinese-podcast discovery purpose, but one helper can fetch arbitrary URLs instead of only Xiaoyuzhou pages, creating a review-worthy network-scope risk.

Review before installing if your agent runs with broad network access. The core ranking use case is understandable, but enrichment should be limited to trusted Xiaoyuzhou URLs or run in a sandbox that cannot reach localhost, private networks, or metadata services.

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

Warning
Location
scripts/enrich_xiaoyuzhou.py:88
Finding

Arbitrary URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
Dict[str, Any]: request = Request( url, headers={ "User-Agent": USER_AGENT, "Accept": "text/html,application/xhtml+xml", "Accept-Encoding": "gzip", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", }, ) with urlopen(request, timeout=30) as response: content_encoding = (response.getheader("Content-Encoding") or "").lower() decompressor = zlib.decompressobj(16 + zlib.MAX_WBITS) if "gzip" in content_encoding else None chunks: List[bytes] = [] total_read = 0 while total_read < MAX_READ_BYTES: raw_chunk = response.read(READ_CHUNK_SIZE) if not raw_chunk: break total_read += len(raw_chunk) chunk = decompressor.decompress(raw_chunk) if decompressor else raw_chunk if chunk: chunks.append(chunk) payload = extract_next_data_from_html_bytes(b"".join(chunks)) if payload is not None: return payload raise ValueError("Could not find __NEXT_DATA__ within the read limit.") ``` ```python def extract_urls_from_payload(payload: Any) -> List[str]: if isinstance(payload, list): items = payload elif isinstance(payload, dict): items = payload.get("items", []) else: return [] urls: List[str] = [] for item in items: if isinstance(item, str): urls.append(item) continue if not isinstance(item, dict): continue if item.get("kind") == "episode" and item.get("episodeUrl"): urls.append(item["episodeUrl"]) ...[truncated 3647 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/enrich_xiaoyuzhou.py:62
Finding

Advertised Twenty-URL Hard Cap Is User-Overridable

Content
View full analysis
args.max_items: raise SystemExit( f"Refusing to enrich {len(urls)} URLs. Narrow the shortlist to {args.max_items} or fewer first." ) ``` ### Technical Analysis The documentation and command-line help identify twenty URLs as a hard enrichment cap. The implementation instead compares the number of URLs against the user-controlled `--max-items` value. A caller can pass an arbitrarily large positive value, such as `--max-items 100000`, causing the supposed hard limit to become 100,000 URLs. There is no independent constant that limits the accepted value to twenty. This discrepancy weakens the intended abuse prevention and request-throttling safeguards. The requests are sequential and delayed by default, but the caller can also reduce `--sleep-seconds` and `--jitter-seconds` to zero. ### Attack Path 1. An attacker or untrusted workflow supplies a JSON document containing more than twenty enrichment URLs. 2. The script is invoked with `--max-items` set to a value equal to or greater than the number of supplied URLs. 3. The `len(urls) > args.max_items` condition evaluates to false. 4. The caller optionally sets `--sleep-seconds 0 --jitter-seconds 0`. 5. The script sends a request for every supplied URL instead of enforcing the documented twenty-request ceiling. ### Impact Assessment The bypass does not by itself provide additional system privileges. Its impact is primarily operational: - Excessive outbound requests. - Increased execution time and resource use. - Remote service rate limiting or blocking. - Violation of the Skill's stated n ...[truncated 260 chars]
Remediation
View remediation
effective_max: raise SystemExit( f"Refusing to enrich {len(urls)} URLs. " f"Narrow the shortlist to {effective_max} or fewer first." ) ``` Alternatively, remove `--max-items` and always enforce twenty as the fixed maximum. Additional hardening should include: - Set minimum permitted request delays if rate limiting is a security requirement. - Apply a total execution deadline. - Apply a global request budget outside the script when run by an Agent. - Limit the size and number of items accepted from `--from-json`. - Record rejected bulk-enrichment attempts for monitoring. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/enrich_xiaoyuzhou.py:98
Finding

Compressed Response Limit Does Not Bound Decompressed Data

Content
View full analysis
Remediation
View remediation
remaining: raise ValueError("Decompressed response exceeded the size limit.") buffer.extend(chunk) payload = extract_next_data_from_html_bytes(bytes(buffer)) if payload is not None: return payload ``` For stronger efficiency, replace repeated full-buffer regular-expression searches with a bounded streaming parser or search only the newly extended relevant window. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Treat the directory containing this `SKILL.md` as the skill root.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill invokes local Python scripts that read local reference files and make outbound network requests, but it does not declare any explicit tool scope such as permissions or allowed-tools. In hosts that rely on manifest-declared scoping, this creates an authorization gap where network and file-read behavior may execute without clear user- or platform-visible constraints, increasing the chance of unintended data access or external requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The prompt instructs the skill to treat casual requests in Chinese in a specific way and is embedded as the default behavior. This creates a language/locale constraint without indicating that the user can choose another language or opt into this behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document states that 'In Chinese, users often say 播客 loosely' and then sets a 'Default interpretation' that remaps several user phrases to episode-level results first. This imposes a language-specific behavior for Chinese phrasing without indicating user choice or opt-in, which matches the policy concern about locale/language-specific handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Line L09 includes a hardcoded Chinese phrase (热门播客) as part of the output-mode behavior, which suggests a locale-specific assumption without any stated user opt-in or language choice. Under the policy rule, forcing or assuming a specific language without explicit choice can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

This markdown guidance mixes English with Chinese-specific title markers and topic categories such as 第 14 期, 对话某某, and 女性 / 国际 / 媒体 / 电影 / 音乐, implying the skill is tailored to Chinese-language content. Because the document does not explicitly state that the skill is region- or platform-specific in a way that justifies the locale constraint, nor does it offer a language choice, it may violate the language/locale policy criterion.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The module description explicitly targets 中文播客榜, and the parsing logic relies on Chinese-language keywords and labels throughout the file. There is no natural-language indication that this locale restriction is optional or user-selectable, which can violate a language/locale choice policy unless clearly documented as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code performs HTTP requests to xyzrank.com to fetch ranking data, but there is no confirmation prompt, print/log disclosure, or warning comment around the external data transfer. Because the script silently contacts a third-party service, users may not realize that running it will initiate network activity.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.