Back to skill

Security audit

paymax

Security checks for vulnerabilities and agentic risk

Overview

This payment skill has a coherent payment purpose, but it needs review because it sends payment details to an external service and documents unsafe command templates for user-controlled fields.

Review this skill before installing, especially if it may be invoked by other skills. Only use it if you trust the payment API at pay.4199191.xyz, are comfortable sending payment details there, and can ensure calls are made with argument-array execution or properly escaped/validated inputs rather than interpolated shell strings.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:72
Finding
Shell Command Injection Through Unquoted User-Controlled Arguments## Vulnerability Details **File Location**: `SKILL.md:72-89` **Vulnerability Type**: OS command injection **Risk Level**: High The skill documentation instructs the agent to interpolate user-controlled values directly into shell command templates: ```bash node ~/.claude/skills/payment/scripts/payment_api.js \ --amount {amount} \ [--order_type {order_type}] \ [--payee {payee}] \ [--description {description}] ``` ```bash python3 ~/.claude/skills/payment/scripts/payment_api.py \ --amount {amount} \ [--order_type {order_type}] \ [--payee {payee}] \ [--description {description}] ``` ### Technical Analysis The `amount`, `order_type`, `payee`, and `description` values originate from users or calling skills. The documented commands do not quote, escape, or validate these values before inserting them into a command interpreted by a shell. If an agent follows this construction literally through a shell, shell metacharacters contained in an argument can terminate or alter the intended command and introduce additional commands. The vulnerability exists before either payment script processes its arguments, so the scripts' argument parsers cannot prevent exploitation. This is particularly dangerous for free-form fields such as `payee` and `description`, which can plausibly contain spaces and punctuation and have no documented character restrictions. ### Attack Path 1. An attacker triggers the payment skill directly or through another skill. 2. The attacker supplies a crafted `description`, `payee`, or amount containing a shell command separator or command substitution. 3. The agent replaces the corresponding placeholder in the documented command template. 4. The resulting command is passed to a shell. 5. The shell interprets the metacharacters and executes the injected command in addition to, or instead of, the payment script. 6. The injected process inherits the operating-system permissions an ...[truncated 704 chars]
Remediation
## Remediation Suggestions - Do not construct commands by interpolating values into shell strings. - Invoke Node.js or Python through an execution API that accepts an argument array and explicitly disables shell interpretation. - Pass each value as an independent argument, for example conceptually as `["script.js", "--amount", amount, "--description", description]`. - Require the amount to match a strict decimal format and enforce positive-value, precision, and upper-bound rules before execution. - Apply explicit length and character restrictions to `order_type`, `payee`, and `description`. - If shell execution is unavoidable, use a platform-appropriate escaping function for every dynamic value; argument-array execution should still be preferred. - Add tests using spaces, quotes, command separators, substitutions, newlines, and leading dashes to verify that supplied values cannot change command structure.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/payment_api.js:83
Finding
Unvalidated Remote Payment Destination and Output Injection## Vulnerability Details **File Location**: `scripts/payment_api.js:83-85`; equivalent behavior in `scripts/payment_api.py:86-92` **Vulnerability Type**: Improper validation of remotely supplied payment output **Risk Level**: High The Node.js implementation accepts remote response fields without format or destination validation: ```javascript if (result.resultCode === 1) { const data = result.data || {}; success(data.tradeCode || '', data.tradeLink || ''); ``` The Python implementation has the same behavior: ```python if result_code == 1: data = result.get("data", {}) trade_code = data.get("tradeCode", "") trade_link = data.get("tradeLink", "") print("SUCCESS") print(f"tradeCode={trade_code}") print(f"tradeLink={trade_link}") ``` ### Technical Analysis Both implementations treat `resultCode === 1` as sufficient proof that all returned data is safe and valid. They do not verify: - That `tradeCode` is present and conforms to the expected type, length, and character set. - That `tradeLink` is an HTTPS URL. - That the URL hostname and path belong to an approved payment destination. - That either value excludes carriage returns, newlines, terminal control characters, or other output delimiters. - That the response is cryptographically associated with the requested amount and intended payee. These values are printed into a line-oriented protocol and are subsequently intended to be displayed prominently to the user. A compromised, malfunctioning, or malicious payment service can therefore return an attacker-controlled destination while preserving a successful result code. Newline-bearing values can also inject additional fields or misleading instructions into the output consumed by the agent. TLS protects the connection in transit under normal certificate validation, but it does not protect against compromise or malicious behavior at the configured API service. ### Attack Pa ...[truncated 1236 chars]
Remediation
## Remediation Suggestions - Define and enforce a strict response schema before reporting success. - Require `tradeCode` to be a non-empty string matching the documented transaction-code format and length. - Parse `tradeLink` with a URL parser and require the `https:` scheme. - Maintain an explicit allowlist of approved payment hostnames, ports, and path prefixes. - Reject credentials in URLs, unexpected ports, fragments, encoded hostname tricks, and redirects to non-allowlisted destinations. - Reject carriage returns, newlines, null bytes, terminal escape sequences, and other control characters in every printed field. - Treat missing or malformed `tradeCode` or `tradeLink` as a failure rather than substituting an empty string. - Bind the result to the original amount, order identifier, and payee. Where supported, verify a server signature over those fields and the payment destination. - Use structured JSON output between the script and agent instead of an unescaped line-oriented key/value protocol. - Display the validated payment hostname and requested amount to the user for confirmation before payment.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/payment_api.js:48
Finding
Missing Validation of Payment Amount## Vulnerability Details **File Location**: `scripts/payment_api.js:48-52`; equivalent behavior in `scripts/payment_api.py:32-40` **Vulnerability Type**: Improper input validation **Risk Level**: Medium The Node.js implementation performs permissive floating-point conversion without checking the result: ```javascript const args = parseArgs(); const payload = {}; if (args.amount !== undefined) payload.amount = parseFloat(args.amount); if (args.order_type !== undefined) payload.order_type = args.order_type; if (args.payee !== undefined) payload.payee = args.payee; if (args.description !== undefined) payload.description = args.description; ``` The Python implementation accepts a floating-point amount but does not enforce payment business rules: ```python parser.add_argument("--amount", type=float, default=None) ``` ```python payload = {} if args.amount is not None: payload["amount"] = args.amount ``` ### Technical Analysis Neither script requires an amount or verifies that it is finite, positive, within an approved range, or limited to the supported currency precision. JavaScript's `parseFloat` is especially permissive: it can accept an initial numeric prefix while ignoring trailing invalid characters. Non-numeric input can also produce `NaN`, which `JSON.stringify` serializes as `null`. Python's floating-point parser can accept non-finite values such as infinity or not-a-number representations, and its JSON serializer can emit non-standard numeric tokens unless configured for strict JSON. Floating-point types are also unsuitable for exact currency handling because many decimal values cannot be represented exactly. Although the remote service should independently validate payment requests, the local clients currently forward invalid or ambiguous values instead of failing closed. ### Attack Path 1. A caller invokes the script directly, or a calling skill supplies an abnormal amount. 2. The amount ...[truncated 924 chars]
Remediation
## Remediation Suggestions - Make `amount` mandatory at the script level instead of relying only on skill instructions. - Accept only a strict decimal representation, such as digits followed by no more than the supported number of fractional digits. - Reject zero, negative, non-finite, partially parsed, and over-precise values. - Enforce documented minimum and maximum payment limits. - Represent currency using an integer minor unit, such as cents, or a decimal arithmetic type rather than binary floating point. - In JavaScript, validate the complete input string before conversion and require `Number.isFinite` on the result. - In Python, use `decimal.Decimal`, reject non-finite values, and serialize only a normalized value accepted by the API contract. - Require the remote API to repeat and cryptographically bind the normalized amount in its response, then verify it before displaying a payment link. - Add boundary tests for missing values, zero, negative amounts, excessive values, excessive decimal precision, `NaN`, infinity, and strings with numeric prefixes followed by invalid characters.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The manifest description and all prescribed trigger phrases and response scripts are written exclusively in Chinese, indicating the skill is designed to operate only in that language. The file does not offer an opt-in language choice or explain that the skill is intentionally limited to a Chinese-speaking or region-specific context.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill initiates creation of a payment request and sends payment-related details to an external API, but the user-facing flow does not clearly warn that external transmission will occur before the request is made. In a payment context, lack of explicit notice and confirmation can cause users to disclose financial or transaction metadata without informed consent, increasing privacy and social-engineering risk.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file's documentation and all user-facing status/error messages are written only in Chinese, which imposes a language choice on users without opt-in or documented locale justification. This matches the policy category for language or locale constraints expressed in natural-language content.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script collects user-supplied payment details and transmits them to a third-party payment API domain without any explicit consent prompt, trust verification, or warning to the operator at runtime. In an agent-skill context, this is dangerous because sensitive transaction metadata can be exfiltrated to an external service the user may not recognize or intend to use.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The script returns all failure messages in Chinese, such as parse, timeout, network, and service errors, without any locale selection mechanism. This is a natural-language policy issue because it constrains interaction to one language regardless of user preference.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code file contains natural-language documentation and output strings exclusively in Chinese, including usage instructions and error messages. That can violate language/locale policy when the skill forces a specific language without user opt-in or an explicit documented locale restriction.

Static analysis

No suspicious patterns detected.