T09 · Insecure Skill Coding Practices
- Location
scripts/coros_mcp_login.py:289- Finding
Legacy login transmits COROS credentials to an unvalidated redirect destination
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a real COROS MCP setup helper, but it handles account credentials and bearer tokens with under-scoped endpoint controls and risky local persistence.
Review before installing. Use only the browser/device login flow, avoid --legacy password login, do not set custom issuer or MCP URL values unless you fully trust the endpoint, and treat the local OpenClaw MCP config and ~/.coros-mcp-skill-gateway state as sensitive because they may contain reusable COROS tokens.
scripts/coros_mcp_login.py:289Legacy login transmits COROS credentials to an unvalidated redirect destination
scripts/coros_mcp_login.py:619Arbitrary issuer and MCP endpoint selection can disclose OAuth tokens and user data
scripts/coros_mcp_login.py:384Bearer access token is exposed through OpenClaw subprocess arguments
scripts/coros_mcp_login.py:116Predictable temporary paths create secret-file symlink and race risks
scripts/coros_mcp_login.py:43Incomplete and bypassable error redaction can leak authentication secrets
The skill is described as installing or refreshing an OpenClaw MCP connection, but the instructions show it also performs direct auth flows, stores and refreshes tokens, supports legacy username/password login, and actively invokes remote MCP tools. This hidden expansion of behavior is dangerous because operators may grant trust for a setup task while unknowingly enabling credential handling, persistent token storage, and arbitrary remote actions through the same helper.
The skill description says it installs or refreshes a COROS MCP connection, but the code also implements generic MCP initialization, tool enumeration, tool description, and tool invocation. That materially expands the capability from authentication/setup into a general remote action proxy, increasing the chance of unauthorized or surprising operations under the user's bearer token.
The call_tool path allows arbitrary remote MCP tool execution with attacker-controlled tool names and JSON arguments, using the stored access token for authorization. In a login helper, this is especially dangerous because users may run it expecting setup behavior, while the code can perform broad server-side actions unrelated to authentication.
The skill exposes broad capabilities—shell, network, file read/write, and environment access—without declaring any explicit tool scope or permission boundaries in the manifest. That increases the blast radius if the skill is invoked unexpectedly or modified later, because consumers cannot easily tell what operations are intended or constrain execution to the minimum necessary set.
The code renders an OpenClaw config containing a live Authorization bearer token and writes it via 'openclaw mcp set' without an explicit warning or safer credential-handling path. This can expose the token through local configuration storage, backups, diagnostics, or other local users/processes, enabling reuse of the bearer token against the MCP service.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def apply_openclaw(self, server_name: str) -> None:
try:
subprocess.run(
["openclaw", "mcp", "set", server_name, self.render_openclaw_config(server_name)],
check=True,
text=True,
The login request forces language to zh and country to CN for all users. This is a natural-language/locale policy issue because the script does not offer locale selection or explain that it is intended only for a China-specific environment.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cls.module = load_skill_module()
def test_help_command_is_available(self):
completed = subprocess.run(
["python3", str(SKILL_SCRIPT), "--help"],
check=False,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
isolated_script = isolated_scripts / "coros_mcp_login.py"
isolated_script.write_text(SKILL_SCRIPT.read_text(encoding="utf-8"), encoding="utf-8")
completed = subprocess.run(
["python3", str(isolated_script), "--help"],
check=False,
capture_output=True,