Back to skill

Security audit

公众号文章诊断助手

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform the advertised article-review task, but users should review it because it sends submitted content and API credentials to a remote service and its runner can be redirected to an arbitrary API endpoint.

Install only if you are comfortable sending article drafts, URLs, uploaded-document references, audience details, goals, and brand constraints to the AI Skills service. Keep AISKILLS_BASE_URL at the default trusted endpoint unless you fully control the replacement service, use HTTPS, and avoid submitting confidential material without approval.

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

Warning
Location
scripts/run.py:23
Finding
Untrusted API Base URL Can Exfiltrate Credentials and Submitted Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run.py:13`, `scripts/run.py:23-38`, `scripts/run.py:82-88`, and `scripts/run.py:129` **Vulnerability Type**: User-controlled authenticated request destination **Risk Level**: Medium ### Vulnerable Code ```python DEFAULT_BASE_URL = "https://ai-skills.ai" ``` ```python def build_base_url(): return os.getenv("AISKILLS_BASE_URL", DEFAULT_BASE_URL).rstrip("/") def build_headers(): api_key = os.getenv("AISKILLS_API_KEY", "").strip() tenant_id = os.getenv("AISKILLS_TENANT_ID", "default").strip() or "default" if not api_key: fail("AISKILLS_API_KEY is required") return { "Content-Type": "application/json", # Cloudflare blocks urllib's default Python user agent for this endpoint. "User-Agent": "ai-skills-runner/1.0 (+https://ai-skills.ai)", "Accept": "application/json", "X-API-Key": api_key, "X-Tenant-Id": tenant_id, } ``` ```python def request_json(method, path, payload): body = json.dumps(payload).encode("utf-8") req = urllib.request.Request( f"{build_base_url()}{path}", data=body, method=method, headers=build_headers(), ) ``` ```python response = request_json("POST", EXECUTE_PATH, {"skillId": SKILL_ID, "params": params}) ``` ### Technical Analysis The request destination is taken directly from the `AISKILLS_BASE_URL` environment variable without validating its scheme or hostname. The same request always includes the `AISKILLS_API_KEY` and `AISKILLS_TENANT_ID` headers. Consequently, a process environment that sets `AISKILLS_BASE_URL` to an attacker-controlled server causes the runner to transmit authentication data and the complete skill input to that server. The input can include unpublished article text, uploaded-material references, audience information, conversion goals, and confidential brand requirements. The implementation also does not explicitly require HTTPS. A con ...[truncated 2195 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Enforce HTTPS** - Parse the configured URL with `urllib.parse.urlparse`. - Reject all schemes other than `https`. - Reject URLs containing embedded credentials, fragments, or malformed hostnames. 2. **Allowlist trusted destinations** - Default to `https://ai-skills.ai`. - Only send `X-API-Key` and `X-Tenant-Id` when the normalized hostname exactly matches an approved hostname. - Avoid suffix-based checks that could accept domains such as `ai-skills.ai.attacker.example`. 3. **Separate custom endpoints from production credentials** - If custom endpoints are needed for development, require an explicit development-mode option. - Use separate test credentials for custom endpoints. - Never automatically reuse production credentials for arbitrary destinations. 4. **Fail closed** - Terminate execution when URL validation fails. - Validate the destination before constructing authentication headers or serializing sensitive request data. 5. **Harden deployment configuration** - Restrict who can modify environment variables in CI/CD, containers, and service definitions. - Store API keys in a managed secret store and scope them to the minimum required permissions. - Rotate the API key if execution with an untrusted base URL may already have occurred. 6. **Add regression tests** - Verify that HTTP endpoints are rejected. - Verify that unapproved hostnames and deceptive subdomains are rejected. - Verify that authentication headers are never attached to custom or untrusted endpoints. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill requires an API key and explicitly calls an external AI Skills API, but it does not declare any tool scope or allowed-tools boundaries. This creates an authorization and transparency gap: a host system or user cannot easily constrain or audit the skill's access to environment variables and network use, increasing the chance of overbroad execution or unintended data handling.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The description uses broad trigger language like questions about whether copy can 'move people' without clear activation boundaries. In systems that auto-select skills from natural-language descriptions, this can cause the skill to trigger on loosely related prompts and route user content to an external API unexpectedly.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The usage guidance lists broad scenarios and input types but does not define exclusion conditions, making accidental activation more likely. Because the skill accepts article text, files, and URLs and sends them to a remote service, ambiguous routing can expose sensitive draft content or internal documents to third parties without clear user intent.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The documentation explains that URLs, files, and text are provided to the runner and sent to the AI Skills API, but it does not clearly warn users that potentially sensitive article drafts and linked content will leave the local environment and be transmitted to an external service. This is a meaningful data-handling weakness because users may submit unpublished copy, confidential marketing plans, or proprietary documents under the assumption the analysis is local.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The display name, short description, and default prompt are entirely in Chinese, which indicates the skill is oriented to a specific language without any visible opt-in or alternative locale handling. Under the policy rule, forcing a language or locale without user choice is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
User-facing labels, placeholders, descriptions, enum values, and validation messages are entirely in Chinese throughout the schema, which effectively enforces a specific language for users. The file does not provide any opt-in, alternative locale, or explanation that this skill is intentionally limited to a Chinese-only context.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script sends the provided params payload to a remote HTTPS endpoint and includes API and tenant identification headers, but there is no confirmation prompt, print/log disclosure before transmission, or docstring/comment warning users that their input and associated account context will be sent over the network. For a code file, this is a safety-relevant external data transmission lacking visible user disclosure in the file itself.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The billing error message is hard-coded in Chinese, which imposes a specific language on users regardless of their locale or preferences. The file does not provide any opt-in, fallback, or documented justification for this language restriction.

Static analysis

No suspicious patterns detected.