Back to skill

Security audit

极鲸云Shopee店铺搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its Shopee research purpose, but it stores login tokens in multiple local places and permits unvalidated authentication/API destinations, so it needs review before installation.

Install only if you trust GeekBI and will use the default GeekBI endpoint. Be aware that login state can be written into local skill and workspace folders as well as user config, so avoid using this in shared or synced workspaces and clear auth state when finished.

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:69
Finding
Bearer Tokens Are Persisted in Multiple Unnecessary Locations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/geekbi_auth.py:69-89`, with token persistence at `scripts/geekbi_auth.py:357-376` and `scripts/geekbi_auth.py:631-652` **Vulnerability Type**: Excessive credential storage and authentication-state namespace collision **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"), ) ``` The resolved stores are all written when authentication state changes: ```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)}") if written == 0: reason = ";".join(errors) or "登录状态目录不可用" raise OSError(reason) ``` The persisted state includes the bearer token: ```python 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(l ...[truncated 2967 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Persist authentication state only in a dedicated user configuration directory, for example: ```python user_config_path("GeekBI", appauthor=False, ensure_exists=True) \ / "geekbi-shopee-shop-search-skill" \ / AUTH_FILE_NAME ``` 2. Remove `_skill_state_path()` and `_workspace_state_path()` from `_resolve_stores()`. 3. Correct the `temu-research-skill` namespace to a unique Shopee Skill identifier. 4. Prefer operating-system credential facilities such as Keychain, Credential Manager, or Secret Service for bearer tokens. 5. If file storage is required, fail closed when restrictive permissions cannot be established instead of silently ignoring permission-setting failures. 6. Migrate existing state by reading legacy locations once, writing the token into the secure canonical store, and securely deleting all legacy copies. 7. Avoid returning exact credential-storage paths in normal user-visible output unless diagnostic disclosure is explicitly requested. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/geekbi_auth.py:698
Finding
Unrestricted Base URLs Permit Insecure Authentication Destinations and Untrusted Action Links<![CDATA[ ## Vulnerability Details **File Location**: `scripts/geekbi_auth.py:698-721`, with affected CLI inputs in `scripts/shopee_goods_search.py:59-67`, `scripts/shopee_mall_info.py:27-34`, and `scripts/shopee_site_list.py:77-83` **Vulnerability Type**: Missing destination validation for authenticated network requests **Risk Level**: Medium ### Vulnerable Code The shared authenticated request function forwards authentication material without validating the destination scheme or host: ```python 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: response_payload = _read_json_response(response) _raise_action_if_needed(response_payload) return response_payload ``` Each API client exposes the destination directly as a command-line option: ```python parser.add_argument("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--param", action="append", default=[], help="查询条件,格式为 名称=值") 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 ) ``` URL construction performs only string concatenation: ```python def build_url(base_url, endpoint, params): url = f"{base_url.rstrip('/')}{endpoint}" query = urlencode(params) return f"{url}?{query}" if query else url ``` The authentication flow also accept ...[truncated 4194 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--base-url` from production-facing commands if endpoint customization is not required. 2. If customization is required, parse the URL with `urllib.parse.urlsplit` and enforce: - Scheme exactly equal to `https`. - Hostname in an explicit allowlist. - Only approved ports. - No username or password component. - No query string or fragment in the base URL. 3. Normalize the origin before using it as an authentication-state key. 4. Ensure the final API request URL has the same normalized origin as the validated base URL. 5. Disable automatic redirects for authenticated requests or manually follow only same-origin HTTPS redirects. 6. Never forward the `token` header across an origin change. 7. Validate every `jumpUrl` before displaying it. Permit only HTTPS URLs on explicitly approved GeekBI authentication hosts. 8. If an invalid action URL is received, stop the workflow and report a generic authentication error without rendering the URL as clickable content. 9. Add automated tests covering HTTP URLs, alternate hosts, embedded credentials, nonstandard ports, malformed URLs, cross-origin redirects, and malicious `jumpUrl` values. ]]>
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.