T09 · Insecure Skill Coding Practices
- Location
scripts/fetch.py:35- Finding
Arbitrary Python Code Execution Through Unsafe URL Interpolation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a legitimate webpage-fetching purpose, but it ships unsafe code that can execute injected Python from a crafted URL and includes live-format billing behavior and credentials that need review before installation.
Review before installing. Do not run this skill on private, tokenized, internal, or sensitive URLs. The publisher should remove the hardcoded SkillPay key, rotate it, add explicit billing consent, make third-party proxying opt-in, block internal network targets, and replace python -c URL interpolation with safe argument passing before broad use.
scripts/fetch.py:35Arbitrary Python Code Execution Through Unsafe URL Interpolation
scripts/fetch_paid.py:104Arbitrary Python Code Execution in the Paid Fetching Script
scripts/fetch_paid.py:15Hardcoded SkillPay API Credential in Distributed Source Code
references/skill.json:6Unpinned Dependencies and Mutable Installation Sources
scripts/fetch.py:103Disclosure of Complete Target URLs to an External Jina Proxy
The README advertises a paid mode with 'automatic charging' and shows usage that triggers billing, but it does not clearly warn users about financial impact, consent flow, or when charges occur. In a skill context, this increases the risk of users invoking paid actions unintentionally or integrating the tool without adequate safeguards around spending.
The README includes direct billing API examples for balance checks and account charging, including API-key-based authentication, but omits prominent warnings about secret handling and irreversible billing actions. This is dangerous because users may copy/paste charging commands or expose credentials in shell history, logs, or shared environments, leading to unauthorized or accidental charges.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -X GET "https://skillpay.me/api/v1/billing/balance?user_id=xxx" \
-H "X-API-Key: YOUR_API_KEY"
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
The trigger list includes generic phrases like '抓取网页', '爬取内容', '无法访问', and '403错误' that can match many normal browsing or troubleshooting requests, causing the skill to activate outside its narrowly intended scope. In this skill, that is more dangerous because activation routes users into anti-bot bypass and third-party scraping workflows without a clear gating step or consent warning.
The skill documents Jina Reader and protected-site fetching but does not clearly warn that URLs and fetched content may be transmitted to third-party services or processed through anti-bot bypass tooling. This creates a data disclosure and compliance risk, especially if users provide private, sensitive, or access-controlled links assuming only local fetching will occur.
The paid-mode setup instructs users to hardcode a live billing API key directly into source code, which encourages credential exposure through version control, logs, file sharing, backups, or accidental publication. Because the key is tied to billing operations, compromise could enable unauthorized charges, balance abuse, or takeover of the payment integration.
The description text is written only in Chinese ("智能网页内容抓取工具,支持绕过反爬机制") and provides no indication that users may choose another language or locale. This can violate language/locale policy when a skill's natural-language metadata is presented to a broader user base without opt-in or documented regional scope.
The skill invokes a stealth/anti-bot fetcher intended to bypass website protections, but this behavior is not surfaced to the user. Beyond legal and policy concerns, it causes opaque network access to arbitrary user-supplied destinations and increases exposure to SSRF-style misuse or collection from sites the user may not expect the tool to access in this manner. The explicit anti-bot bypass purpose makes the context more suspicious, not less.
The subprocess itself is not inherently unsafe, but here it executes dynamically generated Python code built with direct string interpolation of a user-controlled URL. If the URL contains quotes or crafted payload text, it can break out of the string literal in the generated code and achieve arbitrary code execution in the spawned interpreter. The skill context increases risk because the feature is explicitly designed to fetch attacker-controlled remote content and accepts arbitrary URLs from users.
print(json.dumps(result, ensure_ascii=False))
"""
result = subprocess.run(
[VENV_PYTHON, "-c", code],
capture_output=True,
text=True,
This path sends user-supplied URLs to the third-party service r.jina.ai without any disclosure or consent mechanism. That can leak sensitive, internal, or private URLs to an external provider and may trigger unintended server-side requests on behalf of the user. In an agent skill context, this is more dangerous because users may assume local retrieval while the tool actually forwards targets to an outside service.
Natural-language strings in the file present the tool as Chinese-only and several user-facing outputs and descriptions are exclusively in Chinese, with no opt-in or locale selection mechanism. Under the policy, forcing a specific language without user choice is a language/locale policy violation unless the restriction is clearly justified.
The script embeds billing logic and a live billing API key directly in a fetch utility, creating unnecessary financial side effects and exposing a secret that can be reused by anyone with file access. In agent-skill context, hidden or weakly disclosed charging behavior is especially risky because a caller may invoke the tool expecting only content retrieval, not monetary operations.
User identifiers and billing data are sent to an external billing service without any visible warning, consent flow, or privacy notice in this file. In an agent skill, silent transmission of identity and payment-related metadata to a third party is a meaningful privacy and trust risk, especially when coupled with charging behavior.
This request transmits billing identifiers to an external payment endpoint and authorizes a charge using a hard-coded API key. If the key is exposed or abused, attackers could trigger unauthorized billing actions or interact with the payment backend outside intended controls.
def charge_user(user_id: str) -> dict:
"""扣费(余额不足自动返回充值链接)"""
resp = requests.post(
f"{BILLING_API_URL}/api/v1/billing/charge",
headers={
"X-API-Key": BILLING_API_KEY,
This call sends user billing information to an external service to generate payment links, again using the embedded API key. While expected for billing, it still represents external transmission of sensitive metadata and expands abuse potential if the secret or endpoint use is not tightly controlled.
def get_payment_link(user_id: str, amount: float = 8.0) -> str:
"""生成充值链接"""
resp = requests.post(
f"{BILLING_API_URL}/api/v1/billing/payment-link",
headers={
"X-API-Key": BILLING_API_KEY,
The tool sends user-supplied target URLs and may retrieve page content through external services (r.jina.ai and potentially third-party scraping infrastructure) without explicit warning. This can leak sensitive URLs, internal links, or proprietary content to outside providers, which is especially dangerous for agent workflows where users may pass confidential targets.
The subprocess invocation itself is not the core issue; the danger is that untrusted user input (url) is interpolated directly into a Python code string executed with python -c. A crafted URL containing quotes or Python syntax can break out of the string literal and achieve arbitrary code execution in the spawned interpreter.
print(json.dumps(result, ensure_ascii=False))
"""
result = subprocess.run(
[VENV_PYTHON, "-c", code],
capture_output=True,
text=True,
The README opens with Chinese title and content before later offering an English section, which can be interpreted as defaulting users into a specific language rather than clearly offering language choice upfront. The policy allows locale constraints when users are explicitly given a choice or justification is documented.
The natural-language instructions and examples are presented entirely in Chinese, including the manifest description and operational guidance, with no indication that the skill supports other languages or that Chinese is a required locale. This can conflict with organizational language-choice policies when users are not given an opt-in or alternative.
Natural-language strings in the module description and CLI help are presented only in Chinese, with no indication that other languages are supported. Under the policy, forcing a specific language without user opt-in can be a locale/language policy issue.
The inline comment '添加计费信息' suggests the block only annotates the result with billing metadata. However, the code also invokes check_balance(), causing another external API request and retrieving fresh account data, which is more than merely attaching existing information.
No suspicious patterns detected.