Back to skill

Security audit

Proxy Gateway

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed proxy/payment skill, but it needs Review because the implementation exposes high-impact network forwarding and financial/account endpoints with insufficient scoping and authorization.

Install or use this only if you are comfortable with a proxy operator seeing all URLs, headers, bodies, and responses, and do not send secrets or sensitive data through it. For self-hosting, deploy it in a tightly isolated environment with egress filtering that blocks loopback, private networks, metadata services, unsafe redirects, and unnecessary methods/headers. Treat the payment and account endpoints as needing review before production use, especially mainnet USDC deposits, balance/history access, free-trial abuse controls, Redis security, and dependency updates.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
app/core/security.py:43
Finding
Unrestricted Server-Side Request Forgery in the URL Fetch Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `app/core/security.py:43-52`, `app/routers/proxy.py:75-84`, `app/managers/proxy_manager.py:221-240` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: Critical ### Vulnerable Code ```python # app/core/security.py:43-52 def validate_url(url: Optional[str]) -> bool: """ Validate URL format. - Must start with http:// or https:// """ if not url: return False return url.startswith(("http://", "https://")) ``` ```python # app/routers/proxy.py:75-84 from app.core.security import validate_url if not validate_url(fetch_request.url): return JSONResponse( status_code=400, content={ "success": False, "error": "Invalid URL", "message": "URL must start with http:// or https://" } ) ``` ```python # app/managers/proxy_manager.py:221-240 proxy_url = f"http://127.0.0.1:{self.clash_mixed_port}" transport = httpx.AsyncHTTPTransport(proxy=proxy_url) async with httpx.AsyncClient( timeout=30.0, follow_redirects=True, transport=transport ) as client: request_headers = headers or {} request_headers.setdefault("User-Agent", "ProxyGateway/0.3.0") response = await client.request( method=method.upper(), url=url, headers=request_headers, content=body ) ``` ### Technical Analysis The URL validation only verifies that the supplied string begins with `http://` or `https://`. It does not parse and validate the destination hostname, resolve DNS addresses, restrict destination ports, or reject loopback, private, link-local, reserved, multicast, and cloud metadata addresses. The forwarding implementation accepts a caller-controlled method, URL, headers, and body. It also enables automatic redirects without validating each redirect destination. Consequently, an external caller can instruct the server to make requests to resources reachable from the serve ...[truncated 1860 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse URLs with a standards-compliant URL parser and permit only explicitly supported schemes. 2. Resolve the destination hostname before connecting and reject all loopback, private, link-local, unspecified, multicast, reserved, and documentation address ranges for both IPv4 and IPv6. 3. Check every resolved address, not only the first DNS result. 4. Disable automatic redirects or validate and resolve every redirect destination before following it. 5. Protect against DNS rebinding by ensuring the validated address is the address used for the connection. 6. Restrict destination ports to a minimal allowlist, normally TCP 80 and 443. 7. Restrict methods to those required by the service. If arbitrary methods are necessary, apply a destination allowlist and stronger authorization. 8. Remove or block sensitive forwarded headers such as `Authorization`, `Cookie`, `Proxy-Authorization`, and cloud-specific headers unless explicitly required. 9. Enforce network-level egress controls so the application cannot reach metadata services, loopback services, or private network ranges. 10. Add tests covering IPv4, IPv6, encoded addresses, mixed notation, DNS rebinding, redirects, user-info URL syntax, and cloud metadata endpoints. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
app/managers/hosted_payment.py:112
Finding
Mainnet Deposit Verification Accepts Counterfeit Tokens and Unbound Transaction Claims<![CDATA[ ## Vulnerability Details **File Location**: `app/routers/payment.py:47-65`, `app/managers/hosted_payment.py:112-143` **Vulnerability Type**: Improper Blockchain Transaction Verification **Risk Level**: Critical ### Vulnerable Code ```python # app/routers/payment.py:47-65 @router.post("/confirm-deposit") async def confirm_deposit(request: DepositConfirmRequest): """ Confirm a deposit. The user submits a transaction hash, and the platform updates the balance after confirmation. """ try: result = await payment_manager.confirm_deposit(request.user_id, request.tx_hash) return result except InvalidUserIdError: raise HTTPException(status_code=400, detail="Invalid user_id format") except InvalidTxHashError: raise HTTPException(status_code=400, detail="Invalid transaction hash format") except DepositAlreadyProcessedError as e: raise HTTPException(status_code=409, detail=str(e)) except TransactionFailedError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: raise HTTPException(status_code=500, detail="Internal server error") ``` ```python # app/managers/hosted_payment.py:112-143 try: from web3 import Web3 w3 = Web3(Web3.HTTPProvider(self.settings.RPC_URL)) # Get transaction receipt receipt = w3.eth.get_transaction_receipt(tx_hash) if not receipt: raise TransactionFailedError(tx_hash, "Transaction not found") if receipt['status'] != 1: raise TransactionFailedError(tx_hash, "Transaction failed") # Parse USDC Transfer event transfer_topic = Web3.keccak(text="Transfer(address,address,uint256)").hex() amount = Decimal("0") for log in receipt['logs']: if log['topics'][0].hex() == transfer_topic: # Check whether transfer was sent to the platform address to_address = '0x' + log['topics'][2].hex()[-40:] if to_address.lower() == self. ...[truncated 2798 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require the event emitter address, `log.address`, to equal the configured and checksummed `USDC_CONTRACT`. 2. Verify the configured chain ID and ensure the RPC endpoint is connected to the expected network. 3. Validate the recipient, sender, token contract, amount, token decimals, receipt status, and minimum confirmation count. 4. Do not assume token decimal precision solely from application configuration without validating the expected contract. 5. Bind every deposit to an authenticated account. Suitable designs include: - Unique deposit addresses per account - A verified sender wallet previously linked through a nonce-based signature challenge - A unique on-chain payment identifier supported by a payment contract 6. Require authentication on `/confirm-deposit` and derive the account identity server-side rather than trusting a submitted `user_id`. 7. Use a nonce and domain-separated signed message when linking wallet ownership, including chain ID, service origin, expiration, and intended account. 8. Store processing records atomically with the balance update to avoid partial-state inconsistencies. 9. Add regression tests using a counterfeit ERC-20 contract and tests in which one user attempts to claim another user's transaction. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
app/routers/payment.py:68
Finding
Unauthenticated Balance and Transaction History Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `app/routers/payment.py:68-88` **Vulnerability Type**: Broken Object-Level Authorization and Sensitive Financial Metadata Exposure **Risk Level**: High ### Vulnerable Code ```python @router.get("/balance") async def get_balance(user_id: str = Query(..., description="User ID")): """ Query balance. """ if not validate_user_id(user_id): raise HTTPException(status_code=400, detail="Invalid user_id format") balance = payment_manager.get_balance(user_id) history = payment_manager.get_transaction_history(user_id, limit=5) return { "user_id": user_id, "balance": float(balance), "currency": "USDC", "network": get_settings().NETWORK, "recent_transactions": history } ``` ### Technical Analysis The endpoint accepts an arbitrary `user_id` in the query string and returns the corresponding account balance and recent transaction history without authenticating the caller or verifying account ownership. Input-format validation only confirms that the identifier contains permitted characters. It is not an authorization control. Elsewhere, the proxy route uses the API key itself as the account identifier: ```python user_id = api_key or f"free:{client_id}" ``` This makes account identifiers especially sensitive. Supplying such identifiers in URLs can also expose them through browser history, reverse-proxy logs, server access logs, monitoring systems, and referrer data. ### Attack Path 1. The attacker guesses, obtains, or observes another user's identifier or API key. 2. The attacker sends `GET /balance?user_id=<target-identifier>`. 3. The endpoint validates only the identifier's format. 4. The service returns the target account's balance and recent transaction records without requiring proof of ownership. 5. The attacker can repeat the request for additional identifiers and enumerate accessible account metadata. ### Impact Assessment An ...[truncated 526 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for the balance endpoint. 2. Supply API credentials only through an authorization header, never through a URL query parameter. 3. Derive the account identity from the authenticated credential on the server; do not accept a caller-selected `user_id`. 4. Separate public account identifiers from API secrets. Store API keys as securely hashed credentials rather than using them directly as storage keys. 5. Return records only for the authenticated account unless an explicitly authorized administrative role is used. 6. Redact sensitive query values from access logs and monitoring systems. 7. Apply rate limiting and alerting for repeated account-enumeration attempts. 8. Add authorization tests proving that one account cannot retrieve another account's balance or history. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
app/routers/proxy.py:57
Finding
Free-Trial Quota Bypass Through Attacker-Controlled Client Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `app/routers/proxy.py:57-72`, `app/routers/proxy.py:87-112` **Vulnerability Type**: Rate-Limit and Payment-Control Bypass **Risk Level**: Medium ### Vulnerable Code ```python # app/routers/proxy.py:57-72 api_key = request.headers.get("X-API-Key") client_id = request.headers.get("X-Client-ID") # Validate authentication information if not api_key and not client_id: return JSONResponse( status_code=401, content={ "success": False, "error": "Authentication Required", "message": "Provide X-Client-ID for the free trial or X-API-Key for paid mode" } ) # Determine user ID user_id = api_key or f"free:{client_id}" ``` ```python # app/routers/proxy.py:87-112 if not api_key: # Validate client_id format if not client_id or not validate_user_id(client_id): return JSONResponse( status_code=400, content={ "success": False, "error": "Invalid Client ID", "message": "Invalid Client ID format" } ) # Check free-trial quota from cachetools import TTLCache if not hasattr(fetch_url, "_free_trial_cache"): fetch_url._free_trial_cache = TTLCache(maxsize=100000, ttl=86400) free_trial = fetch_url._free_trial_cache.get(client_id, { "remaining": settings.FREE_TRIAL_LIMIT, "total_used": 0 }) ``` ### Technical Analysis The caller is allowed to choose any syntactically valid `X-Client-ID`. The free-trial quota is keyed exclusively by that unauthenticated, attacker-controlled value. Changing the header creates a new quota record with the full free-trial allowance. The quota is also stored in an in-process `TTLCache`. It is not durable, is reset when the process restarts, and is not shared across application workers or replicas. A caller may therefore bypass limits by rotating client IDs, targeting different workers, ...[truncated 1177 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Issue free-trial credentials on the server rather than trusting caller-selected identifiers. 2. Cryptographically sign trial credentials and include an issuance time, expiration, quota, and unique identifier. 3. Store quota state in a durable shared backend such as Redis and decrement it atomically. 4. Apply defense-in-depth abuse controls using IP reputation, account registration, verified contact information, proof of work, or other appropriate signals. 5. Ensure quotas are consistent across workers, replicas, deployments, and service restarts. 6. Add global and per-destination rate limits to reduce forwarding and SSRF abuse. 7. Do not treat an arbitrary client ID as authentication. 8. Add tests that rotate client identifiers and distribute calls across multiple workers to verify that the free allowance cannot be reset. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (82)

Credential Access

High
Category
Privilege Escalation
Content
- Response content

**DO NOT use this proxy for:**
- API keys or access tokens
- Private keys or passwords
- Personal or sensitive data
- Internal/private network endpoints
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Response content

**DO NOT use this proxy for:**
- API keys or access tokens
- Private keys or passwords
- Personal or sensitive data
- Internal/private network endpoints
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
pip install -r requirements.txt

# 4. Configure environment
cp .env.example .env
# Edit .env with your settings:
# - HOSTED_WALLET: Your Polygon wallet address
# - ADMIN_TOKEN: Secure random string (16+ chars)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 4. Configure environment
cp .env.example .env
# Edit .env with your settings:
# - HOSTED_WALLET: Your Polygon wallet address
# - ADMIN_TOKEN: Secure random string (16+ chars)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 4. Configure environment
cp .env.example .env
# Edit .env with your settings:
# - HOSTED_WALLET: Your Polygon wallet address
# - ADMIN_TOKEN: Secure random string (16+ chars)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 4. Configure environment
cp .env.example .env
# Edit .env with your settings:
# - HOSTED_WALLET: Your Polygon wallet address
# - ADMIN_TOKEN: Secure random string (16+ chars)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 4. Configure environment
cp .env.example .env
# Edit .env with your settings:
# - HOSTED_WALLET: Your Polygon wallet address
# - ADMIN_TOKEN: Secure random string (16+ chars)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description promises a network-facing proxy service that enables unrestricted internet access and related web/API operations. The actual code shown does not perform proxying, outbound HTTP requests, scraping, routing, billing, or any other internet-access functionality. Instead, it is a generic security helper module focused on validation, sanitization, token generation, masking, and password checks. While such utilities could support a larger proxy system, this code chunk itself materially differs from the declared primary purpose, so this should be flagged as a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description emphasizes a secure HTTP proxy that gives AI agents internet access and supports scraping/API access. However, the supplied code does not implement proxying, HTTP requests, web access, scraping, or API integration behavior. Instead, it implements an abstract payment manager focused on deposits, balances, deductions, and charging users per request. While billing could be a supporting component of a pay-per-use proxy service, this code chunk’s primary purpose is payment processing, which is materially different from the declared primary functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description emphasizes a secure HTTP proxy that grants AI agents unrestricted internet access for web scraping and API use. The provided code chunk does not implement proxying, HTTP request routing, web access, scraping, or research automation. Instead, it only creates and caches a payment manager, switching between testnet and hosted payment implementations depending on configuration. That is a materially different primary purpose from the declared skill behavior, so this is a clear mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents the skill as an HTTP proxy for internet access and web/API retrieval. The supplied code does not implement proxying, web scraping, outbound HTTP access for agents, or research automation. Instead, it is a payment subsystem centered on USDC deposits to a hosted wallet, blockchain receipt inspection, balance accounting, and request-cost deduction. While the pricing amount ($0.001 per API call) loosely aligns with billing language in the description, the primary behavior is materially different and includes significant undeclared capabilities related to cryptocurrency payments and ledger management.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description centers on a secure HTTP proxy that gives AI agents internet access for scraping, APIs, and research automation. The supplied code does not implement proxying, outbound HTTP requests, request routing, scraping, billing, or internet access. Instead, it defines an abstract storage interface plus concrete MemoryStorage and RedisStorage implementations for application state/cache handling. This is a materially different primary purpose from the declared one. While storage could be a supporting component of a proxy system, this chunk itself is purely backend storage logic and exposes additional undeclared capabilities such as Redis access and Lua script evaluation. Therefore, the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a secure HTTP proxy service for agent internet access, web scraping, and API integrations. The supplied code does not implement proxying, HTTP request forwarding, scraping, or general internet access. Instead, it is a billing/payment component specifically for testnet payments: it provides a deposit address, validates user IDs and transaction hashes, optionally checks a blockchain transaction receipt through Web3, auto-credits a fixed amount of test USDC, deducts usage balance, stores transaction history, and can reset test balances. While the pay-per-request price of 0.001 appears consistent with the pricing mentioned in the description, the primary purpose and capabilities are materially different. Therefore this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents the skill as an HTTP proxy for unrestricted internet access and research/web/API usage. However, the supplied code chunk does not implement proxying, outbound web access, scraping, or API integration features. Instead, it handles billing/payment operations centered on USDC deposits, confirming blockchain transactions, querying balances, and resetting test balances in testnet mode. While payment may support the broader product, this chunk’s actual purpose is materially different from the declared primary purpose, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises a functional secure HTTP proxy for AI agents with internet access and related automation use cases. However, the provided code chunk is only an empty `tests/integration/__init__.py` file containing a comment. It does not implement any of the described capabilities, access any resources, define triggers, or provide supporting runtime behavior for the stated purpose. This is a material mismatch between declared purpose and actual behavior of the supplied code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Yes, this is a clear mismatch. The description claims a functional secure HTTP proxy service for AI agents with internet access and related capabilities. However, the provided code chunk is only `tests/unit/__init__.py` containing a comment marking a unit test package. It has no executable logic and does not implement any of the declared behavior. This is not merely partial coverage or a supporting detail; the actual code shown is unrelated to the stated primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description promises a network-facing HTTP proxy product that enables unrestricted internet access and related scraping/integration capabilities. The actual code does not implement or exercise proxying, outbound HTTP access, scraping, billing, or agent internet access. Instead, it contains unit tests for config parsing and input validation utilities, including transaction hash validation suggestive of a different application domain. This is a materially different primary purpose, so the description does not accurately represent the supplied code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description centers on a secure HTTP proxy that gives AI agents internet access for scraping and API use. The supplied code does not implement or test proxy/network request behavior. Instead, it is a unit test module covering storage abstractions and a testnet payment manager with deposit addresses, balances, deductions, and per-request charges. While pay-per-use billing may support the broader product, this specific chunk’s primary behavior is materially different from the declared proxy/internet-access purpose, so this is a description-behavior mismatch.

Credential Access

High
Category
Privilege Escalation
Content
DATABASE_URL: Optional[str] = Field(default=None, description="PostgreSQL database URL")
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = True
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Context-Inappropriate Capability

High
Confidence
92% confidence
Finding
This endpoint can arbitrarily reset a user's balance when the service is in testnet mode, gated only by a static bearer admin token and an environment flag. If testnet is exposed publicly, misconfigured, or the admin token is leaked, an attacker could mint credits, alter account balances, or abuse the proxy service without payment, which directly affects integrity of billing and access control.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Known Vulnerable Dependency: web3==7.14.1 — 2 advisory(ies): CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling); CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling)

High
Category
Supply Chain
Confidence
96% confidence
Finding
Using web3==7.14.1 with a known SSRF issue in CCIP Read/OffchainLookup handling is a genuine vulnerability if the service processes untrusted blockchain responses or user-supplied contract interactions. In this skill's context as an internet-enabled proxy gateway, SSRF is especially dangerous because it can be abused to reach internal services, cloud metadata endpoints, or other restricted network locations.

Known Vulnerable Dependency: pytest==8.3.5 — 2 advisory(ies): CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This markdown file is entirely presented in Chinese, and there is no indication that the skill or report is region-specific or that users can opt into another language. Under the language/locale policy, forcing a specific language without user choice or clear justification is a natural-language policy concern.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The report simultaneously marks security as passed while documenting that unauthenticated access to the fetch capability is allowed during a free-trial path. In a proxy-gateway skill that provides internet access, any unauthenticated network egress path can be abused for unauthorized scraping, SSRF-style pivoting, quota evasion, or use of the service as an open proxy, so calling security 'passed' is misleading and dangerous.

Static analysis

Detected: suspicious.dynamic_code_execution, suspicious.exposed_secret_literal

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
app/managers/hosted_payment.py:256

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
app/managers/storage.py:178

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
app/managers/storage.py:136

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
app/routers/proxy.py:57