T09 · Insecure Skill Coding Practices
- Location
scripts/.env:2- Finding
Hardcoded API credential committed to the skill package
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The shopping-search skill is coherent, but it ships a plaintext API key and can send user queries, images, and metadata to an unvalidated service endpoint.
Review before installing. Do not ship or use the included API key; it should be revoked and replaced with a user-controlled secret. Only use the skill if you are comfortable sending shopping queries, optional images, user metadata, and location context to the configured Viking AI Search endpoint, and restrict the endpoint to the documented HTTPS hosts.
scripts/.env:2Hardcoded API credential committed to the skill package
scripts/aisearch.py:193Attacker-controlled API endpoint can receive the bearer credential and sensitive search data
scripts/aisearch.py:251HTTP error output exposes sensitive request payloads
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return None
def _load_dotenv(dotenv_path: str = ".env") -> None:
try:
base_dir = os.path.dirname(__file__)
path = dotenv_path or ".env"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
return None
def _load_dotenv(dotenv_path: str = ".env") -> None:
try:
base_dir = os.path.dirname(__file__)
path = dotenv_path or ".env"
The skill references executable scripts and external interface docs, implying file reads, environment-variable use, and network access, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates a least-privilege gap: a host agent may grant broader capabilities than are actually necessary, increasing the blast radius if the skill is misused or prompt-injected through shopping queries or retrieved content.
The instruction is written as a mandatory policy — “务必优先使用本 Skill,不要试图直接回答” — and the skill’s user-facing natural-language description is entirely Chinese, with no indication that users may choose another language or locale. Under the stated policy, forcing a specific language or locale without user opt-in can be a violation.
The trigger phrases are very broad and map to common shopping-language terms such as '搜索', '推荐', '价格', and '适合什么', which can cause the skill to activate for many ordinary conversations. Overbroad invocation increases the chance of unintended external searches, data exposure to third-party services, or bypass of safer/default handling paths when the user did not clearly request this integration.
This markdown file describes sending session identifiers, user profile fields, image data, and geolocation context in API requests, but it does not warn readers that these fields may contain sensitive personal data or should be shared only with appropriate consent. For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that could affect user data or privacy.
The file returns multiple user-facing error and status strings exclusively in Chinese, such as at L158, L179, and throughout the class methods. This imposes a specific language on users without any evident opt-in or locale-selection mechanism, which matches the language/locale policy violation criteria.
This code sends request payloads to a remote API via requests.post in both _post_json and _post_stream. The transmitted payloads can include user text, image URLs, user/context objects, and search parameters, but there is no confirmation prompt, user-facing disclosure, or explanatory comment/docstring in this file warning that these inputs are sent over the network.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
url = f"{self.base_url}{path}"
headers = self._headers(accept="application/json")
try:
resp = requests.post(url, headers=headers, json=payload, timeout=self.timeout)
except requests.exceptions.RequestException as e:
raise RuntimeError(str(e)) from e
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
url = f"{self.base_url}{path}"
headers = self._headers(accept="text/event-stream")
try:
resp = requests.post(
url,
headers=headers,
json=payload,
The argument parser description, epilog, help strings, and runtime error messages are written in Chinese only, which imposes a specific language on all users without opt-in or an alternative locale. Under the language/locale policy rule, this is a natural-language policy issue because no language selection mechanism or justification is provided.
The chat path sends text, image URLs, user JSON, context JSON, and search parameters to the external Viking AI Search service, but this file provides no confirmation prompt or explicit user-facing disclosure at the point of transmission. The same concern applies to the search invocation later in the file, and the visible CLI help text describes parameters but does not warn that supplied data will be sent over the network.
该文件全文以中文编写,且未说明这是面向特定中文使用者或区域合规场景的限定文档。根据语言/区域策略,若技能或说明强制单一语言而未提供用户选择或明确 justification,可能构成自然语言层面的策略问题。
The dependency is specified as requests>=2.25.0, which permits installation of many future or older-compatible releases without guaranteeing a reviewed, fixed version. This weakens build reproducibility and can inadvertently pull in a vulnerable or incompatible release during deployment.
requests>=2.25.0
requests has multiple known advisories, and because the manifest does not pin the package version, there is no assurance that deployed environments will avoid affected releases. In a skill likely to interact with external services for search or shopping flows, use of a vulnerable HTTP client could expose credentials, request integrity, or sensitive data depending on the resolved version.
The script accepts an API key directly via --api-key and also references environment-based credentials when constructing the client, but there is no comment, help text, or user-facing disclosure about handling sensitive credentials. For a code-file audit under this rule, sensitive credential access without any disclosure is in scope.