T09 · Insecure Skill Coding Practices
- Location
scripts/fetch-news.py:35- Finding
Untrusted RSS Content Is Written to Markdown Without Sanitization
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is not overtly malicious, but its documentation overstates capabilities and requests trust for services and credentials that the shipped code does not actually implement.
Review this before installing. Use it only with public RSS feeds unless translation is disabled or clearly understood, do not provide API tokens unless the implementation is updated to use them safely, and treat generated Markdown as untrusted content when opening it in rich renderers. The package should be corrected to match its documentation, disclose third-party translation, sanitize feed content, and pin dependencies.
scripts/fetch-news.py:35Untrusted RSS Content Is Written to Markdown Without Sanitization
requirements.txt:1Dependency Set Is Unpinned, Unhashed, and Missing a Runtime Dependency
The skill claims broad multi-source collection and summarization, but the reported code behavior only handles RSS while also performing translation and local file writes that are not disclosed in the description. Hidden or overstated capabilities are dangerous because users may authorize the skill under false assumptions about what data is collected, transmitted, or stored.
The skill claims broad multi-source collection and summarization, but the reported code behavior only handles RSS while also performing translation and local file writes that are not disclosed in the description. Hidden or overstated capabilities are dangerous because users may authorize the skill under false assumptions about what data is collected, transmitted, or stored.
The skill documentation declares file-read and file-write capable behavior but does not define any tool scope or permission boundary. In an agent setting, missing explicit scoping increases the chance of over-broad filesystem access, unexpected reads/writes, or unsafe execution assumptions by users and orchestrators.
The markdown omits a clear warning that the skill sends requests to multiple external services and may transmit query content, fetched data, or credentials off-system. In a news-digest workflow this increases privacy and token-handling risk because users may provide API keys or input topics without realizing that third parties will process the data.
The manifest description and all user-facing documentation are written only in Chinese, with no indication that language can be selected or changed. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.
The natural-language description and implementation indicate mandatory Chinese translation and output, including target='zh-CN' and Chinese-only digest fields. This enforces a specific language/locale without any user opt-in or documented justification.
The script sends feed titles and summaries to GoogleTranslator, which discloses third-party content to an external service without any explicit notice, consent, or configuration control. In this skill context, news feeds are usually public, so the risk is reduced, but private/internal feeds or sensitive source URLs could still leak content externally.
The script hard-codes translation target 'zh-CN' and the surrounding strings/docstrings indicate the output is intended to be Chinese. This enforces a specific language/locale behavior without offering the user any choice or opt-in, which matches the language-policy violation criteria.
The manifest describes a skill that collects tech news from RSS, Twitter, GitHub, and Web Search, then generates a combined summary. In this file, the main loop explicitly processes only sources whose type is "rss", with no code handling Twitter, GitHub, or web search inputs, creating a clear mismatch between the stated capability and actual behavior.
This text digest is primarily presented in Chinese, but several headlines and summaries remain in English, with no indication that the user opted into mixed-language output or that the digest is region-specific. That creates a natural-language policy concern under the language/locale rule because the file effectively forces a mixed presentation without documented choice or justification.
The instructions show writing output to /tmp/td-merged.json but do not explicitly warn users that the pipeline persists fetched and summarized content to disk. Undisclosed persistence can expose potentially sensitive queries, article selections, or generated summaries to other local users, backup systems, or later processes.
This JSON manifest defines multiple enabled external RSS URLs, which implies the skill will make outbound network requests and transmit system metadata such as IP address and request headers to third-party services. Because this is a manifest file, there is no visible user warning, comment, or disclosure here describing that behavior.
This JSON config contains user-facing text in Chinese alongside English, such as the label and description for the LLM topic. Because the file does not indicate that users can choose their language or that the locale is intentionally region-specific, it may impose a language/locale experience without explicit opt-in.
The AI Agent topic description is presented in Chinese while the surrounding configuration is mixed-language. Without any accompanying note that this configuration is for a Chinese-speaking audience or that language choice is configurable, this can conflict with language/locale policy expectations.
The coding topic label and description are user-facing strings in Chinese, but the file provides no indication that users selected this locale or that the skill is region-specific. This may constitute a language/locale policy issue where the experience is constrained without documented choice.
The dependency is specified with a lower-bound constraint only, which makes builds non-reproducible and allows installation of different versions over time. In a skill that aggregates untrusted external content from RSS, Twitter, GitHub, and web search, supply-chain exposure matters because an unexpected or vulnerable upstream release could be pulled in during deployment.
feedparser>=6.0.0
requests>=2.31.0
python-dateutil>=2.8.0
The manifest references feedparser without pinning a version, and the package has multiple historical advisories. That does not prove the deployed version is vulnerable, but it does mean the project cannot demonstrate it is using a safe release; in a news-ingestion skill that parses untrusted feeds, this uncertainty is more relevant because malformed external content may directly exercise parser bugs.
requests>=2.31.0 permits any newer version, so the installed package may vary across environments and time. Because this skill fetches data from external network sources, using an unpinned HTTP client increases supply-chain and patch-verification uncertainty, including the possibility of pulling a release later found to be flawed.
feedparser>=6.0.0
requests>=2.31.0
python-dateutil>=2.8.0
The manifest does not pin requests, so despite known advisories affecting some releases, there is no reliable way to verify whether the installed version is safe. This is meaningful in context because the skill performs outbound HTTP requests to multiple external sources, making the security properties of the HTTP client materially important.
python-dateutil>=2.8.0 is also unpinned, creating the same reproducibility and supply-chain uncertainty as the other entries. While this package is less obviously exposed than the network-facing libraries, permitting arbitrary newer versions still weakens build integrity and complicates vulnerability management.
feedparser>=6.0.0
requests>=2.31.0
python-dateutil>=2.8.0
The manifest description says the skill fetches tech news from RSS, Twitter, GitHub, and Web Search, then generates a summary. In this file, the source loop explicitly filters to sources where type == "rss", so the implemented behavior is narrower than the claimed multi-source capability.
The description suggests integrated summarization across multiple fetched sources. Here, the code formats up to 10 RSS items and writes each item's translated/truncated summary into a text file, which is more of a compiled digest than a synthesized summary.
The code saves both a JSON file and a text digest to disk, but there is no prior warning in comments, docstrings, or user-facing output that files will be created or overwritten. For a code-file review, file writes should have some visible disclosure unless clearly documented as part of the skill behavior.
This markdown file presents all article titles and summaries in Chinese, including translated headings and descriptions, with no indication that the language was user-selected or that the skill is intended for a Chinese-only audience. The policy specifically flags language or locale constraints when a specific language is imposed without user opt-in.
This JSON data includes bilingual fields such as "title" and "title_cn", but several summary fields remain in English while most localized content is Chinese. Because SQP-3 applies to all file types, this presents a language/locale policy concern if the skill implicitly serves mixed-language content without explicit user opt-in or a documented locale scope.
No suspicious patterns detected.