T09 · Insecure Skill Coding Practices
- Location
scripts/qualification_upload.py:1124- Finding
Unrestricted API-Supplied Hostname Used for Sensitive Document Uploads
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent for Volcengine domestic SMS work, but its sensitive document upload path accepts a server-supplied upload host without an approved-domain allowlist.
Install only if you are comfortable giving the skill access to your Volcengine SMS account, sending SMS or batch tasks after confirmation, and uploading qualification documents for remote processing. Review is warranted until the document upload code restricts upload destinations to approved ImageX/Volcengine domains and prevents unsafe redirects/header forwarding.
scripts/qualification_upload.py:1124Unrestricted API-Supplied Hostname Used for Sensitive Document Uploads
This code chunk appears to be an unrelated third-party frontend library asset (react-dom.production.min.js). Its purpose is to support rendering of a web UI, which is only a generic implementation detail and does not itself implement the declared SMS-related capabilities. Because the supplied code does not substantiate the declared behavior and instead has a materially different direct purpose, the description does not accurately represent what this code chunk actually does.
代码的主功能非常明确:它是 qualification_mcp_server,围绕 run_qualification_wizard 构建一个 MCP 应用,提供 4 个工具——打开资质申请、确认表单可见、查询申请结果、取消申请。资源部分也只提供一个“火山引擎短信资质表单”HTML 页面。虽然这与声明中“资质敏感材料只通过本机私密表单处理”这一点是一致的,但声明覆盖的范围远大于代码实际行为。声明把技能描述为一个可发送和管理国内短信的综合能力集合,而代码没有任何发送短信、群发、签名/模板申请、发送记录/回执/分析查询等实现痕迹。故这不是轻微遗漏,而是描述的主要用途明显宽于实际代码,属于实质性不匹配。
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"volcengine-cli_1.1.1_SHA256SUMS"
)
DEFAULT_TIMEOUT = 15.0
DEFAULT_ENV_PATH = "~/.openclaw/.env"
LOGIN_PROCESS_LEASE_SECONDS = 30 * 60
MAX_READ_RETRIES = 2
MAX_CLI_CACHE_BYTES = 256 * 1024
The skill requests or implies powerful capabilities (environment access, file read/write, network, and shell) but does not declare an explicit tool scope. That creates an over-privileged execution surface where the agent may invoke sensitive operations beyond what is clearly constrained by policy, increasing the risk of misuse, accidental data exposure, or command execution abuse.
The document declares lang="zh-CN" and all visible user-facing status and title text are only in Simplified Chinese. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is explicitly justified or the user is offered a choice.
This code file contains extensive user-facing natural-language strings that force a specific language/locale, beginning with the role and step labels in Chinese and continuing throughout the workflow. Under the policy, language constraints should either offer user opt-in/choice or be explicitly documented as justified for a region-specific tool; neither is evident in this file.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}, [refresh, updateStatus]);
const stepList = useMemo(
() => (state ? requiredSteps(state, purpose) : allStepKeys),
[state, purpose],
);
The document requires ApplySmsTemplateV2 to use a fixed area=cn, which imposes a specific locale/region constraint. The file does not offer user opt-in or explain that this skill is strictly limited to a China-specific regulatory or product context, so this reads as a natural-language locale policy constraint.
The entire skill content and the prescribed user-facing sentence are written only in Chinese, including the exact message the agent must deliver to the user. This imposes a specific language/locale without user opt-in, which matches the policy-violation category for language constraints.
The contract explicitly allowlists temporary upload credentials and tokens such as accessKeyId, secretAccessKey, sessionToken, and token in action results. Even if short-lived, exposing cloud upload credentials to broader skill layers or end users materially increases the chance of credential leakage, misuse of storage access, and unintended handling of sensitive qualification documents.
The manifest describes sending SMS, bulk SMS, notifications, marketing messages, qualification onboarding, signatures/templates, logs, receipts, and customer-visible analytics. These lines additionally register SendSmsVerifyCodeByMobile and CheckSmsVerifyCodeByMobile, which implement mobile verification-code issuance and validation as a distinct authentication/identity-check workflow not mentioned in the manifest description.
DeleteBatchTask is a destructive operation by name and is marked read_only=False, but this file provides no user-facing confirmation, warning comment, or explanatory disclosure about deletion behavior. For safety-critical irreversible actions, some visible disclosure is expected unless documented elsewhere.
This code forces the Volcengine CLI language via ---lang EN, which is a natural-language locale policy decision embedded in code. The file also contains user-facing Chinese strings elsewhere, so unconditionally forcing English is not clearly documented as a justified region-specific constraint and does not provide user choice.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
env: Mapping[str, str],
timeout: float,
) -> subprocess.CompletedProcess:
return subprocess.run(
list(command),
env=dict(env),
stdout=subprocess.PIPE,
The refresh path explicitly appends ---lang EN, enforcing a specific language for CLI interaction. Under the policy, language forcing is a violation unless the user is given a choice or the restriction is clearly justified and documented.
The identity validation command appends ---lang EN, again forcing one language for command output and interaction. This is a natural-language policy issue because no user choice or explicit justification is provided in the file.
This code defines all tool titles and descriptions in Chinese, and subsequent user-facing status messages are also returned only in Chinese. That creates a language-policy issue because the skill imposes a specific language on users without any opt-in, fallback, or indication that the skill is intentionally limited to a Chinese-language audience.
This code uploads business certificate and identity document images, then sends their resulting URIs for OCR processing via external service calls. While the module has internal comments about credential handling, there is no user-facing prompt, print/log disclosure, or inline warning to inform users that sensitive personal/business documents will be transmitted for remote processing.
Detected: suspicious.exposed_secret_literal