Back to skill

Security audit

极鲸云美客多商品搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do the advertised Mercado Libre product research, but its login handling stores bearer tokens in multiple local places and trusts login/action links too broadly.

Review this skill before installing if you handle sensitive business data. Install only if you trust GeekBI and keep usage on the default GeekBI API origin; avoid custom --base-url values. Be aware that login tokens may be written to local JSON files in more than one place, including the current workspace, and clear those files when access is no longer needed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/geekbi_auth.py:65
Finding
Bearer tokens are unnecessarily replicated across multiple local storage locations## Vulnerability Details **File Location**: `scripts/geekbi_auth.py:65-90`, `scripts/geekbi_auth.py:371-379`, and `scripts/geekbi_auth.py:631-648` **Vulnerability Type**: Excessive storage of plaintext bearer tokens **Risk Level**: Medium ### Vulnerable Code ```python def _user_config_state_path(): return _absolute_path( user_config_path("GeekBI", appauthor=False, ensure_exists=True) / "temu-research-skill" / AUTH_FILE_NAME ) def _skill_state_path(): return _absolute_path(Path(__file__).parent.parent / AUTH_STATE_DIR / AUTH_FILE_NAME) def _workspace_state_path(): return _absolute_path(Path(os.getcwd()) / AUTH_STATE_DIR / AUTH_FILE_NAME) def _resolve_stores(): candidates = ( ResolvedStore(_user_config_state_path(), "user-config-directory"), ResolvedStore(_skill_state_path(), "skill-directory"), ResolvedStore(_workspace_state_path(), "working-directory"), ) stores = [] seen_paths = set() for store in candidates: path_key = os.path.normcase(os.fspath(store.path)) if path_key in seen_paths: continue seen_paths.add(path_key) stores.append(store) return tuple(stores) ``` ```python def _write_state_files(stores, payload): normalized = _normalize_state(payload) errors = [] written = 0 for store in stores: try: _write_state_file(store, normalized) written += 1 except OSError as error: errors.append(f"{store.kind}: {_storage_probe_reason(error)}") ``` ```python token_data = response["data"] access_token = token_data.get("accessToken") if not isinstance(access_token, str) or not access_token: raise ValueError("Login token response does not contain accessToken") expires_in = int(token_data.get("expiresIn", 0)) def save_token(latest): latest_server = latest["s ...[truncated 3065 chars]
Remediation
## Remediation Suggestions 1. Store authentication state in exactly one Skill-specific user configuration location. 2. Replace the `temu-research-skill` directory with a unique Mercado Libre Skill identifier. 3. Remove `_skill_state_path()` and `_workspace_state_path()` from production credential storage. 4. Prefer the operating system's credential manager or keychain for bearer-token material. Keep only non-sensitive metadata in JSON. 5. Implement a migration that reads any legacy state once, moves it into the new secure store, and securely removes all legacy copies. 6. Enforce restrictive ACLs on Windows as well as mode `0700` for directories and `0600` for files on POSIX systems. 7. Fail closed when secure token storage cannot be established rather than falling back to the Skill or working directory. 8. Add tests confirming that authentication never creates `.geekbi/agent-auth.json` in the project or current working directory.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mercadolibre_goods_search.py:61
Finding
Authentication endpoints and server-provided action URLs are accepted without origin validation## Vulnerability Details **File Location**: `scripts/mercadolibre_goods_search.py:61-71`, `scripts/geekbi_auth.py:525-533`, `scripts/geekbi_auth.py:669-693`, and `scripts/geekbi_auth.py:698-721` **Vulnerability Type**: Unrestricted authentication destination and untrusted action-link propagation **Risk Level**: Medium ### Vulnerable Code ```python def main(): parser = argparse.ArgumentParser(description="Query Mercado Libre products and output JSON") parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--param", action="append", default=[], help="Query condition in name=value format") parser.add_argument("--timeout", type=float, default=30) args = parser.parse_args() try: params = parse_params(args.param) payload = authenticated_json_request( build_url(args.base_url, ENDPOINT, params), args.base_url, args.timeout ) ``` Equivalent unrestricted `--base-url` parameters are also present in `scripts/mercadolibre_goods_info.py` and `scripts/mercadolibre_site_list.py`. ```python def _post_json(url, body, timeout): request = Request( url, data=json.dumps(body, ensure_ascii=False).encode("utf-8"), headers=_api_headers("application/json"), method="POST", ) with urlopen(request, timeout=timeout) as response: return _read_json_response(response) ``` ```python def _save_challenge(base_url, response_payload): data = response_payload.get("data", {}) device_code = data.get("deviceCode") jump_url = data.get("jumpUrl") if not isinstance(device_code, str) or not device_code: raise ValueError("Login response does not contain deviceCode") if not isinstance(jump_url, str) or not jump_url: raise ValueError("Login response does not contain jumpUrl") expires_in = int(data.get("expiresIn", 0)) def save_challenge(payload): ...[truncated 4524 chars]
Remediation
## Remediation Suggestions 1. Remove `--base-url` from production-facing commands when alternate servers are not required. 2. If alternate environments are necessary, validate the parsed URL against an explicit allowlist of exact origins. 3. Require HTTPS, reject embedded user information, reject fragments, restrict ports, and normalize the origin before using it as a token-store key. 4. Enforce exact matching with `https://openapi.geekbi.com` for production requests. 5. Install an explicit redirect handler that rejects cross-origin redirects and HTTPS-to-HTTP downgrades. 6. Verify the final response URL after every request before parsing or trusting its contents. 7. Validate `jumpUrl` against a separate allowlist of approved HTTPS authentication origins. 8. Do not reproduce arbitrary server text as trusted instructions. Present a fixed local explanation and a clearly labeled, validated authentication link. 9. Add tests for HTTP URLs, user-information URLs, unexpected ports, hostname suffix confusion, encoded hostnames, cross-origin redirects, and malicious `jumpUrl` values. 10. Keep tokens scoped to the exact normalized trusted origin and clear them if origin validation fails.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Natural-Language Policy Violations

High
Confidence
88% confidence
Finding
The skill is written to operate in Chinese by default without indicating that it should preserve or adapt to the user's language. This can mislead users, degrade informed consent, and cause incorrect interpretation of commercial analysis or policy guidance, especially in multilingual contexts where accuracy and clarity matter.

Static analysis

No suspicious patterns detected.