T09 · Insecure Skill Coding Practices
- Location
config.json:1- Finding
Messaging Credentials Are Stored in a Plaintext Project Configuration File
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does what it claims, but it needs review because it stores messaging credentials in a local config file and sends trading reports to third-party chat services.
Install only if you are comfortable giving the skill outbound network access and storing messaging credentials locally. Move real tokens/webhooks out of config.json if possible, restrict bot and webhook permissions, verify every configured chat destination, and remember that the generated trading calls are not investment advice.
config.json:1Messaging Credentials Are Stored in a Plaintext Project Configuration File
scripts/advise.py:54Runtime Access to an Undisclosed Secondary Market-Data Service
The declared behavior materially differs from the implemented behavior: the README promises AI analysis, trade-entry recommendations, and multi-platform pushing, while static analysis indicates those capabilities are absent or incomplete and that external CoinEx dependency is underdisclosed. This mismatch is dangerous because users may trust the skill for financial decision-making or enable it in environments with external connectivity based on misleading documentation, causing unsafe reliance and unexpected data flows.
The skill description and setup guidance are written in Chinese, and the file does not indicate that the skill is intended only for a Chinese-speaking or region-specific audience, nor does it offer an English or user-selectable language option. Under the policy rule for natural-language constraints, this is a locale/language restriction without opt-in or justification.
The skill advertises network-dependent behavior and external data/push integrations, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization and transparency gap: an agent or reviewer cannot easily constrain or reason about what outbound access the skill requires, increasing the risk of unintended network use or data exfiltration through misconfiguration or future code changes.
The skill description does not define clear activation constraints, trigger conditions, or examples, so an agent may invoke it too broadly whenever cryptocurrency topics appear. Overbroad invocation can lead to unnecessary external requests, unintended messaging actions, or financial-analysis outputs in contexts where the user did not explicitly request them.
The skill states that it auto-pushes analysis every 30 minutes to external platforms, but it does not prominently warn users about the ongoing automated external transmission of generated content. In context, this is more dangerous because the skill integrates with multiple messaging channels, so users may unknowingly enable recurring outbound notifications that disclose trading-related information or create spam/abuse risks.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"""Fetch market sentiment data"""
try:
import urllib.request
r = urllib.request.urlopen("https://api.gateio.ws/api/v4/futures/usdt/tickers?contract=BTC_USDT", timeout=5)
d = json.loads(r.read())
if isinstance(d, list) and len(d) > 0:
return {"funding": float(d[0].get("funding_rate", 0)) * 100}
The skill generates all user-facing advice strings in Chinese, including recommendations and warnings, with no option for the user to select a language. This is a natural-language policy issue because it imposes a specific locale on all users without opt-in or documented regional scope.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"""Check prices for BTC and ETH - CoinEx API (China accessible)"""
import json, urllib.request
COINEX = "https://api.coinex.com/v1"
def get_price(symbol):
try:
The hardcoded Telegram API endpoint indicates intentional external transmission of report data to a third-party platform. In this skill's context, that is security-relevant because trading reports are likely to be sensitive and their routine export increases the chance of disclosure through configuration mistakes or compromised bot credentials.
try:
# TG消息不能太长,截断
msg = text[:3000] if len(text) > 3000 else text
url = f"https://api.telegram.org/bot{t['bot_token']}/sendMessage"
data = json.dumps({"chat_id": t["chat_id"], "text": msg, "parse_mode": "Markdown"}).encode()
r = urllib.request.urlopen(urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}), timeout=10)
return r.status == 200, "Telegram OK" if r.status == 200 else f"TG HTTP {r.status}"
This code transmits the generated report to Telegram, an external third-party service, which is a real outbound data flow. In the context of a trading-analysis skill, reports may contain sensitive or proprietary strategy information, so sending them externally without validation, minimization, or user confirmation creates confidentiality risk.
msg = text[:3000] if len(text) > 3000 else text
url = f"https://api.telegram.org/bot{t['bot_token']}/sendMessage"
data = json.dumps({"chat_id": t["chat_id"], "text": msg, "parse_mode": "Markdown"}).encode()
r = urllib.request.urlopen(urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}), timeout=10)
return r.status == 200, "Telegram OK" if r.status == 200 else f"TG HTTP {r.status}"
except Exception as e:
return False, f"TG异常: {e}"
This sends report content to a Discord webhook URL, which is an external endpoint that may expose trading intelligence to unintended parties if the webhook is leaked, misconfigured, or shared. Because webhook URLs act as bearer secrets, any misuse or compromise can result in silent exfiltration of the report.
try:
msg = text[:1800] if len(text) > 1800 else text
data = json.dumps({"content": f"```{msg}```"}).encode()
r = urllib.request.urlopen(urllib.request.Request(d["webhook_url"], data=data, headers={"Content-Type": "application/json"}), timeout=10)
return r.status == 204, "Discord OK"
except Exception as e:
return False, f"Discord异常: {e}"
This posts the report to a WeCom webhook, creating an external transmission channel for potentially sensitive trading content. If the webhook is misrouted, leaked, or the receiving channel has broad membership, confidential analysis can be exposed beyond the intended audience.
try:
msg = text[:2000] if len(text) > 2000 else text
data = json.dumps({"msgtype": "text", "text": {"content": msg}}).encode()
r = urllib.request.urlopen(urllib.request.Request(w["webhook_url"], data=data, headers={"Content-Type": "application/json"}), timeout=10)
return r.status == 200, "企微OK"
except Exception as e:
return False, f"企微异常: {e}"
The script automatically sends the generated trading report to all configured third-party messaging platforms without any confirmation, review step, or explicit consent at send time. Because reports may contain sensitive trading signals, account-related context, or other proprietary information, this creates a real data leakage risk if the configuration is wrong, shared, or compromised.
The skill description and instructions are entirely in Chinese and mention a China-specific data source connection, but they do not state that the skill is intentionally region- or language-specific or provide user opt-in for language preference. This can violate language/locale policy when users are not given a documented choice or justification.
The manifest description is written entirely in Chinese and presents the skill as a trading analysis system without any indication that language is configurable or that the Chinese-only locale is an intentional regional constraint. Under the policy, natural-language content that forces a specific language without user opt-in can be a locale-policy violation.
Several docstrings and user-facing status/error strings are presented only in Chinese, such as the timeout message and platform status messages. This can violate language/locale policy when the skill forces a specific language without user opt-in or a documented regional justification.
No suspicious patterns detected.