T09 · Insecure Skill Coding Practices
- Location
rss_reader.py:33- Finding
API Credential Disclosure Through an Unrestricted AI Endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This RSS skill appears purpose-built rather than malicious, but it needs review because it can repeatedly fetch arbitrary URLs and send API keys plus RSS-derived data to configurable external services.
Install only if you are comfortable with RSS titles, links, summaries, and generated reports being sent to the AI provider and, if configured, to Feishu/Lark. Use only public feed URLs, avoid localhost/private/internal feed addresses, keep OPENAI_BASE_URL fixed to a trusted provider, protect the API key and webhook values, and review the cron command before enabling automatic refreshes.
rss_reader.py:33API Credential Disclosure Through an Unrestricted AI Endpoint
rss_reader.py:190Server-Side Request Forgery Through User-Supplied RSS URLs
requirements.txt:1Unpinned Third-Party Dependencies Permit Unreviewed Future Releases
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
try:
response = requests.post(
f"{OPENAI_BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {OPENAI_API_KEY}",
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
try:
response = requests.post(
f"{OPENAI_BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {OPENAI_API_KEY}",
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
response = requests.post(
FEISHU_WEBHOOK_URL,
json=message,
timeout=10
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
base_url = os.getenv("OPENAI_BASE_URL", "https://open.bigmodel.cn/api/paas/v4")
api_url = base_url if base_url.endswith("/chat/completions") else f"{base_url}/chat/completions"
response = requests.post(
api_url,
headers={
"Authorization": f"Bearer {api_key}",
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
response = requests.post(webhook_url, json=payload, timeout=10)
if response.status_code == 200:
result = response.json()
if result.get("StatusCode") == 0:
This markdown file instructs users to initialize a Git repository and push the entire skill directory to a public hosting service, but it does not warn users to review files for secrets, local data, or generated artifacts before publishing. Because this action can affect privacy and data integrity, a user-facing warning is expected in the documentation.
The README explicitly documents configuring a Feishu webhook for pushing RSS-derived summaries, but it does not clearly warn users that article content, extracted summaries, or metadata may be transmitted to an external third-party service. In a skill that also performs AI summarization and automated scheduled refreshes, this can lead to unintentional disclosure of internal or sensitive feed content, especially if users subscribe to private or semi-private RSS sources.
The skill documentation describes capabilities that require environment-variable access, filesystem reads/writes, and network access, but it does not declare any explicit tool scope or permissions boundary. This creates an authorization mismatch: users and platforms cannot easily understand or constrain what the skill may access, increasing the risk of unintended data exposure or over-privileged execution.
The skill description emphasizes AI summarization and Feishu push, but it does not clearly warn users that article metadata and generated summaries will be transmitted to third-party AI and messaging services. This is dangerous because users may invoke the skill assuming local processing, while the skill can disclose reading interests, selected sources, titles, and summary content to external providers.
The trigger phrases are broad enough to match ordinary conversation about subscriptions, summaries, or RSS-like topics, which can cause the skill to activate unexpectedly. In this skill's context, unintended activation is more dangerous because activation can lead to external network requests, automatic subscription creation, article processing, and possible Feishu/AI transmission without sufficiently explicit user intent.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export OPENAI_API_KEY="sk-xxx"
export OPENAI_BASE_URL="https://api.openai.com/v1"
💡 智谱 AI 优势:
The manifest text, including the description and all declared commands, is exclusively in Chinese. This can amount to a language/locale policy issue because the skill appears to require a specific language without documenting opt-in, alternatives, or a justified region-specific scope.
The skill transmits article content and metadata to an external AI provider when generating summaries, but there is no explicit runtime warning or consent gate at the point of execution. In a content-aggregation skill, feeds may include proprietary, internal, or sensitive subscription sources, so silent exfiltration to a third party creates a real privacy and compliance risk.
This call sends article content to an external AI service. In this skill's context, outbound transmission is core functionality, but it is still a genuine data-exposure surface because RSS items may contain sensitive text and the transfer occurs without minimizing or classifying content sensitivity.
content_clean = re.sub(r'<[^>]+>', '', content)[:1500]
try:
response = requests.post(
f"{OPENAI_BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {OPENAI_API_KEY}",
The summarization prompt explicitly instructs the model to respond in concise Chinese, and the rest of the CLI/help text is also fixed in Chinese. This imposes a language choice without user opt-in, which matches the policy-violation category for locale or language constraints.
The batch summarization path instructs the model in Chinese and requests concise Chinese summaries for all articles. Because no language preference mechanism is provided, the skill enforces a specific language by default rather than offering user choice.
The batch-summary path transmits multiple article titles and summaries to an external AI service, increasing the volume of exposed data in a single request. Although intended behavior, it represents a real privacy/compliance risk when feeds include non-public or sensitive material.
prompt += "\n\n请按以下格式输出:\n1. [摘要内容]\n2. [摘要内容]\n..."
try:
response = requests.post(
f"{OPENAI_BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {OPENAI_API_KEY}",
This webhook send transmits article title, summary, source, and link to an external collaboration platform. Because the skill automatically distributes content outside the local environment, it creates a real information-sharing risk if feeds or generated summaries contain sensitive or internal material.
}
try:
response = requests.post(
FEISHU_WEBHOOK_URL,
json=message,
timeout=10
The daily-report generation sends a consolidated set of article titles and sources to an external AI provider. Aggregated metadata can itself be sensitive because it reveals monitoring interests, internal topics, or research focus, making this more than a harmless network call.
base_url = os.getenv("OPENAI_BASE_URL", "https://open.bigmodel.cn/api/paas/v4")
api_url = base_url if base_url.endswith("/chat/completions") else f"{base_url}/chat/completions"
response = requests.post(
api_url,
headers={
"Authorization": f"Bearer {api_key}",
The code automatically pushes the generated report, including article titles and links, to Feishu without an explicit execution-time confirmation. This can leak aggregated reading activity or sensitive feed contents to a broader audience than intended, especially because report push happens automatically after refresh/report flows.
This sends the full generated report to Feishu, potentially exposing aggregated insights, titles, and links to a configured external destination. In this skill, automatic post-refresh/report pushing makes the risk more concrete because distribution can happen without an additional human review step.
}
try:
response = requests.post(webhook_url, json=payload, timeout=10)
if response.status_code == 200:
result = response.json()
if result.get("StatusCode") == 0:
A natural-language policy issue exists because the skill documentation forces a specific language presentation for all users without any opt-in or alternative language path. The file does not indicate that the skill is region-specific or that Chinese is required for compliance or audience constraints.
Natural-language instructions, commands, and operational guidance are written entirely in Chinese, including the invocation examples and cron prompt text. There is no indication that the skill is region-specific or that alternative language support is available, which can violate a language-choice policy.
Although the file states that 18 feeds are auto-added on first use, it is presented as a feature rather than a caution about modifying the user's subscription state. Since this changes stored user data/configuration automatically, a clearer warning would better disclose the behavior.
The design section explicitly states '单篇摘要 ❌(已移除)' and '不做单篇摘要', indicating the skill no longer performs per-article summaries. However, later documentation reintroduces 'AI 摘要' as an active feature in the feature table, FAQ, changelog, and examples, which contradicts the stated intent and can mislead users about what the skill actually does.
No suspicious patterns detected.