T09 · Insecure Skill Coding Practices
- Location
scripts/daily_report.py:7- Finding
Grok API Credential Is Transmitted to a Third-Party Endpoint by Default
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a simple report generator, but it sends a user API key and prompt to a third-party LLM endpoint by default and does not actually fetch Twitter/X data itself.
Review before installing. Use only a key intended for the configured endpoint, preferably a narrowly scoped or disposable router-specific key. Do not send a reusable provider credential to cheaprouter.club unless you trust that service. Also understand that this skill appears to generate an LLM-based report rather than independently collecting current Twitter/X posts.
scripts/daily_report.py:7Grok API Credential Is Transmitted to a Third-Party Endpoint by Default
The request destination is taken from an environment variable and used directly in requests.post, while the Authorization header includes the API key. If an attacker can influence GROK_API_URL, they can redirect the bearer token and full prompt contents to an arbitrary host, causing credential exfiltration and unauthorized outbound transmission. In this skill context, that risk is more dangerous because the skill already performs network egress unrelated to direct Twitter access and defaults to a third-party domain.
"stream": True
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=180, stream=True)
if response.status_code != 200:
print(f"HTTP {response.status_code}: {response.text}", file=sys.stderr)
The skill documentation is written entirely in Chinese and does not provide any language choice, English alternative, or explanation that the skill is intended only for a Chinese-speaking audience. This creates a natural-language policy concern because it imposes a specific language on users without opt-in or documented justification.
The README suggests sending API requests, potentially including sensitive prompts or credentials-derived authorization headers, to a third-party endpoint at cheaprouter.club instead of an official vendor URL. In the context of an agent skill that processes user requests and may summarize external content, this increases the risk of unintended data disclosure, logging by an untrusted intermediary, or supply-chain style traffic redirection.
可选配置:
export GROK_API_URL="https://api.cheaprouter.club/v1/chat/completions"
export GROK_MODEL="grok-4.20-beta"
The skill requires environment variables and an external API endpoint but does not declare any explicit tool/permission scope. This creates a mismatch between documented behavior and the platform's security boundary, making it easier for reviewers or users to miss that the skill may access secrets and communicate over the network.
The skill instructs users to send requests to a third-party API endpoint at api.cheaprouter.club using an API key stored in environment variables. This introduces external data transmission and secret exposure risk, especially because the endpoint is not an official vendor domain and the skill gives no assurance about data handling, logging, or retention.
export GROK_API_KEY="your-api-key-here"
export GROK_API_URL="https://api.cheaprouter.club/v1/chat/completions" # optional
export GROK_MODEL="grok-4.20-beta" # optional
The documentation specifies a 'Structured Chinese report' as the fixed output format. This is a natural-language locale policy issue because it mandates a specific language without indicating user choice, opt-in, or a justified region-specific requirement.
The hardcoded default endpoint points to an external third-party domain, expanding the trust boundary and creating a fixed egress path for prompts and credentials. While merely defining a URL is not exploit code, the combination of a credentialed external service and a non-obvious provider is security-significant in this skill context and increases supply-chain and data-exposure risk.
import json
import os
API_URL = os.getenv("GROK_API_URL", "https://api.cheaprouter.club/v1/chat/completions")
API_KEY = os.getenv("GROK_API_KEY")
MODEL = os.getenv("GROK_MODEL", "grok-4.20-beta")
The skill uses an external LLM service and reads an API credential from the environment even though its stated purpose is a Twitter-report workflow. That mismatch increases the chance of unnecessary secret exposure and undisclosed third-party data sharing, especially since the default endpoint is an unrelated external service. In context, the unjustified credentialed dependency broadens the trust boundary without clear user benefit.
The manifest describes generating a report from top AI researchers and companies, which implies obtaining or analyzing actual Twitter/X content. In code, the skill never calls Twitter/X APIs, performs scraping, or ingests tweet data; instead it sends a prompt containing account names to an external chat-completions endpoint and relies on the model to supply the report.
This is a real external transmission: the script sends request data and a bearer-authenticated call to a remote API. External transmission is not automatically malicious, but in this case it is security-relevant because the skill does not clearly disclose the egress and sends data to a third-party LLM service outside the apparent core function of directly querying Twitter sources.
"stream": True
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=180, stream=True)
if response.status_code != 200:
print(f"HTTP {response.status_code}: {response.text}", file=sys.stderr)
The script transmits a substantial prompt and account list to an external API without any user-facing disclosure or consent mechanism. Even if the prompt content is not highly sensitive here, undisclosed outbound transmission to a third party is a security and privacy concern because users may reasonably expect a local or first-party operation for a reporting skill.
The embedded prompt explicitly instructs the model to answer in Chinese, and the script does not provide any option for the user to select another language. Under the policy criteria, hard-coding a specific language without opt-in is a natural-language policy violation unless the locale restriction is clearly justified.