Back to skill

Security audit

17ce Speedtest

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it distributes shared API credentials and can send sensitive request details to a third-party testing service without enough safeguards.

Review before installing. Use only test targets you are authorized to probe, avoid sending private/internal URLs or production cookies through this skill, and do not rely on the bundled shared 17CE credential. Prefer a revised version that removes embedded credentials, uses protected per-user secrets, requires confirmation before external or bulk tests, disables cookie forwarding by default, escapes generated HTML reports, and pins dependencies.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/speedtest.py:30
Finding
Credentials and Session Cookies Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/speedtest.py`, lines 30-31, 59-97, and 118-155 **Vulnerability Type**: Plaintext transmission of sensitive information **Risk Level**: High ### Vulnerable Code ```python LEGACY_API_BASE = "http://www.17ce.com/api/site" API_BASE = "http://www.17ce.com/apis" ``` The API-password authentication request is constructed and transmitted as follows: ```python data = [ ("user", username), ("t", str(t)), ("code", code), ("url", url), ("rt", str(rt)), ("nocache", str(nocache)), ] if cookie: data.append(("cookie", cookie)) response = requests.post( f"{API_BASE}/http", data=data, timeout=30 ) ``` The legacy authentication mode transmits the account secret directly: ```python data = [ ("appKey", username), ("appSecret", password), ("url", url), ("rt", str(rt)), ("nocache", str(nocache)), ] if cookie: data.append(("cookie", cookie)) response = requests.post( f"{LEGACY_API_BASE}/http", data=data, timeout=30 ) ``` ### Technical Analysis Both API base URLs use plaintext HTTP. The legacy mode places the account name and reusable account secret in an unencrypted form body. The alternative mode transmits the username, timestamp, derived authentication code, target URL, and any supplied cookie without transport encryption. Although the API-password mode does not transmit the raw API password, its authentication code is exposed to network observers and may be replayable during its accepted timestamp window. The script's own API error definitions indicate that timestamps are accepted within a five-minute range. The Base64 operation reported by the static pre-scan is not itself a covert exfiltration mechanism. It is an intermediate operation in the documented authentication hash: ```python code = hashlib.md5(base64.b64encode(raw.encode())).hexdigest() ``` The confirmed vulnerability is the subsequent network transmission over plaintex ...[truncated 1312 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace both plaintext API endpoints with verified HTTPS endpoints. 2. Remove the legacy account-password authentication mode if the service does not support it securely over TLS. 3. Configure the HTTP client to reject redirects from HTTPS to HTTP. 4. Do not accept or forward production session cookies by default. 5. If cookie-based testing is indispensable, require explicit user confirmation and short-lived, test-only credentials. 6. Implement certificate verification and fail closed on TLS validation errors. 7. Ensure sensitive request fields are never written to logs or exception messages. 8. Rotate any account passwords or cookies previously transmitted through these HTTP endpoints. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:33
Finding
Hard-Coded Shared API Credential and Command-Line Secret Exposure<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 33-50; duplicated in `README.md`, lines 33-50 **Vulnerability Type**: Hard-coded secret and insecure credential handling **Risk Level**: High ### Vulnerable Content ```text ## API Authentication By default, please use the following public, official 17CE credentials provided for OpenClaw users, unless the user explicitly provides their own: - Email (--user): huangwg@gmail.com - API PWD (--apipwd): PVCYVIQEGF8Y6D1G ``` The documentation requires passing the credential directly through command-line arguments: ```bash python scripts/speedtest_ws.py http://example.com \ --user huangwg@gmail.com \ --apipwd PVCYVIQEGF8Y6D1G \ --html > report.html ``` The same credential and command examples appear in both `SKILL.md` and `README.md`. ### Technical Analysis A reusable API credential is embedded in plaintext in the distributed Skill package. Anyone who can download or inspect the package can obtain it. The Skill also directs the Agent to pass the secret through `argv`. Command-line secrets can be exposed through process listings, shell history, execution telemetry, Agent transcripts, crash reports, and orchestration logs. Marking the account as public does not eliminate these risks: the value remains an authentication credential tied to quota and account state. This behavior exceeds minimum privilege because the Skill could instead request a per-user credential through a protected secret channel, and public website tests do not justify distributing a reusable shared secret. ### Attack Path 1. An attacker downloads the Skill package or reads a copy of `SKILL.md` or `README.md`. 2. The attacker extracts the embedded email address and API password. 3. Alternatively, the attacker observes the command line through process inspection, shell history, Agent logging, or execution telemetry. 4. The attacker submits independent 17CE tasks using the exposed credential. 5. The attacker consumes t ...[truncated 522 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the exposed API password immediately. 2. Remove the email address and API password from `SKILL.md`, `README.md`, examples, demo files, and repository history. 3. Require each user to supply an individual credential. 4. Read credentials from a protected environment variable, operating-system secret store, or platform secret manager rather than command-line arguments. 5. Prevent credentials from being echoed in logs, error output, generated reports, or Agent transcripts. 6. Scope credentials to the minimum required operations and quota. 7. Add automated secret scanning to the development and release process. 8. Document credential configuration using placeholders such as `${17CE_API_PASSWORD}` rather than live values. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report.py:65
Finding
HTML and Script Injection in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/report.py`, lines 65-70, 77-99, and 207-236 **Vulnerability Type**: HTML injection and stored cross-site scripting **Risk Level**: High ### Vulnerable Code Remote or JSON-supplied result fields are used without escaping: ```python prov = r.get("Province", "未知") isp = r.get("ISP", "未知") loc = f"{prov}{isp}" chart_html += f""" <div class="chart-row"> <div class="chart-lbl">{loc}</div> <div class="chart-bar-wrap"> <div class="chart-bar" style="width:{pct}%; background:{color}"></div> <div class="chart-val" style="color:{color}">{display_val}</div> </div> </div>""" ``` Additional fields are interpolated into table markup: ```python table_rows += f""" <tr> <td><span class="loc">{loc}</span></td> <td> <div class="bar-wrap"><div class="bar-fill" style="{bar_width};background:{bar_bg}"></div></div> <span style="color:{color};font-weight:600">{f"{total:.1f}" if is_ok else '--'}</span> <span class="badge" style="background:{color}20;color:{color}">{label}</span> </td> <td class="fade">{f"{ttfb:.1f}" if is_ok else '--'}</td> <td class="fade">{f"{dns:.1f}" if is_ok else '--'}</td> <td><span class="code {code_cls}">{code if code > 0 else '-'}</span></td> <td class="fade ip-col">{r.get('SrcIP','-')}</td> </tr>""" ``` The user-controlled target URL and test time are also inserted directly: ```python <span class="t">{test_time}</span> ``` ```python <span class="u">{url or "未指定"}</span> ``` ### Technical Analysis The report generator builds HTML through formatted strings without applying HTML entity encoding. The target URL is directly user-controlled. Result fields may originate from the remote 17CE service or from an arbitrary JSON document supplied to `report.py`. An attacker can close the surrounding HTML element and inject new elements, event handlers, or script tags. Because the output is intended to be saved as an HTML file and opened in a brows ...[truncated 1356 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Apply `html.escape(value, quote=True)` to every dynamic text value before interpolation. 2. Escape at the final output context rather than relying solely on input validation. 3. Validate numeric fields such as response times and HTTP codes as strict numeric types before formatting them. 4. Treat all remote service responses and piped JSON fields as untrusted. 5. Prefer a templating engine with automatic HTML escaping enabled. 6. Add a restrictive Content Security Policy, for example disallowing inline scripts and limiting outbound connections. 7. Remove externally loaded resources from reports or constrain them through the Content Security Policy. 8. Add regression tests using payloads containing closing tags, script elements, quotes, and event-handler attributes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/speedtest_ws.py:69
Finding
Authenticated Cookies Forwarded to Third-Party Monitoring Infrastructure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/speedtest_ws.py`, lines 69-91 and 234-253 **Vulnerability Type**: Excessive collection and third-party disclosure of session credentials **Risk Level**: Medium ### Vulnerable Code The task-building interface accepts an arbitrary cookie: ```python def build_task(url: str, isp_list: list, area_list: list, num: int, pro_ids: str = "221,49", rt: str = "GET", host: str = None, cookie: str = None, agent: str = None) -> dict: task = { "txnid": int(time.time()), "nodetype": isp_list, "num": num, "Url": url, "TestType": "HTTP", "Host": host or "", "TimeOut": 20, "Request": rt, "NoCache": True, "Speed": 0, "Cookie": cookie or "", "Trace": False, "Referer": url, "UserAgent": agent or "curl/7.47.0", ``` The command-line argument is passed directly into that task: ```python parser.add_argument("--cookie", help="自定义 Cookie") ``` ```python task = build_task( url=args.url, isp_list=args.isp, area_list=args.area, num=args.num, pro_ids=args.pro_ids, rt=args.rt, host=args.host, cookie=args.cookie, agent=args.agent, ) ``` The resulting task is sent to 17CE: ```python await ws.send(json.dumps(task, ensure_ascii=False)) ``` ### Technical Analysis The Skill supports forwarding arbitrary HTTP cookies to the 17CE service, where distributed monitoring nodes use them when requesting the target. Cookies commonly contain authenticated session tokens, authorization state, or access to non-public application resources. WSS protects the connection in transit to the 17CE endpoint, but it does not prevent the receiving service or remote monitoring infrastructure from observing, retaining, or misusing the cookie. The implementation provides no warning, confirmation, domain binding, cookie-name allowlist, redaction, or requirement that the token ...[truncated 1114 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove cookie forwarding from the default Skill interface. 2. If authenticated testing is a required advanced feature, require explicit informed confirmation before transmitting a cookie. 3. Display the destination service and explain that third-party monitoring nodes will receive the credential. 4. Require short-lived, least-privileged, test-only tokens instead of production session cookies. 5. Bind the supplied credential to an explicitly validated target hostname. 6. Reject URLs whose hostname does not match the approved cookie domain. 7. Redact cookie values from command output, logs, process listings, exceptions, and reports. 8. Prefer a secure secret input channel over `argv`. 9. Confirm and document the monitoring provider's retention, node-isolation, and credential-handling guarantees. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Dependencies Are Not Reproducibly Pinned<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt`, lines 1-2 **Vulnerability Type**: Uncontrolled dependency resolution **Risk Level**: Low ### Vulnerable Configuration ```text websockets>=10.4 requests>=2.28.0 ``` ### Technical Analysis The dependency declarations specify only minimum versions and have no upper bounds, exact pins, lock file, or package hashes. A future installation can therefore resolve to versions that were not reviewed with the Skill. The package names themselves are legitimate and no typosquatting or known malicious package was identified in the audited files. The risk arises from non-reproducible dependency resolution and the possibility that a future compromised, vulnerable, or incompatible release will be installed automatically. ### Attack Path 1. The Skill is installed at a later date or in a different environment. 2. The package resolver selects the newest versions satisfying the lower bounds. 3. A selected release contains a vulnerability, malicious modification, or behavior incompatible with the audited code. 4. The dependency is imported by the Skill with the privileges of the invoking process. 5. The vulnerable or compromised dependency affects network handling or executes malicious package code. ### Impact Assessment Impact depends on the behavior of the selected dependency release. A compromised package could execute code with the privileges of the user running the Skill, while a vulnerable networking release could expose credentials, corrupt results, or permit denial of service. No present malicious dependency was confirmed; this is a supply-chain hardening deficiency that increases future installation risk. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin dependencies to reviewed exact versions. 2. Generate and commit a lock file appropriate to the deployment process. 3. Use package hashes, such as pip's `--require-hashes`, to verify downloaded artifacts. 4. Install packages only from an approved package index over TLS. 5. Run automated vulnerability and license scanning on every dependency update. 6. Adopt a controlled update process that reviews and tests new releases before changing pins. 7. Periodically refresh pins so that security fixes are incorporated intentionally rather than through uncontrolled resolution. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (32)

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The README embeds shared 17CE credentials and instructs the agent to use them by default in normal operation. Hard-coded third-party credentials are a real secret-handling vulnerability because they enable unauthorized use, quota theft, account abuse, and accidental disclosure to users, logs, or downstream tooling.

Ssd 3

High
Confidence
99% confidence
Finding
The skill embeds and operationalizes shared account secrets, explicitly telling the agent to use and potentially expose them during standard execution. In context, this is especially dangerous because the secrets are not incidental examples; they are the prescribed authentication path for all users, magnifying the chance of credential leakage, abuse, quota exhaustion, and downstream compromise of the third-party account.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented behavior says the skill performs a WebSocket-based speed test, but the actual described behavior includes authenticated API submission, secret handling, and extra request-shaping features outside that scope. This mismatch can mislead users and reviewers about what data is sent, what credentials are used, and what the skill is really capable of doing.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The skill embeds hard-coded shared account credentials and instructs the agent to use them by default. Exposed credentials can be abused by anyone with access to the skill, lead to quota theft or account compromise, and normalize unsafe secret distribution practices.

Ssd 3

High
Confidence
98% confidence
Finding
The skill both embeds shared credentials and encourages passing user-provided API passwords through bot actions and command-line arguments. Secrets in skill docs, prompts, process arguments, logs, or agent traces may be exposed to other users, operators, or telemetry systems.

Missing User Warnings

High
Confidence
99% confidence
Finding
The script sends authentication material and optional sensitive metadata such as cookies, referer, host, and user-agent to 17CE over plain HTTP via both API_BASE and LEGACY_API_BASE. This allows any network observer or active man-in-the-middle to intercept or modify credentials and request contents, potentially leading to account compromise, session leakage, and tampered test submissions.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger list is broad enough to activate on generic phrases like 'check website' or 'website slow', which can cause the skill to run in situations the user did not clearly intend. In this skill, unintended activation is more dangerous because execution sends targets to an external service and may consume shared credentials and external quota automatically.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill description says it retrieves real-time speed data from global monitoring nodes via WebSocket but does not clearly warn users that their supplied URL will be transmitted to an external service. This is a genuine privacy and consent issue because users may provide internal, sensitive, or non-public endpoints without realizing they will be probed by third-party infrastructure.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The instructions direct the agent to automatically test multiple AI API endpoints without warning the user that this initiates outbound probes to several third-party services. This increases risk because the action is autonomous, multi-target, and can create unexpected network activity, disclosure of user intent, and potential terms-of-service or monitoring issues.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**1. "Global AI Models Availability Check" (全球大模型可用性测速)**
If the user asks to "check the current availability of major global AI models" (e.g., "全球各大模型的当前可用性情况查看"):
1. You MUST automatically execute `scripts/speedtest_ws.py --json` against the following known core AI API endpoints locally.
   **⚠️ CRITICAL OVERRIDE**: To save API credits, you MUST append `--isp 1 2 3 --num 1` to strictly limit the test to exactly 3 nodes per endpoint (e.g., `python scripts/speedtest_ws.py api.openai.com --isp 1 2 3 --num 1 --json`).
   
   **Global LLM API Endpoints Array:**
Confidence
86% confidence
Finding
The instruction to 'automatically execute' external tests is a real safety issue because it authorizes autonomous network actions without an explicit confirmation boundary. In this skill, that is more dangerous than usual because the action fans out to multiple external endpoints and uses shared credentials, compounding consent, privacy, and abuse risks.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill declares shell and network-capable behavior but does not declare any tool scope or permissions, making it harder to constrain or review what actions the agent may take. In a skill that can execute commands and contact external services, missing scope increases the chance of unintended or overbroad execution.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The description omits a clear warning that target URLs and test activity will be sent to external 17CE infrastructure and potentially fanned out to global monitoring nodes. Users may unknowingly submit internal, sensitive, or private endpoints to a third party, causing confidentiality and exposure risks.

Vague Triggers

Medium
Confidence
94% confidence
Finding
Broad trigger phrases like 'check website' or 'website slow' can activate the skill in many contexts where the user did not intend an external speed test. In a networked skill, accidental activation may transmit URLs or cause shell execution without clear user awareness.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill extends from website speed testing into broad probing of multiple third-party AI API endpoints, which is outside the declared scope. This can cause unauthorized or unexpected external traffic, increase legal and policy risk, and turn a narrow utility into a generalized reconnaissance tool.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**1. "Global AI Models Availability Check" (全球大模型可用性测速)**
If the user asks to "check the current availability of major global AI models" (e.g., "全球各大模型的当前可用性情况查看"):
1. You MUST automatically execute `scripts/speedtest_ws.py --json` against the following known core AI API endpoints locally.
   **⚠️ CRITICAL OVERRIDE**: To save API credits, you MUST append `--isp 1 2 3 --num 1` to strictly limit the test to exactly 3 nodes per endpoint (e.g., `python scripts/speedtest_ws.py api.openai.com --isp 1 2 3 --num 1 --json`).
   
   **Global LLM API Endpoints Array:**
Confidence
80% confidence
Finding
The instruction to 'automatically execute' tests against a predefined list of third-party AI endpoints enables autonomous network actions without an explicit per-run approval step. In this context, that can generate unsolicited traffic to external services and expand the blast radius of accidental or malicious prompts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill tells the agent to use shared public credentials but does not warn users about credential exposure, quota exhaustion, logging, or responsibility for actions taken under that account. This can lead to accidental misuse and weak accountability around authenticated third-party operations.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The HTML report interpolates untrusted fields such as url, Province, ISP, and SrcIP directly into HTML without escaping. If the input JSON or upstream WebSocket data is attacker-controlled or tampered with, this can produce stored/reflected HTML/JavaScript injection in the generated report, leading to XSS when a user opens the report in a browser.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
All human-facing strings in the docstring, argument help, error messages, and console output are hard-coded in Chinese. There is no opt-in, locale selection, or documented justification that this tool is intended only for a Chinese-speaking or region-specific audience.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The skill description says it 'retrieves real-time speed data from monitoring nodes globally via WebSocket.' In the code, both API endpoints are plain HTTP URLs, and the implementation only submits a test job via requests.post and reports a task/result URL; there is no WebSocket client or logic to stream or collect real-time node results.

Tainted flow: 'data' from requests.post (line 207, network input) → requests.post (network output)

Medium
Category
Data Flow
Content
data.append(("agent", agent))

    try:
        response = requests.post(
            f"{API_BASE}/http",
            data=data,
            timeout=30
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'data' from requests.post (line 207, network input) → requests.post (network output)

Medium
Category
Data Flow
Content
data.append(("agent", agent))

    try:
        response = requests.post(
            f"{LEGACY_API_BASE}/http",
            data=data,
            timeout=30
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code builds a WebSocket URL from the provided account email and API password-derived authentication code, then sends the测速 task to the remote 17CE service. Although the script prints basic progress messages, it does not warn the user that their supplied account identifier and request details will be transmitted externally.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The built-in command is presented with a Chinese name and example phrasing for activation, without indicating that users may choose another language. This can be a language/locale policy issue because the skill appears to privilege a specific language path without explicit user choice or justification.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The document declares `lang="zh-CN"`, and the visible UI text throughout the page is Chinese-only. This imposes a specific language/locale without any indication of user opt-in or justification for a region-specific constraint, which matches the policy-violation category for language/locale handling.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The document declares `lang="zh-CN"`, and all visible UI text is presented in Chinese, which imposes a specific language/locale on users. Under the policy, locale-specific behavior should either provide user opt-in/choice or be clearly justified as region-specific.

Static analysis

No suspicious patterns detected.