Back to skill

Security audit

GitHub Issue Reply Assistant

Security checks for vulnerabilities and agentic risk

Overview

The skill can draft GitHub issue replies, but it also includes under-disclosed payment and upgrade-link behavior that is not clearly scoped to the stated assistant purpose.

Review this before installing if you do not want monetization behavior in a GitHub reply helper. It does not appear to charge users or make network calls itself, but it always returns a payment link and can use environment variables to point that link at a configurable endpoint. Install only if that payment flow is intended, and prefer a version that clearly discloses billing, encodes user identifiers, restricts payment hosts, and asks before showing or using payment links.

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/github_issue_reply_assistant.py:13
Finding

Unencoded User Input Enables Payment URL Query Parameter Injection

Content
View full analysis
str: template = os.getenv("SKILLPAY_PAYMENT_URL_TEMPLATE", "").strip() if template: return template.format(user_id=user_id) base = os.getenv("SKILLPAY_TOPUP_BASE_URL", "https://skillpay.me/pay").strip() sep = "&" if "?" in base else "?" return f"{base}{sep}user_id={user_id}" ``` ### Technical Analysis The `_payment_url()` function inserts the attacker-controllable `user_id` directly into a URL without percent-encoding it. `validate_payload()` only verifies that `user_id` is non-empty and does not restrict metacharacters such as `&`, `=`, `#`, or `?`. For the fallback construction path, a value such as: ```text victim&amount=100&redirect=https://example.invalid ``` produces a URL resembling: ```text https://skillpay.me/pay?user_id=victim&amount=100&redirect=https://example.invalid ``` The injected delimiters create additional query parameters rather than remaining part of the `user_id` value. The configured template path is similarly unsafe because unrestricted user input is passed directly to `str.format()` without encoding. Exploitation depends on a downstream user, browser, payment service, or integration opening or interpreting the generated `upgrade.payment_url`. The script itself does not make an outbound request or perform a charge. ### Attack Path 1. An attacker supplies an otherwise valid payload with a crafted, non-empty `user_id` containing URL query delimiters. 2. `validate_payload()` accepts the value because it only checks whether `user_id` is empty. 3. `run()` passes the validated identifier to `_payment_url()`. 4. `_payment_url()` concatenates or formats the identifier into the payment URL without percent-encoding. 5. The generated URL is returned in `upgrade.payment_url`. 6. If a ...[truncated 826 chars]
Remediation
View remediation
str: base = os.getenv( "SKILLPAY_TOPUP_BASE_URL", "https://skillpay.me/pay", ).strip() parts = urlsplit(base) query = parse_qsl(parts.query, keep_blank_values=True) query.append(("user_id", user_id)) return urlunsplit( (parts.scheme, parts.netloc, parts.path, urlencode(query), parts.fragment) ) ``` 2. Validate `user_id` against the application's documented identifier format, including a reasonable maximum length. For example, if identifiers are limited to letters, digits, underscores, and hyphens: ```python if not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", user_id): raise ValidationError("`user_id` contains unsupported characters") ``` 3. Avoid free-form URL templates where possible. If template support is required, percent-encode the identifier before substitution and document that `{user_id}` represents an encoded query value. 4. Validate configured payment URLs: - Require HTTPS. - Restrict hosts to an explicit allowlist. - Reject embedded credentials and malformed URLs. - Prevent configuration from redirecting users to untrusted origins. 5. Add tests covering identifiers containing `&`, `=`, `?`, `#`, percent sequences, Unicode characters, and unusually long values. Verify that the resulting URL contains exactly one correctly encoded `user_id` parameter. ]]>
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 (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill declares executable behavior and the analyzer detected capabilities related to environment access and file reading, but the manifest does not define any explicit tool scope or permissions boundary. That omission is dangerous because it leaves reviewers and runtime policy with no clear least-privilege contract, increasing the chance of unintended data access or broader execution than the skill’s simple issue-drafting purpose requires.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description reserves 'premium upgrade hooks for multilingual replies,' which implies language-changing behavior but does not state that the user chooses the language or opts into locale changes. This can violate language/locale policy because the skill suggests enforcing or switching language behavior without explicit user selection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The contract explicitly defines sending a user identifier, purchase details, and arbitrary metadata to a billing endpoint, but it contains no requirement for user notice, consent, or minimization of shared data. In a skill that may trigger billing-related actions, this can lead to undisclosed data transfer and surprise charges, creating privacy, trust, and compliance risk even if no secret is directly exposed in the document.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The payment-link generator is out of scope for a GitHub issue reply assistant and introduces monetization behavior unrelated to the stated task. Because the URL is built from environment-controlled values and user identifiers, the skill can direct users to arbitrary payment endpoints, increasing phishing and unauthorized billing risk if deployed in a broader agent ecosystem.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This Python skill contains user-facing reply text entirely in Chinese, and the premium feature list also advertises multilingual replies as an upgrade. There is no indication that the user opted into Chinese output or that the skill is intentionally limited to a Chinese-language context, which creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description says premium functionality is only reserved as hooks, but the code actively returns an upgrade object with pricing, a payment URL, and premium feature marketing in normal responses. This is a deceptive capability mismatch that can route users into an unexpected payment flow and undermine trust, especially because payment behavior is not necessary for drafting GitHub issue replies.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The manifest description says the skill 'drafts a structured GitHub issue response and triage checklist' but does not define specific trigger phrases, scope limits, or exclusion conditions. For a markdown/manifest file, this leaves activation criteria ambiguous and could cause the skill to match broadly to general requests about replies or issue handling.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.