Back to skill

Security audit

极鲸云美客多数据分析与市场调研

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Mercado Libre research purpose, but its credential handling and configurable API destination create review-worthy risk.

Install only if you trust GeekBI and understand that this skill authenticates to GeekBI and stores bearer-token login state locally. Avoid using custom --base-url values, do not run it from shared or published repositories, and clear any .geekbi/agent-auth.json copies when done.

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

Error
Location
scripts/mercadolibre_search_common.py:107
Finding
Unrestricted API Base URL Allows Authentication Traffic to Be Redirected to Untrusted or Insecure Origins<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mercadolibre_search_common.py:11,107-110`; `scripts/geekbi_auth.py:564-579,698-721`; query scripts exposing `--base-url`, including `scripts/mercadolibre_goods_search.py:62-70` **Vulnerability Type**: Unvalidated authentication destination and insecure transport **Risk Level**: High ### Vulnerable Code ```python # scripts/mercadolibre_search_common.py:11 DEFAULT_BASE_URL = "https://openapi.geekbi.com" ``` ```python # scripts/mercadolibre_search_common.py:107-110 def build_url(base_url, endpoint, params): url = f"{base_url.rstrip('/')}{endpoint}" query = urlencode(params) return f"{url}?{query}" if query else url ``` ```python # scripts/geekbi_auth.py:564-579 def complete_pending_login(base_url, timeout): payload = _load_state() server_key = _server_key(base_url) server = payload["servers"].get(server_key) if not isinstance(server, dict): return False now = int(time.time()) changed = _clear_expired(server, now) pending = server.get("pending") if not isinstance(pending, dict): if changed: _persist_expiry_cleanup(server_key, now) return False endpoint = f"{base_url.rstrip('/')}{TOKEN_ENDPOINT}" try: response = _post_json(endpoint, {"deviceCode": pending["deviceCode"]}, timeout) ``` ```python # scripts/geekbi_auth.py:698-721 def authenticated_json_request( url, base_url, timeout, *, method="GET", body=None, headers=None, ): complete_pending_login(base_url, timeout) request_headers = _api_headers() if headers: request_headers.update(headers) authorization = _authorization_header(base_url) if authorization: request_headers["token"] = authorization request = Request( url, data=body, headers=request_headers, method=method, ) try: with urlopen(request, timeout=timeout) as response: ``` ```pyth ...[truncated 3955 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--base-url` from production-facing query commands unless custom endpoints are a documented requirement. 2. Enforce an explicit origin allowlist, preferably only: - Scheme: `https` - Host: `openapi.geekbi.com` - Default HTTPS port 3. Parse URLs with `urllib.parse.urlsplit` rather than validating them through string matching. 4. Reject URLs containing user information, fragments, unexpected ports, malformed hostnames, or non-root path prefixes. 5. Ensure the API request URL and authentication base URL resolve to the same canonical approved origin. 6. Disable redirects for authenticated requests or implement a redirect handler that rejects every cross-origin redirect. 7. Never forward the `token` header after a redirect unless the destination is the same validated origin. 8. Validate server-provided action URLs before presenting them to users. Require HTTPS and an explicitly approved authentication hostname. 9. Add automated tests covering HTTP URLs, unknown hosts, embedded credentials, deceptive hostname suffixes, unexpected ports, and cross-origin redirects. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/geekbi_auth.py:52
Finding
Reusable Bearer Tokens Are Unnecessarily Mirrored into Skill and Working Directories<![CDATA[ ## Vulnerability Details **File Location**: `scripts/geekbi_auth.py:52-74,386-400,637-648` **Vulnerability Type**: Excessive plaintext credential persistence **Risk Level**: Medium ### Vulnerable Code ```python # scripts/geekbi_auth.py:52-74 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"), ) ``` ```python # scripts/geekbi_auth.py:386-400 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)}") if written == 0: reason = ";".join(errors) or "Authentication state directory is unavailable" raise OSError(reason) ``` ```python # scripts/geekbi_auth.py:637-648 def save_token(latest): latest_server = latest["servers"].get(server_key) if not isinstance(latest_server, dict): return False, False latest_pending = latest_server.get("pending") if not isinstance(latest_pending, dict): return False, False if latest_pending.get("deviceCode") != pending.get("deviceCode"): return False, False _remove_access_token(latest_server) latest_server["accessToken"] = access_token latest_server["accessTokenExpires ...[truncated 3134 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store authentication state only in the platform-specific user configuration directory. 2. Prefer the operating system's protected credential facility, such as Keychain, Credential Manager, or Secret Service, for the bearer token. 3. Do not write tokens into the Skill installation directory or current working directory. 4. If cross-process state synchronization is required, synchronize only non-sensitive metadata and keep the bearer token in one protected store. 5. Correct the `temu-research-skill` directory name to a Skill-specific Mercado Libre namespace after implementing a secure migration process. 6. Document the credential location, retention period, expiration behavior, and revocation procedure. 7. Make cleanup failures visible instead of silently ignoring every deletion error. 8. On startup, detect legacy mirrored files, securely migrate the active token where feasible, and delete obsolete copies with explicit error reporting. 9. Add tests asserting that authentication never creates state files beneath the project, Skill package, or arbitrary current working directory. 10. Continue enforcing restrictive file permissions as defense in depth, but do not treat permissions as a substitute for minimizing credential copies. ]]>
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

Static analysis

No suspicious patterns detected.