T09 · Insecure Skill Coding Practices
- Location
api/geo_api.py:15- Finding
Hard-Coded Tavily API Credential Exposed in Source Code
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is mostly a brand-monitoring tool, but it exposes shared credentials and overstates important paid/API behavior, so users should review it before installing.
Install only if you are comfortable sending brand and competitor terms to third-party AI/search services and any configured Feishu webhook. Do not deploy the included API service as-is; rotate/remove the embedded Tavily key, replace shared placeholder API keys, add real entitlement/rate-limit checks, and clarify the actual platform coverage before relying on the reports.
api/geo_api.py:15Hard-Coded Tavily API Credential Exposed in Source Code
api/geo_api.py:19Published Shared API Key Grants Unauthorized Pro API Access
scripts/geo_quota.py:181Paid-Tier Authorization Can Be Enabled Without Entitlement Validation
api/requirements.txt:1Unbounded Dependency Constraints Produce Non-Reproducible Builds
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def search_brand_tavily(brand_name, max_results=5):
"""使用Tavily搜索品牌信息"""
try:
response = requests.post(
TAVILY_API_URL,
json={
"api_key": TAVILY_API_KEY,
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
Claiming to explain 'why not recommended,' support Feishu push, and monitor multiple keywords while only doing limited counting/search creates a material trust gap. In a brand-monitoring context, this can cause organizations to make operational or marketing decisions based on incomplete or fictitious analysis, and to assume notifications or broader coverage exist when they do not.
Claiming to explain 'why not recommended,' support Feishu push, and monitor multiple keywords while only doing limited counting/search creates a material trust gap. In a brand-monitoring context, this can cause organizations to make operational or marketing decisions based on incomplete or fictitious analysis, and to assume notifications or broader coverage exist when they do not.
Claiming to explain 'why not recommended,' support Feishu push, and monitor multiple keywords while only doing limited counting/search creates a material trust gap. In a brand-monitoring context, this can cause organizations to make operational or marketing decisions based on incomplete or fictitious analysis, and to assume notifications or broader coverage exist when they do not.
The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The skill has shell-command execution capability through subprocess.run, but that capability is not reflected in declared permissions. In an agent-skill environment, undeclared execution capability is dangerous because it weakens policy enforcement and can allow a skill that appears low-risk to invoke external binaries or expand behavior later without explicit user awareness.
The skill uses 'file_read' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The skill uses 'file_write' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The README explicitly advertises server-side relay and Feishu webhook integration, but it does not clearly warn users that brand queries, platform results, or notification content may be transmitted to the vendor's infrastructure or third-party services. In a monitoring skill that processes business-sensitive brand and competitor terms, this lack of disclosure can lead to unintended external data exposure and privacy/compliance risk.
The documentation advertises Tavily-based real-time search and server-side relay but does not prominently warn that user brand queries and resulting data may be transmitted to external services. This creates a privacy and data-governance risk, especially for sensitive competitive intelligence, internal brand campaigns, or confidential product names entered by users.
The module description and API responses are written in Chinese, and the outbound search query appends Chinese terms ("品牌 AI 服务") to every brand search. This imposes a specific language/locale behavior without user opt-in or an explicit documented regional justification.
The code embeds a live-looking Tavily API key as a default fallback in source. Hardcoded credentials are dangerous because anyone with code access can reuse the key, incur charges, abuse the linked account, and potentially access associated usage data; the brand-monitoring context increases risk because this service is explicitly internet-facing and depends on that key for all searches.
# Tavily API配置
TAVILY_API_KEY = os.environ.get('TAVILY_API_KEY', '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')
TAVILY_API_URL = "https://api.tavily.com/search"
# API认证(简易版:检查X-API-Key头)
API_KEYS = {
The manifest describes automatic searches on Kimi、讯飞星火、文心一言、智谱等AI平台 and support for 飞书推送, implying platform-specific AI visibility monitoring. In this implementation, the core behavior is a single POST to Tavily's generic search API, with no code for querying those AI platforms or sending Feishu notifications, so the actual behavior is materially narrower than the claimed functionality.
This endpoint sends user-provided brand queries and a server-side API key to an external service. External transmission is expected for functionality, but in this skill context it still creates data-sharing risk because user inputs may reveal commercially sensitive monitoring targets, and there are no visible controls for disclosure, minimization, or allowlisting beyond the fixed endpoint.
def search_brand_tavily(brand_name, max_results=5):
"""使用Tavily搜索品牌信息"""
try:
response = requests.post(
TAVILY_API_URL,
json={
"api_key": TAVILY_API_KEY,
User-supplied brand data is transmitted to a third-party search provider without any visible consent, notice, or minimization controls in this code. In a brand-monitoring skill, users may submit sensitive client, campaign, or stealth-brand terms; silently disclosing them to an external service can create confidentiality and compliance risk.
This Python file contains user-facing natural-language strings and docstrings entirely in Chinese, including the module description and console output. Under the policy, forcing a specific language without user opt-in can be a locale-policy violation, and there is no indication that this skill is intentionally region-specific or that another language is supported.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def test_search(brand="91tokenhub"):
"""测试搜索"""
resp = requests.post(
API_URL,
headers={"X-API-Key": TEST_KEY},
json={"brand": brand, "max_results": 5}
The config sets the report language to "zh-CN" unconditionally. Forcing a specific language/locale in configuration without any stated opt-in or alternative can violate language-choice policy requirements.
When AI_ENDPOINT is configured, the skill sends brand names, GEM scores, and summarized search-result snippets to an external AI service. This external transmission may expose potentially sensitive business intelligence or customer data, and the risk is elevated by the skill's context because it analyzes monitoring data that could include proprietary campaign or competitor information.
# ⚠️ 如需启用AI分析功能,请在此填入您的AI接口地址
# 例如:https://your-api-server.com/v1/chat/completions
# 当前默认使用本地分析框架(见 _get_fallback_analysis)
AI_ENDPOINT = "" # <-- 填入AI接口地址,如 https://api.minimax.chat/v1/chat/completions
if not AI_ENDPOINT:
return self._get_fallback_analysis()
This code path executes an external command to contact an AI service, creating an unnecessary command-execution surface for a task that only requires HTTP. While the current command is static and not obviously injectable, subprocess-based network calls increase operational risk, inherit environment behavior, and make future misuse easier if endpoint, headers, or arguments become configurable.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
resp = json.loads(result.stdout)
return resp.get("choices", [{}])[0].get("message", {}).get("content", "")
except Exception as e:
All user-facing messages and documentation strings in the file are in Chinese, with no indication that language is selectable or tied to a region-specific requirement. This creates a language/locale policy issue because the skill effectively forces one language without user opt-in.
No suspicious patterns detected.