Back to skill

Security audit

alibabacloud-help-doc-search

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed Alibaba Cloud documentation lookup tool, but its document-read command is under-scoped and can fetch non-Alibaba URLs or local files.

Review before installing. The normal search and metadata workflows are read-only and disclosed, but until the read command enforces an allowlist, avoid giving it untrusted URLs and prefer explicit official Alibaba Cloud HTTPS document URLs only. The publisher should reject non-Help Center hosts, non-HTTPS schemes, private or loopback destinations, file URLs, and unvalidated redirects.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/help_read.py:48
Finding
Arbitrary URL Fetch Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/help_read.py:48-63` **Vulnerability Type**: Arbitrary outbound request / SSRF **Risk Level**: High ### Vulnerable Code ```python url = args.url host = _url_host(url) # Ensure .md suffix if not url.endswith(".md"): # Only the two Help Center hosts serve raw Markdown at '<url>.md' if host in _DOC_HOSTS: url = url.rstrip("/") + ".md" site = (getattr(args, "site", None) or "").strip().lower() if site in SITES and host and host != SITES[site]["result_host"]: print(f"WARN[site-cross]: --site {site} points at {SITES[site]['result_host']} but the given URL is " f"on '{host}'; the URL is read as-is and no cross-site rewriting is performed", file=sys.stderr) text = fetch(url, max_bytes=DOC_MAX_BYTES) ``` The request is ultimately executed by the shared transport layer: ```python req = urllib.request.Request(url, headers={"User-Agent": UA}) opener = urllib.request.urlopen if allow_redirects else _NO_REDIRECT_OPENER.open try: with opener(req, timeout=effective_timeout(timeout or TIMEOUT)) as resp: data = resp.read() ``` ### Technical Analysis The `read` command accepts a user-controlled URL and derives its host with `_url_host()`. However, membership in `_DOC_HOSTS` is used only to determine whether the `.md` suffix should be appended. An unapproved host is never rejected. A site mismatch also produces only a warning and explicitly continues to read the URL as supplied. Consequently, arbitrary URL schemes and destinations accepted by `urllib.request` can reach the network transport. Redirects are enabled by default in `fetch()`. Therefore, even if direct input were later restricted to an approved Alibaba Cloud host, a redirect could still send the request to an unapproved destination unless every redirect target is validated. This behavior contradicts the module statement that only Help Center hosts are accepted and exceeds the minimum network access r ...[truncated 1478 chars]
Remediation
## Remediation Suggestions 1. Enforce an exact destination allowlist before every request: - Require the `https` scheme. - Permit only `help.aliyun.com` and `www.alibabacloud.com`. - Reject missing hosts, user-information components, nonstandard schemes, and unexpected ports. 2. Do not merely warn on a host mismatch. Return an input error before making a request. 3. Disable automatic redirects for document reads. If redirects are required, process them manually and validate every destination against the same scheme, host, and port policy. 4. Resolve the destination and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses. Repeat validation after each redirect and account for multiple DNS answers. 5. Consider constraining paths to the documented Help Center layouts rather than allowing every path on an approved domain. 6. Add regression tests covering: - Direct requests to localhost and private IP addresses. - Link-local metadata addresses. - Unsupported schemes such as `file:`. - Approved hosts redirecting to unapproved hosts. - Hostname parsing edge cases, embedded credentials, and unexpected ports. - Valid China and international Help Center document URLs. A suitable validation flow is: ```python parsed = urllib.parse.urlsplit(url) if parsed.scheme != "https": raise _UsageError("Only HTTPS Help Center URLs are supported.") if parsed.hostname not in _DOC_HOSTS: raise _UsageError("Only official Alibaba Cloud Help Center hosts are supported.") if parsed.username or parsed.password or parsed.port not in (None, 443): raise _UsageError("URL credentials and nonstandard ports are not supported.") text = fetch(url, max_bytes=DOC_MAX_BYTES, allow_redirects=False) ``` If legitimate canonical redirects must be supported, follow them through a bounded loop and apply the full validation policy to each `Location` value before issuing the next request.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (27)

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
rage profile to a candidate family, and finally validate with real-world testing before committing. The official selection guide walks through this decision process step by step and is the recommended starting point for capacity planning.

Source: https://help.aliyun.com/document_detail/58291.html

## How do subscription, pay-as-you-go, and preemptible instances differ?

Subscription is a prepaid model best for steady 7x24 services such as persistent web servers: you pay upfront for a fixed term at a lower effective price. Pay-as-you-go bills by the second/hour with no commitment, ideal for elastic, bursty, or short-lived workloads. Preemptible instances offer steep discounts over pay-as-you-go but can be reclaimed automatically when market price exceeds your cap or supply runs short, so they only fit interruption-tolerant jobs such as batch computation, CI, and stateless scaling.

Source: https://help.aliyun.com/document_detail/25370.html

## What are savings plans and how do they red
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Instruction Override

High
Category
Prompt Injection
Content
## Why can I not ping my ECS instance, and how do security groups factor in?

The security group must contain a rule allowing ICMP (ping) inbound; if that rule was removed, ping fails and you should restore it in the ECS console. Also check the VPC network ACL bound to the instance's vSwitch, because ACL rules restrict both inbound and outbound traffic and can override security-group allowances. Ping failures should be diagnosed layer by layer: security group rules, network ACLs, then OS-level firewall settings.

Source: https://help.aliyun.com/document_detail/40572.html
Confidence
90% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill describes capabilities that include environment-variable use, local cache reads/writes under the user's home directory, and outbound network access, but it does not declare an explicit tool/permission scope. That creates a governance gap: an orchestrator or reviewer cannot reliably constrain the skill to the minimum required privileges, increasing the chance of unintended file or network access if the implementation diverges from the documentation.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger list includes phrases like "help center", "best practice", "API reference", and especially "what does this error mean" / "how to fix this error", which are common across many domains and not uniquely tied to Alibaba Cloud. Although the description is Alibaba-specific overall, these broad phrases are presented as triggers without requiring explicit Alibaba Cloud context or negative examples, increasing the risk of unintended invocation.

Intent-Code Divergence

Medium
Confidence
82% confidence
Finding
Lines L139-L140 state that error codes, parameter names, and quota numbers are 'never recalled from the index leg' and that this is 'the metadata leg's job'. But earlier guidance distinguishes search-based narrative troubleshooting from explicit `api-info` metadata lookups for per-API contract data, so this wording overstates what ordinary search does and blurs tool behavior. That is an intent/documentation contradiction rather than a mere omission.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The related documentation search is hard-coded to use `site="cn"` and `lang="zh"`, and the rendered output also labels the results as 'China site, zh'. This enforces a locale/language choice in the skill behavior with no user selection or opt-in, which matches the policy's language/locale violation criteria.

Session Persistence

Medium
Category
Rogue Agent
Content
def _save_category_cache(cache: dict) -> None:
    """Write the cache file back (create the directory if missing).

    Bare-int seed entries are not written to the file (avoid cache-file shape drift; seeds only take effect in memory).
    Write to a temp file (same directory, pid suffix) then os.replace atomically; on write failure only WARN,
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Site-independent OpenAPI metadata endpoint (both sites reference the same contracts).
META_BASE = "https://api.aliyun.com/meta/v1"


# Backwards-compatible aliases for the pre-i18n defaults (cn + zh). They must resolve to the
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Session Persistence

Medium
Category
Rogue Agent
Content
DOC_MAX_BYTES = 4 * 1024 * 1024


# categoryId mapping cache: must live in the user directory; never write into the skill directory (platform static checks only allow standard files)
CATEGORY_CACHE_PATH = os.path.expanduser("~/.cache/aliyun-help-search/category_map.json")
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
# N3: a caller may widen or narrow every request deadline from the command line (0 = keep the
# per-endpoint default). The override is applied only through effective_timeout(), so no call
# site carries its own timeout arithmetic.
_cli_timeout = 0


def set_cli_timeout(seconds) -> None:
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
# N3: a caller may widen or narrow every request deadline from the command line (0 = keep the
# per-endpoint default). The override is applied only through effective_timeout(), so no call
# site carries its own timeout arithmetic.
_cli_timeout = 0


def set_cli_timeout(seconds) -> None:
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
# N3: a caller may widen or narrow every request deadline from the command line (0 = keep the
# per-endpoint default). The override is applied only through effective_timeout(), so no call
# site carries its own timeout arithmetic.
_cli_timeout = 0


def set_cli_timeout(seconds) -> None:
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The file embeds bilingual Chinese-English aliasing and later rewrites Chinese queries into English documentation vocabulary, which imposes a specific language/locale behavior in the skill itself. There is no visible user opt-in, configuration, or alternative locale handling in this file, so the skill appears to enforce a language policy rather than offering a choice.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The translate_query_for_english function rewrites Chinese input terms into English terms for search, and its docstring indicates the caller should refuse the Chinese full-text path and use the rewritten English form instead. This is a natural-language locale transformation with no user opt-in or visible choice mechanism in the file.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
An out-of-range pageNum is not an error on search.json: it answers HTTP 200 with a full
    page whose entries lost categoryId, categoryName and content (measured: pageNum=50 with 40
    valid pages returned 10 items carrying only 7 fields), so a length-based pagination test
    would loop forever and collect shells. require_content=False is used for doSearch, whose
    entries always carry both fields (measured 197/197) and whose historical behaviour must not
    change; there only an entry without a URL is structurally useless.
    """
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
An out-of-range pageNum is not an error on search.json: it answers HTTP 200 with a full
    page whose entries lost categoryId, categoryName and content (measured: pageNum=50 with 40
    valid pages returned 10 items carrying only 7 fields), so a length-based pagination test
    would loop forever and collect shells. require_content=False is used for doSearch, whose
    entries always carry both fields (measured 197/197) and whose historical behaviour must not
    change; there only an entry without a URL is structurally useless.
    """
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring states the endpoint 'only ever serves the cn+zh corpus,' and the implementation defaults to site='cn' and lang='zh'. This natural-language behavior indicates a fixed language/locale constraint without any user opt-in or documented choice, which matches the language/locale policy violation category.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The docstring says the unscoped request preserves 'the historical behaviour a default cn+zh invocation relies on,' which natural-language-wise encodes a locale-specific default rather than offering a choice. Because the file presents this as default behavior rather than a documented user-selected regional mode, it falls under the locale policy concern.

Static analysis

No suspicious patterns detected.