Back to skill

Security audit

wooshpay-api

Security checks for vulnerabilities and agentic risk

Overview

This WooshPay payment skill is mostly coherent, but it has unsafe credential handling that could expose a merchant API key or payment secrets.

Review before installing. Use only with a restricted WooshPay key if possible, do not paste API keys into chat, avoid running get_payment.py with any full URL, and expect payment client secrets to appear in terminal output unless the skill is fixed.

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
scripts/get_payment.py:44
Finding

WooshPay API Credential Disclosure Through an Attacker-Controlled Lookup URL

Content
View full analysis

Vulnerability Details

File Location: scripts/get_payment.py, lines 44–45 and 68–73
Vulnerability Type: Arbitrary authenticated request, credential disclosure, and server-side request forgery
Risk Level: High

Vulnerable Code

python
# 补全完整URL
if not order_id.startswith("http"):
    if not order_id.startswith("pi_"):
        print("❌ 订单ID格式错误,应以 pi_ 开头")
        sys.exit(1)

return order_id
python
# 构建URL
if order_id.startswith("http"):
    url = order_id
else:
    url = f"{BASE_URL}/{order_id}"

print(f"\n⏳ 正在查询订单 {order_id}...")

try:
    response = requests.get(url, headers=headers, timeout=30)

The headers object attached to this request contains the merchant credential:

python
headers = {
    "Authorization": f"Basic {api_key}"
}

Technical Analysis

The order lookup accepts any input beginning with http as a complete request URL. The script then sends a request to that URL while attaching the WOOSHPAY_API_KEY in an HTTP Basic Authorization header.

There is no restriction requiring the destination to use HTTPS, no allowlist requiring the hostname to be api.wooshpay.com, and no strict validation that the input is a payment intent ID. Consequently, a user can be induced to enter an attacker-controlled URL instead of an order ID.

Because the Authorization header is attached before the destination is validated, the merchant API key is disclosed directly to the selected server. An http:// destination would additionally transmit it without transport encryption. The same behavior can access internal network addresses, creating an SSRF primitive.

This behavior exceeds the minimum privileges required for payment status lookup. The declared functionality only requires requests to the fixed WooshPay endpoint.

Attack Path

  1. An attacker supplies a purported payment identifier such as https://attacker.example/collect.
  2. A merchant ...[truncated 1305 chars]
Remediation
View remediation

Remediation Suggestions

  • Accept only payment intent identifiers, not complete URLs.

  • Validate input with a strict, length-bounded allowlist expression such as ^pi_[A-Za-z0-9]+$.

  • Always construct the request URL from the trusted constant:

    python
    import re
    
    if not re.fullmatch(r"pi_[A-Za-z0-9]+", order_id):
        raise ValueError("Invalid payment intent ID")
    
    url = f"{BASE_URL}/{order_id}"
    response = requests.get(url, headers=headers, timeout=30)
    
  • If configurable endpoints are required for testing, place them behind explicit configuration and verify that the parsed scheme is https and the hostname exactly matches an approved allowlist.

  • Never attach the API credential before validating the final destination.

  • Use a restricted API key with only read permission for status lookup if WooshPay supports scoped credentials.

  • Rotate the existing API key if the vulnerable lookup feature has been used with any untrusted URL.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_payment.py:156
Finding

Payment Client Secret Exposed in Terminal Output

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/create_payment.py, line 156
  • scripts/create_checkout.py, lines 214–216
  • scripts/get_payment.py, lines 90–91

Vulnerability Type: Sensitive payment credential exposure through standard output
Risk Level: Medium

Vulnerable Code

scripts/create_payment.py:

python
print(f"📌 Client Secret: {result.get('client_secret')}")

scripts/create_checkout.py:

python
client_secret = result.get('client_secret')
if client_secret:
    print(f"\n📌 Client Secret: {client_secret}")

scripts/get_payment.py:

python
if result.get('client_secret'):
    print(f"📌 Client Secret: {result.get('client_secret')}")

Technical Analysis

Client secrets returned by WooshPay are printed directly to standard output. Terminal output may be retained in shell transcripts, continuous-integration logs, agent conversation history, support records, screen recordings, or centralized logging systems.

Displaying the secret is not required for the declared status-query functionality and is not necessary when the operator only needs the hosted checkout or payment URL. The status lookup is particularly overprivileged because it discloses the secret during an otherwise read-only inspection operation.

The precise authority of a WooshPay client secret depends on the service's implementation, but such secrets should be treated as sensitive bearer-style payment-session credentials and disclosed only to the client component that explicitly requires them.

Attack Path

  1. A legitimate creation or lookup request returns a client_secret.
  2. The script writes the value to standard output without redaction.
  3. The terminal session or agent execution output is captured in logs or conversation history.
  4. An unauthorized person with access to those records retrieves the secret.
  5. The person attempts to use it against the corresponding payment o ...[truncated 564 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove all default printing of client_secret values.
  • For normal operations, display only non-sensitive identifiers, status information, and the hosted payment URL.
  • In get_payment.py, omit the client secret entirely because it is unnecessary for status inspection.
  • If a legitimate integration workflow requires access to the secret, return it only through a deliberate machine-readable interface rather than ordinary logs.
  • Require explicit opt-in, such as --show-client-secret, and display a warning before revealing it.
  • Ensure logging, exception handling, telemetry, and agent output redact fields named client_secret, Authorization, and similar credentials.
  • Review retained execution logs and remove exposed secrets where practical. Invalidate affected sessions if exposure is suspected.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_payment.py:31
Finding

User Guidance Encourages API Key Disclosure in Agent Conversations

Content
View full analysis

Vulnerability Details

File Location: scripts/create_payment.py, line 31
Vulnerability Type: Unsafe secret-handling guidance
Risk Level: Medium

Vulnerable Code

python
print("\n或直接在对话中告诉我你的 API Key,我来帮你设置")

The message tells the user that they may provide the API key directly in the conversation so that the agent can configure it.

Technical Analysis

A merchant API key is a sensitive credential and should not be pasted into an agent conversation. Conversation content may be retained in chat history, application logs, debugging telemetry, moderation systems, or support exports. It may also be visible to other users with access to the conversation.

The declared functionality only requires the credential to be configured in the local WOOSHPAY_API_KEY environment variable. Asking the user to disclose it through a conversation unnecessarily expands the credential's exposure surface and violates least-disclosure practices.

Attack Path

  1. The user launches create_payment.py without setting WOOSHPAY_API_KEY.
  2. The script displays guidance stating that the key can be provided directly in the conversation.
  3. The user pastes the merchant API key into an agent or support chat.
  4. The conversation is stored or included in logs and telemetry.
  5. A person or system with access to those records obtains the key.
  6. The exposed key is reused against WooshPay according to its assigned privileges.

Impact Assessment

Exposure may grant unauthorized merchant-level API access. Based on the operations implemented by this project, a sufficiently privileged key may permit payment creation, transaction lookup, checkout creation, and refund requests.

The issue does not automatically transmit the key by itself; exploitation requires the user to follow the unsafe guidance. However, the instruction explicitly promotes that behavior and creates a credible credential-compromise path.

Remediation
View remediation

Remediation Suggestions

  • Remove the instruction inviting users to provide API keys through a conversation.

  • Replace it with guidance that explicitly warns users never to paste credentials into chat, command history, source code, or logs.

  • Recommend local configuration through a protected environment variable or operating-system secret manager.

  • Prefer a restricted-permission configuration file or secret store with owner-only access where environment variables are unsuitable.

  • Provide safe guidance such as:

    python
    print("Set WOOSHPAY_API_KEY locally using a secure secret manager.")
    print("Do not paste API keys into chat, source code, or logs.")
    
  • If a key has already been disclosed in a conversation, revoke and rotate it, then review relevant transaction activity.

  • Use separate, least-privilege API credentials for read-only lookup and financially sensitive operations such as refunds where supported.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (27)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/create_checkout.py (reported line 188)May include surrounding context.

python
print("\n⏳ 正在创建收银台...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/create_payment.py (reported line 150)May include surrounding context.

python
print("\n⏳ 正在创建订单...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

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

Critical
Category
Data Flow
Confidence
99% confidence
Finding

The WooshPay API key is read from the environment and placed directly into the Authorization header for every request, including attacker-controlled URLs when full URLs are accepted. This can leak the credential to arbitrary external services, enabling unauthorized API access, payment data exposure, and potentially fraudulent operations depending on the key's privileges.

Content

Scanner excerpt · scripts/get_payment.py (reported line 75)May include surrounding context.

python
print(f"\n⏳ 正在查询订单 {order_id}...")
    
    try:
        response = requests.get(url, headers=headers, timeout=30)
        
        if response.status_code == 200:
            result = response.json()

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/refund.py (reported line 148)May include surrounding context.

python
print("\n⏳ 正在发起退款...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code only implements order/payment intent lookup functionality. It reads WOOSHPAY_API_KEY from the environment, prompts for an order ID, performs a GET request to the WooshPay payment_intents endpoint, and displays status/details. This aligns with the declared 'Query Order Status' scenario, but the broader declared description claims additional capabilities—creating payments, creating hosted checkout sessions, processing refunds, and managing checkout sessions—that are not present in this code chunk. There is no evidence of unrelated or dangerous undeclared behavior, but the declared purpose overstates the implemented functionality for this chunk, so this is a description/behavior mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script explicitly encourages the user to reveal their API key in conversation, which creates a direct path for credential disclosure outside secure secret-handling channels. In an agent skill context, this is especially dangerous because users may assume the assistant can safely store or configure the secret, leading to compromise of payment API credentials.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Telling users to disclose the API key so it can be handled on their behalf is a credential-handling anti-pattern that can cause immediate secret leakage. Because this skill processes payment operations, exposure of the WooshPay API key could enable unauthorized payment creation, refund abuse, transaction inspection, or broader account compromise depending on key scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Accepting arbitrary full URLs in an order lookup feature broadens a simple status query into an authenticated arbitrary outbound request primitive. In this payment-gateway context, that is especially dangerous because it can exfiltrate WooshPay credentials and turn a benign support/admin workflow into a credential-leak vector.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is described as an order-status query utility, but this code expands that narrow function into arbitrary outbound requests while carrying WooshPay credentials. That mismatch increases risk because operators may trust the tool as a limited gateway helper while it actually enables broader network interaction and secret disclosure.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents use of environment secrets and outbound network access to a payment API, but it does not declare any explicit tool scope or permissions. In an agent environment, missing scope declarations can cause overbroad execution privileges, making it easier for the skill or adjacent code to access secrets or perform network actions without clear policy enforcement.

Content

No source excerpt is available for this finding.

Tainted flow: 'data' from input (line 147, user input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/create_checkout.py (reported line 188)May include surrounding context.

python
print("\n⏳ 正在创建收银台...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script prints the checkout session client_secret directly to stdout, exposing a sensitive secret that may be captured in terminal history, logs, screen recordings, or shared transcripts. In a payment workflow, unnecessary disclosure of session secrets increases the risk of unauthorized session use or leakage into less-trusted environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

All prompts, instructions, and user-facing messages in the script are presented only in Chinese. This can violate language/locale policy when the skill does not offer user opt-in for Chinese or explain that the tool is intentionally region- or language-specific.

Content

No source excerpt is available for this finding.

Tainted flow: 'url' from input (line 70, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
98% confidence
Finding

The script allows the user to supply a full URL instead of only a WooshPay payment intent ID, then sends an authenticated HTTP request to that URL. Because the Authorization header contains the WooshPay API key, this creates a server-side request forgery / credential exfiltration path where an attacker can cause the script to send secrets to an arbitrary host.

Content

Scanner excerpt · scripts/get_payment.py (reported line 75)May include surrounding context.

python
print(f"\n⏳ 正在查询订单 {order_id}...")
    
    try:
        response = requests.get(url, headers=headers, timeout=30)
        
        if response.status_code == 200:
            result = response.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script prints sensitive payment fields such as client_secret and payment method identifiers directly to the terminal. These values may be captured in shell history, terminal logs, screen recordings, support transcripts, or shared consoles, creating unnecessary exposure of confidential payment data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script's user-facing docstrings, prompts, warnings, and status messages are written entirely in Chinese, which imposes a specific language on all users. Under the policy rule, this is a natural-language locale constraint and there is no opt-in, fallback, or documentation indicating the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_checkout.py (reported line 11)May include surrounding context.

python
import json
import requests

BASE_URL = "https://api.wooshpay.com/v1/refunds"

# 退款原因
REFUND_REASONS = {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_payment.py (reported line 11)May include surrounding context.

python
import json
import requests

BASE_URL = "https://api.wooshpay.com/v1/refunds"

# 退款原因
REFUND_REASONS = {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/get_payment.py (reported line 11)May include surrounding context.

python
import json
import requests

BASE_URL = "https://api.wooshpay.com/v1/refunds"

# 退款原因
REFUND_REASONS = {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/refund.py (reported line 11)May include surrounding context.

python
import json
import requests

BASE_URL = "https://api.wooshpay.com/v1/refunds"

# 退款原因
REFUND_REASONS = {

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_checkout.py (reported line 188)May include surrounding context.

python
print("\n⏳ 正在发起退款...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_payment.py (reported line 150)May include surrounding context.

python
print("\n⏳ 正在发起退款...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/refund.py (reported line 148)May include surrounding context.

python
print("\n⏳ 正在发起退款...")
    
    try:
        response = requests.post(BASE_URL, headers=headers, json=data, timeout=30)
        result = response.json()
        
        if response.status_code in [200, 201]:

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation omits an order-cancellation capability while later exposing a cancel-payment operation. Undocumented transaction-affecting actions reduce operator awareness and review quality, which can lead to misuse or unexpected cancellation of payment orders in production.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

All user-facing prompts, status messages, and the module description are written in Chinese, which imposes a specific language on users. The file does not offer any language selection or indicate that the skill is intentionally limited to Chinese-speaking users or a region-specific deployment.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.