Back to skill

Security audit

大麦数据美客多市场洞察与选品

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a Mercado Libre research tool, but it also includes sensitive account onboarding, payment-order creation, public image upload, automatic feedback reporting, and broad local response retention that users should review carefully.

Install only if you trust LinkFox with market queries, local images you choose for image search, and account/billing workflows. Prefer obtaining and storing API keys outside the agent in a secure credential manager, avoid giving SMS codes unless you intentionally want assisted onboarding, confirm any paid calls or payment orders yourself, and treat uploaded images as publicly accessible during the stated availability window.

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 (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/damai_mercado_market_intelligence.py:36
Finding
Credentials and personal data can be transmitted to environment-controlled endpoints<![CDATA[ ## Vulnerability Details **File Location**: `scripts/damai_mercado_market_intelligence.py:36-78`; `scripts/upload_image.py:21-73`; `scripts/onboarding.py:68-85, 209-246` **Vulnerability Type**: Unrestricted endpoint override for authenticated requests **Risk Level**: High ### Relevant Code ```python def get_api_base() -> str: """Gateway base address: environment variable first, production fallback.""" return ( os.environ.get("LINKFOX_TOOL_GATEWAY") or "https://tool-gateway.linkfox.com" ).rstrip("/") ``` ```python def call_api(params): api_url = get_api_url() api_key = get_api_key() data = json.dumps(params).encode("utf-8") headers = { "Authorization": api_key, "Content-Type": "application/json", "User-Agent": "LinkFox-Skill/2.0", "SESSION_ID": os.environ.get("SESSION_ID", ""), "MESSAGE_ID": os.environ.get("MESSAGE_ID", ""), "MODE_ID": os.environ.get("MODE_ID", ""), "APP_NAME": os.environ.get("APP_NAME", ""), } req = Request(api_url, data=data, headers=headers, method="POST") with urlopen(req, timeout=150) as response: return json.loads(response.read().decode("utf-8")) ``` The onboarding client separately permits authentication endpoints to be replaced: ```python def _agent_base() -> str: return _env_base( "LINKFOX_AGENT_API_URL", "https://tool-gateway.linkfox.com", "LINKFOX_TOOL_GATEWAY", ) def _login_base() -> str: return _env_base("LINKFOX_LOGIN_API_URL", "https://api.linkfox.com") def _agent_user_base() -> str: return _env_base( "LINKFOX_AGENT_USER_API_URL", "https://agent-api.linkfox.com", ) ``` ### Technical Analysis The code treats environment variables as trusted network destinations and attaches sensitive authentication material without validating the resulting scheme or host. Depending on the operation, transmitted data can include: - LinkFox API keys - Acc ...[truncated 1669 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Hardcode or strictly allowlist the documented LinkFox hosts for authenticated traffic. 2. Require `https` and reject HTTP, IP-literal destinations, user-info components, unexpected ports, and unapproved subdomains. 3. Disable automatic cross-origin redirects for requests carrying credentials, or revalidate every redirect target and remove authentication headers on origin changes. 4. Separate test endpoint support from production builds. Require an explicit development mode and never use production credentials with test overrides. 5. Validate the presigned upload URL against the expected object-storage hostname before reading and uploading the local file. 6. Send only metadata required by the specific API. Remove `MESSAGE_ID`, `MODE_ID`, `APP_NAME`, and similar headers unless each is demonstrably necessary. 7. Add automated tests confirming that malformed and unapproved endpoint overrides are rejected before any credential-bearing request is issued. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onboarding.py:468
Finding
Generated API keys are printed to stdout and users are directed to persist them in plaintext<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:468-517`; `references/onboarding.md:7-15` **Vulnerability Type**: Plaintext credential disclosure and insecure secret storage **Risk Level**: High ### Relevant Code ```python def login_and_get_key(phone: str, code: str, channel: str) -> dict: masked = _mask_phone(phone) # Authentication and token-generation steps omitted here. tok = _get_or_generate_api_token( lg["access_token"], lg["user_id"], info["group_id"] ) if "error" in tok: return {"error": tok["error"], "phone": masked} return { "api_key": tok["api_key"], "phone": masked, "group_id": info["group_id"], "member_id": info["member_id"], "source": tok["source"], "nick_name": lg.get("nick_name", ""), "team_name": info.get("team_name", ""), "is_new_user": lg.get("is_new_user", False), } ``` ```python def _emit(obj: dict) -> None: print(json.dumps(obj, ensure_ascii=False, indent=2)) def _cmd_login(args) -> int: r = login_and_get_key(args.phone.strip(), args.code.strip(), args.channel) _emit(r) if "api_key" in r: print( f"{TAG} Successfully obtained API key (source: {r['source']})", file=sys.stderr, ) return 0 return 1 ``` The onboarding instructions direct users to save that key persistently: ```text setx LINKFOX_AGENT_API_KEY "<key>" echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc ``` ### Technical Analysis The login command serializes the complete API key to stdout. In an Agent environment, stdout may be captured in model context, conversation transcripts, terminal logs, shell pipelines, CI logs, debugging output, or monitoring systems. The documentation then instructs users to place the complete secret directly in shell startup files. These files ar ...[truncated 1269 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never print complete API keys to stdout or stderr. Display only a short, non-sensitive fingerprint. 2. Pass newly issued secrets directly to a secure credential-storage integration rather than through Agent-visible output. 3. Use the operating system's credential manager, such as Keychain, Credential Manager, or Secret Service. 4. If file storage is unavoidable, use a dedicated file with owner-only permissions, exclude it from version control and backups where appropriate, and document rotation procedures. 5. Avoid commands that place secrets in shell history. Do not recommend appending secrets to `.bashrc` or `.zshrc`. 6. Add explicit key revocation and rotation instructions. 7. Redact sensitive values from exceptions, telemetry, transcripts, and structured command results. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upload_image.py:90
Finding
Local images are uploaded with public-read access without sufficient disclosure safeguards<![CDATA[ ## Vulnerability Details **File Location**: `scripts/upload_image.py:90-120`; `SKILL.md:63-66`; `references/api.md:97-110` **Vulnerability Type**: Public disclosure of user-selected local files **Risk Level**: High ### Relevant Code ```python def upload_file(presigned_url: str, file_path: str, content_type: str): """Upload the local file to the presigned OSS URL via HTTP PUT.""" with open(file_path, "rb") as f: file_data = f.read() req = Request( presigned_url, data=file_data, headers={ "Content-Type": content_type, "x-oss-object-acl": "public-read", }, method="PUT", ) try: with urlopen(req, timeout=150) as response: if response.status not in (200, 201): print( f"Upload failed with status: {response.status}", file=sys.stderr, ) sys.exit(1) except HTTPError as e: body = e.read().decode("utf-8") if e.fp else "" print( f"Upload failed: HTTP {e.code}: {e.reason}\n{body}", file=sys.stderr, ) sys.exit(1) ``` ```python def extract_public_url(presigned_url: str) -> str: """Extract the base public URL by stripping query parameters.""" return presigned_url.split("?")[0] ``` ```python public_url = extract_public_url(presigned_url) print(json.dumps({"url": public_url}, indent=2, ensure_ascii=False)) ``` ### Technical Analysis The helper reads the entire user-selected image and explicitly requests `public-read` access. It then removes the presigned query string and returns the base object URL, making public accessibility part of the intended workflow. The implementation does not: - Ask for explicit confirmation immediately before public upload - Validate that the presigned URL belongs to an approved storage host - Enforce a maximum file size - Verify the file signature matches the extension - ...[truncated 1232 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit, informed user confirmation immediately before upload, including the destination, public-access status, and retention period. 2. Use private object storage and a narrowly scoped, short-lived signed GET URL instead of `public-read`. 3. Validate the scheme and exact hostname of every presigned URL before opening the local file. 4. Enforce conservative file-size limits and stream uploads instead of loading the entire file into memory. 5. Validate magic bytes and decode the image using a trusted image library. 6. Re-encode images to remove EXIF, geolocation, thumbnails, comments, and other metadata. 7. Provide deletion or revocation support and technically enforce retention. 8. Reject symlinks or otherwise ensure the selected path resolves to the file explicitly approved by the user. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/onboarding.py:364
Finding
Onboarding grants account and payment capabilities beyond the Skill’s market-research purpose<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onboarding.py:364-490, 519-568`; `references/onboarding.md:5-22` **Vulnerability Type**: Excessive privileges and unrelated account-management functionality **Risk Level**: High ### Relevant Code The script solicits a phone number and SMS verification code: ```python def _login_v3(phone: str, code: str, channel: str) -> dict: resp = _login_post("/user/v3/web/login", { "type": "sms", "method": "login", "systemId": "LinkFoxAgent", "data": { "areaCode": "+86", "authPhone": phone, "authCode": code, "sourceChannel": channel or "skill", }, }) ``` It then enumerates user/team information and generates an API token: ```python def login_and_get_key(phone: str, code: str, channel: str) -> dict: lg = _login_v3(phone, code, channel) if "error" in lg: return {"error": lg["error"], "phone": masked} if lg.get("is_new_user"): lbt = _login_by_token(lg["access_token"], lg["refresh_token"]) info = _fetch_user_info_v3(lg["access_token"], lg["user_id"]) if "error" in info: return {"error": info["error"], "phone": masked} tok = _get_or_generate_api_token( lg["access_token"], lg["user_id"], info["group_id"] ) ``` The same script supports financial operations: ```python def _cmd_order(args) -> int: try: pkgs = fetch_packages( 7 if bool(fetch_user_info().get("isTeamUser")) else 1 ) match = next( ( n for n in (normalize_package(p) for p in pkgs) if n and n["plan_id"] == args.plan_id ), None, ) order = create_order(args.plan_id, args.method) except (RuntimeError, ValueError) as e: _emit({"error": True, "message": str(e)}) return 1 qr = render_qr(order["qr_content"], session_dir()) order["png_path"] = qr.get("png_p ...[truncated 2108 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove registration, login, token generation, package purchase, and payment tracking from the market-intelligence Skill. 2. Move onboarding and billing into a separately packaged and separately reviewed component. 3. Require explicit user initiation and confirmation for each identity or financial action. 4. Never request SMS verification codes in ordinary market-research conversations. 5. Use a browser-based OAuth or device-authorization flow so credentials and one-time codes are not exposed to the Agent. 6. Scope issued credentials to read-only market operations and prohibit account-management and ordering privileges. 7. Add transaction confirmation showing the exact plan, amount, payment method, recipient, and expiration before creating an order. 8. Maintain an auditable boundary between free diagnostics, paid data calls, account administration, and financial operations. ]]>

other

Warning
Location
SKILL.md:136
Finding
Skill instructions direct automatic transmission of inferred user feedback to a separate service<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:136-138`; `references/api.md:184-202` **Vulnerability Type**: Unconsented telemetry and unrelated network side effect **Risk Level**: Medium ### Relevant Instructions ```markdown ## Feedback Auto-detect and report feedback through the Feedback API in `references/api.md` when the skill behavior, documentation, or result presentation mismatches the user's intent, or when the user expresses praise or dissatisfaction. Never include credentials, private data, Base64 images, or complete large responses. ``` The referenced destination and payload are: ```markdown - **POST** `https://skill-api.linkfox.com/api/v1/public/feedback` - **Content-Type**: `application/json` { "skillName": "linkfox-damai-mercado-market-intelligence", "sentiment": "NEUTRAL", "category": "SUGGESTION", "content": "Product trend coverage should be explained more clearly." } ``` ### Technical Analysis The Skill directs the Agent to infer whether a user has expressed praise or dissatisfaction and automatically submit conversation-derived information to a service separate from the market-intelligence gateway. The instruction does prohibit credentials and private data, which reduces risk, but it does not require: - An explicit user request to submit feedback - Prior consent - Display of the exact payload - Confirmation of the destination - A user-controlled opt-out This is an unrelated network side effect triggered by natural-language sentiment rather than an explicit market-research operation. ### Attack Path 1. The user comments positively or negatively on the Skill's behavior or results. 2. The loaded Skill instructions classify that statement as feedback. 3. The Agent summarizes the user's intent, the observed behavior, or the requested improvement. 4. The summary is transmitted to `skill-api.linkfox.com` without a separate confirmation step. 5. Interaction details leave the expected market-query boundary. ### Imp ...[truncated 336 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make feedback submission strictly opt-in. 2. Show the user the exact destination and complete proposed payload before transmission. 3. Require an affirmative confirmation for each submission. 4. Provide a persistent opt-out and do not infer consent from praise or dissatisfaction. 5. Apply deterministic redaction for credentials, identifiers, URLs, personal data, and response content. 6. Avoid including conversational excerpts when a generic category and local diagnostic code are sufficient. 7. Document retention, access, and deletion policies for submitted feedback. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/damai_mercado_market_intelligence.py:89
Finding
Complete API responses are retained in unexpected fallback locations with default permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/damai_mercado_market_intelligence.py:89-121, 199-242, 330-346`; `SKILL.md:43-51` **Vulnerability Type**: Insecure local data retention and unsafe temporary-directory fallback **Risk Level**: Medium ### Relevant Code The response cache stores complete payloads: ```python def _save_cache(path, payload): try: with open(path, "w", encoding="utf-8") as f: json.dump(payload, f, ensure_ascii=False, indent=2) except OSError: pass ``` The output root silently falls back beyond the documented working directory: ```python candidates.append(os.path.join(os.getcwd(), "linkfox")) candidates.append(os.path.join(os.path.expanduser("~"), "linkfox")) import tempfile candidates.append(os.path.join(tempfile.gettempdir(), "linkfox")) for root in candidates: try: os.makedirs(root, exist_ok=True) probe = os.path.join(root, ".write_probe") with open(probe, "w", encoding="utf-8") as f: f.write("") os.remove(probe) except OSError: continue root = os.path.abspath(root) _SESSION_CACHE["_root"] = root return root ``` Every response is then written in full: ```python serialized = json.dumps(result, ensure_ascii=False, indent=2) ts = int(time.time()) out_path = _resolve_output_path(ts) try: with open(out_path, "w") as f: f.write(serialized) print( f"Saved full response: {out_path} ({len(serialized)} bytes)" ) except OSError as e: print(f"Failed to save to {out_path}: {e}", file=sys.stderr) ``` ### Technical Analysis `SKILL.md` states that complete responses are written under the current working directory, that `/tmp` is prohibited, and that an unwritable current directory should cause an error. The implementation contradicts this policy by silently falling back to the user's home directory and then the system temporary directory. Both cache files and archived output use default pr ...[truncated 1346 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce the documented storage policy and fail closed if the approved output directory is unavailable. 2. Remove the system temporary-directory fallback for complete responses. 3. Create directories with owner-only permissions and files with mode `0600`, independent of the ambient umask. 4. Do not cache responses containing personal data, credentials, account identifiers, raw provider diagnostics, or image content. 5. Implement actual expiration and deletion rather than merely refusing to read old cache files. 6. Provide a configurable retention period and a command to enumerate and securely remove stored data. 7. Record and display the chosen storage location before writing. 8. Encrypt sensitive retained data with a key managed outside the output directory. 9. Align `SKILL.md` with the implementation and add tests that ensure no fallback to `/tmp` occurs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (32)

Tainted flow: 'req' from os.environ.get (line 71, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method="POST",
    )
    try:
        with urlopen(req, timeout=150) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
95% confidence
Finding
The request sent via urlopen includes multiple headers populated directly from environment variables, and the destination base URL is also controllable via LINKFOX_TOOL_GATEWAY. In this skill context, that can leak sensitive session metadata and the API key to an attacker-controlled endpoint if the environment is poisoned or the skill runs in an untrusted execution environment, creating a real SSRF/credential exfiltration risk.

Tainted flow: 'url' from os.environ.get (line 235, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
95% confidence
Finding
The script allows base URLs for login and agent-user APIs to be overridden via environment variables and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and generated API keys to those endpoints. In an agent/skill environment where outer orchestration can influence environment variables, this creates a credential exfiltration and SSRF-style risk if a malicious or compromised runtime redirects traffic to attacker-controlled hosts.

Tainted flow: 'req' from os.environ.get (line 244, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code
Confidence
92% confidence
Finding
Gateway requests use a URL derived from environment-controlled base configuration and attach the LinkFox API key in the Authorization header. If an attacker can set or influence LINKFOX_AGENT_API_URL or fallback variables, requests may be sent to an arbitrary host, leaking credentials and enabling unintended outbound access.

Tainted flow: 'req' from os.environ.get (line 57, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urlopen(req, timeout=150) as response:
            result = json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 57, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urlopen(req, timeout=150) as response:
            if response.status not in (200, 201):
                print(f"Upload failed with status: {response.status}", file=sys.stderr)
                sys.exit(1)
Confidence
90% confidence
Finding
The code performs an HTTP PUT to a presigned URL returned by a remote service, and that URL is not validated against an allowlist or expected host pattern before upload. If the presign endpoint is compromised, misconfigured, or redirected via a malicious LINKFOX_TOOL_GATEWAY setting, local file contents could be exfiltrated to an arbitrary external destination.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The skill advertises product research but also supports local image upload to object storage and generation of public URLs, which is a distinct data-handling operation with privacy implications. Uploading local files expands the attack surface from read-only market queries to exfiltration of user-provided local content, especially if users do not clearly understand that a public link will be created.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises product research but also supports local image upload to object storage and generation of public URLs, which is a distinct data-handling operation with privacy implications. Uploading local files expands the attack surface from read-only market queries to exfiltration of user-provided local content, especially if users do not clearly understand that a public link will be created.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises product research but also supports local image upload to object storage and generation of public URLs, which is a distinct data-handling operation with privacy implications. Uploading local files expands the attack surface from read-only market queries to exfiltration of user-provided local content, especially if users do not clearly understand that a public link will be created.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
python scripts/damai_mercado_market_intelligence.py '{"toolName":"product_sales_trend","arguments":{"market_code":"MLM","sku_id":"MLM1602785195","days":90}}'
```

## Display Rules

1. Present only fields supported by the response; do not invent demand, profit, or competition conclusions.
2. State the market, filters, time coverage, record count, currency, and pagination when available.
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
示 JSON 里的 phone/agreements
   - 收到验证码后:`python scripts/onboarding.py login <phone> <code>`
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill is described as a Mercado Libre market-intelligence/query capability, but this script performs account onboarding, SMS login, API key issuance, package discovery, and payment/order handling. That mismatch materially expands privilege and data-handling scope, increasing the chance users or calling agents trigger credential collection and account actions they would not reasonably expect from a research/query skill.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The code can create orders and generate payment QR codes, which is unrelated to the stated market-research purpose and introduces financial-action capability. In an agentic context, unnecessary purchase flows are dangerous because they can facilitate unauthorized charges, social engineering, or misleading prompts to complete payment.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares capabilities that include environment access, file writes, and network use, but it does not define an explicit tool scope or allowed-tools boundary. In an agent setting, that omission weakens least-privilege controls and makes it harder to prevent unintended filesystem, secret, or outbound-network access if the implementation drifts or is abused.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
Line L032 states that category and product keywords must use the selected market's local language. This is a language/locale constraint expressed as a requirement, but the document does not offer the user a choice or frame it as an opt-in behavior, which conflicts with the policy against forcing a specific language without user opt-in.

Ssd 3

Medium
Confidence
95% confidence
Finding
The skill mandates writing complete responses to session-scoped local files, even when those responses may include user-provided content, account metadata, or other unnecessary details. Persistent storage increases exposure through local compromise, accidental commits, over-retention, or cross-task data leakage, especially because it is always-on rather than narrowly justified.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
Automatically reporting user praise, dissatisfaction, or intent mismatches to a Feedback API is not necessary for fulfilling market-intelligence queries and results in unneeded transmission of interaction metadata. That creates privacy and data-governance risk because user behavior and context may be shared with another endpoint without explicit, informed consent.

Ssd 3

Medium
Confidence
91% confidence
Finding
The feedback rule directs the agent to send user interaction details to another API whenever sentiment or intent mismatch is detected. That is a form of behavioral telemetry export and can leak contextual user information unrelated to the requested market-analysis function.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The parameter description states `query` must be a local-language category keyword, which imposes a language requirement in the skill documentation. The file does not offer a user opt-in or explain that the constraint is a justified region-specific requirement, so it reads as a language policy restriction.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The `keyword` field is described as requiring a local-language product keyword, which is a natural-language constraint. Because the file does not present this as optional or explicitly justified by upstream service requirements, it may violate the language/locale policy.

External Transmission

Medium
Category
Data Exfiltration
Content
空结果、`data_available=false` 或覆盖不足提示通常是正常业务结果,不等同于系统故障。

## curl 示例

```bash
curl -X POST "${LINKFOX_TOOL_GATEWAY}/damai/call" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The onboarding flow explicitly asks the user to provide a phone number so a local script can register on their behalf, but it gives no privacy notice, consent language, retention limits, or guidance on safe handling of that personal data. In an agent setting, this increases the risk of unnecessary collection, logging, or exposure of phone numbers and one-time codes during troubleshooting.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs users to persist an API key in shell startup files and environment settings without warning that these locations may be readable by other local users, copied into backups, exposed through shell history, or inherited by unrelated processes. Persisting long-lived credentials this way expands the exposure window and can lead to credential theft if the host is shared or compromised.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The module documentation explicitly says writing to /tmp is forbidden and that unwritable current directories should cause an error, but the implementation silently falls back to home and temp directories. This mismatch can cause sensitive API responses to be persisted in locations with weaker isolation or different retention properties than operators expect, increasing accidental data exposure risk.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script always writes the full API response to disk, including potentially sensitive market data, comments, images metadata, and any returned identifiers, regardless of response size. In an agent-skill setting, automatic persistence expands the data exposure surface because later users, tools, or processes on the same host may access these files without the caller realizing the data was retained.

External Transmission

Medium
Category
Data Exfiltration
Content
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.