Back to skill

Security audit

online-shopping-discount

Security checks for vulnerabilities and agentic risk

Overview

This shopping discount skill mostly matches its stated purpose, but it automatically sends a stable device identifier to a remote service and handles cached credentials in ways users may not expect.

Review this skill before installing. It contacts a remote shopping API, registers an account, stores credentials locally, and may send your machine UUID or machine-id unless you provide a username yourself. Prefer using an explicit throwaway username, avoid printing the credential cache, and install only if you are comfortable with the remote service receiving shopping queries and account identifiers.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/register.sh:49
Finding
Persistent Device Identifier Collected and Transmitted to an External Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/register.sh:49-85`, `scripts/register.sh:174-199` **Vulnerability Type**: Excessive collection and external transmission of a stable device identifier **Risk Level**: Medium ### Vulnerable Code ```bash get_device_uuid() { local uuid="" if [[ "$OSTYPE" == "darwin"* ]]; then if command -v ioreg >/dev/null 2>&1; then uuid=$(ioreg -rd1 -c IOPlatformExpertDevice 2>/dev/null | awk -F'"' '/IOPlatformUUID/ {print $4; exit}') fi elif [[ "$OSTYPE" == "linux"* ]] || [[ "$OSTYPE" == "gnu"* ]]; then if [ -r /sys/class/dmi/id/product_uuid ]; then uuid=$(cat /sys/class/dmi/id/product_uuid 2>/dev/null) elif [ -r /etc/machine-id ]; then uuid=$(cat /etc/machine-id 2>/dev/null) fi elif [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "cygwin"* ]] || [[ "$OSTYPE" == "win32"* ]]; then if command -v powershell.exe >/dev/null 2>&1; then uuid=$(powershell.exe -NoProfile -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID" 2>/dev/null | tr -d '\r') elif command -v pwsh >/dev/null 2>&1; then uuid=$(pwsh -NoProfile -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID" 2>/dev/null | tr -d '\r') elif command -v wmic >/dev/null 2>&1; then uuid=$(wmic csproduct get UUID 2>/dev/null | awk 'NF && $0 !~ /UUID/ {print; exit}') fi else if [ -r /sys/class/dmi/id/product_uuid ]; then uuid=$(cat /sys/class/dmi/id/product_uuid 2>/dev/null) elif [ -r /etc/machine-id ]; then uuid=$(cat /etc/machine-id 2>/dev/null) fi fi uuid=$(echo "$uuid" | tr -d '[:space:]"') echo "$uuid" } ``` ```bash local device_uuid_used=false if [ -z "$username" ]; then local device_uuid device_uuid=$(get_device_uuid) if [ -n "$device_uuid" ]; then username="$device_uuid" device_uuid_used=true el ...[truncated 2892 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `get_device_uuid` and never access DMI UUIDs, `/etc/machine-id`, macOS platform UUIDs, or Windows hardware UUIDs for this workflow. 2. Generate a cryptographically random, application-specific pseudonymous identifier instead: ```bash generate_client_id() { if command -v openssl >/dev/null 2>&1; then openssl rand -hex 16 else tr -dc 'a-f0-9' </dev/urandom | head -c 32 fi } ``` 3. Use the generated value only for the minimum period required by the service. 4. If a persistent client identifier is necessary, store a random application identifier in a permission-restricted file rather than deriving it from the host. 5. Do not return or cache a `device_uuid` field. 6. Require explicit, informed user consent before collecting any persistent device identifier. 7. Document the external service operator, the transmitted fields, retention policy, and privacy policy. 8. Add automated tests that fail if the registration script accesses known machine-identity resources. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search_products.sh:73
Finding
Credential Exposed Through Process Arguments and GET Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search_products.sh:73-76`, `scripts/search_products.sh:124-143`; related usage in `SKILL.md:143-147` and `scripts/generate_link.sh:72-75` **Vulnerability Type**: Insecure credential handling and sensitive data exposure **Risk Level**: Medium ### Vulnerable Code The credential is accepted as a command-line argument: ```bash --credential) CREDENTIAL="$2" shift 2 ;; ``` The search workflow then defaults `user_id` to the credential and transmits it through an HTTP GET query parameter: ```bash local endpoint endpoint="$(normalized_endpoint "$API_ENDPOINT")/coupon/search" local user_value="${USER_ID:-$CREDENTIAL}" local curl_cmd=(curl -s -G --max-time "$TIMEOUT") curl_cmd+=(--data-urlencode "keyword=$KEYWORD") if [ -n "$PLATFORM" ]; then curl_cmd+=(--data-urlencode "platform=$PLATFORM") fi if [ -n "$user_value" ]; then curl_cmd+=(--data-urlencode "user_id=$user_value") fi if [ -n "$START_PRICE" ]; then curl_cmd+=(--data-urlencode "start_price=$START_PRICE") fi if [ -n "$END_PRICE" ]; then curl_cmd+=(--data-urlencode "end_price=$END_PRICE") fi curl_cmd+=("$endpoint") local response if ! response=$("${curl_cmd[@]}"); then error_exit "Search request failed" "NETWORK_ERROR" fi ``` The skill documentation explicitly instructs callers to place the credential in the command line: ```bash ./scripts/search_products.sh \ --credential "token_abc123xyz" \ --keyword "无线耳机" \ --platform "taobao" ``` The link-generation script uses the same command-line pattern: ```bash --credential) CREDENTIAL="$2" shift 2 ;; ``` ### Technical Analysis Secrets passed as command-line arguments may be exposed through process inspection mechanisms, debugging tools, command auditing, shell history, orchestration logs, or agent execution telemetry. Quoting the value prevents shell word splitting but does not remove it from the process argument vector. The search script further ...[truncated 2373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Stop accepting credentials directly through command-line arguments. Read them from a permission-restricted file descriptor, standard input, or a protected secret store. 2. Send authentication material in an HTTP authorization header rather than as request data: ```bash curl_cmd=( curl -sS -X POST --max-time "$TIMEOUT" -H "Authorization: Bearer $CREDENTIAL" -H "Content-Type: application/x-www-form-urlencoded" ) ``` 3. Use a separate, non-secret opaque account identifier when the API requires `user_id`. Never default it to the authentication credential. 4. Change sensitive search requests from GET to POST so identity and search parameters are not stored in ordinary URL logs. 5. Configure servers, reverse proxies, observability systems, and error trackers to redact authorization data and sensitive identifiers. 6. Update `SKILL.md`, `EXAMPLE.md`, and `scripts/README.md` so examples do not encourage embedding credentials in command lines. 7. Rotate existing credentials because historical process and HTTP logs may already contain them. 8. Ensure credentials have limited scope, short expiration periods, server-side revocation support, and rate limits. 9. Use `curl -sS --fail-with-body` and validate HTTP status codes so authentication and transport failures cannot be mistaken for normal API responses. 10. Add regression tests confirming that credentials do not appear in process arguments, generated URLs, standard output, or logs. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill depends on external credentials and remote API access while the declared purpose under-describes those external interactions and overstates implemented capabilities such as recommendation and link generation logic. Undisclosed external access is risky because users and orchestrators may approve a benign-looking shopping skill without realizing it performs authenticated network operations and token handling.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill depends on external credentials and remote API access while the declared purpose under-describes those external interactions and overstates implemented capabilities such as recommendation and link generation logic. Undisclosed external access is risky because users and orchestrators may approve a benign-looking shopping skill without realizing it performs authenticated network operations and token handling.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The skill depends on external credentials and remote API access while the declared purpose under-describes those external interactions and overstates implemented capabilities such as recommendation and link generation logic. Undisclosed external access is risky because users and orchestrators may approve a benign-looking shopping skill without realizing it performs authenticated network operations and token handling.

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/search_products.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/generate_link.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/generate_link.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
# scripts/generate_link.sh
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script collects a persistent device identifier (IOPlatformUUID, product_uuid, machine-id, or Windows UUID) and, when available, uses it as the username sent to a remote registration endpoint. For a shopping discount skill, this hardware-derived identifier is not necessary for core functionality and creates an unnecessary device fingerprint that enables cross-session tracking, correlation, and privacy loss if the service or logs are compromised.

External Transmission

Medium
Category
Data Exfiltration
Content
🔗 购买链接:https://s.click.taobao.com/xxx

📱 二维码:https://api.example.com/qr/xxx.png

⏰ 有效期:7天(至 2026-03-16)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
Manifest 仅声明“查找优惠商品信息、生成优惠建议和优惠链接”,并列举商品搜索、价格比较、优惠推荐和链接生成。L283-L296 额外描述了持续性的价格监控与后续通知能力,这属于长期跟踪/提醒功能,不是前述购物查询与链接生成的直接实现细节。

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The examples normalize automatic credential registration, local storage, refresh, and cross-session reuse without clear user-facing disclosure or consent about how credentials are stored and shared. This can lead to unsafe deployment assumptions, especially in shared agents, multi-tenant environments, or systems where local files may be accessible to other processes.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The document explicitly instructs viewing the local credential cache file with `cat scripts/.credential_cache | jq .`, exposing secret material that is not necessary for normal shopping-query functionality. Encouraging direct credential inspection increases the chance of secret disclosure through logs, transcripts, screenshots, or model output.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill instructs the agent to execute shell scripts (`register.sh`, `search_products.sh`, `generate_link.sh`) but does not declare any explicit tool scope or allowed-tools boundary. This creates an authorization ambiguity where a host agent may invoke shell access more broadly than intended, increasing the chance of unsafe command execution or policy bypass.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The entire skill description, prompts, and example interactions are written exclusively in Chinese, and the skill presents Chinese-only response templates without any opt-in or alternative language behavior. This can violate language/locale policy when a user has not chosen Chinese or may prefer another language.

Vague Triggers

Medium
Confidence
97% confidence
Finding
The trigger keywords are extremely broad (`买`, `购物`, `buy`, `discount`, etc.), making the skill likely to activate in ordinary conversation far beyond narrowly intended contexts. Over-broad activation is dangerous here because activation leads to shell-driven registration, credential use, and network queries, potentially causing unintended external actions or data disclosure from casual user prompts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation describes automatic collection and transmission of the local machine's device UUID during registration, but provides no clear consent flow, privacy notice, or explanation of why this sensitive identifier is needed. This creates a privacy/security issue because persistent hardware identifiers can be used to track users or correlate activity across environments, especially when silently sent to a backend service.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The README states that if no username is provided, the registration script automatically reads the host device UUID and uses it as the username. A hardware/device UUID is a persistent identifier unrelated to the shopping-discount function, and sending it to a service enables host fingerprinting and cross-session tracking. In this skill context, that data collection is not necessary for product search or coupon generation, which makes it more suspicious and increases privacy risk.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script derives `user_id` from the credential when `--user_id` is not provided and sends that value to a remote API. Even though the default endpoint is HTTPS and the value is URL-encoded, this still discloses an authentication-related identifier over the network without clear consent or minimization, which can expose user/account linkage data to the service and any configured alternate endpoint.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The script's comments, help text, logs, and error messages are written in Chinese, and there is no indication that users can select another language or opt in to this locale. This is a natural-language policy concern because the skill imposes a specific language on all users rather than documenting a locale constraint or providing a choice.

Static analysis

No suspicious patterns detected.