Back to skill

Security audit

Pond3r Skill - Query Onchain Data

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a Pond3r data-query integration, but it includes under-scoped file reading and external report creation that users should review before installing.

Install only if you trust Pond3r with your query text and report descriptions. Avoid letting untrusted instructions choose --sql-file paths, keep POND3R_API_KEY out of logs and shared files, and treat report creation as a persistent external action that should require explicit user 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/query.mjs:34
Finding
Arbitrary Local File Disclosure Through Unrestricted --sql-file Input<![CDATA[ ## Vulnerability Details **File Location**: `scripts/query.mjs:34-41`, with the network sink in `scripts/client.mjs:76-98` **Vulnerability Type**: Unrestricted local file read followed by transmission to an external service **Risk Level**: Medium ### Vulnerable Code `scripts/query.mjs:34-41`: ```js let querySql = sql; if (sqlFile) { querySql = readFileSync(sqlFile, "utf8").trim(); } if (!datasetId || !querySql) { console.error("Usage: node query.mjs --dataset-id <dataset_id> --sql \"SELECT ...\" | --sql-file <path>"); process.exit(1); } const result = await callTool("query", { dataset_id: datasetId, sql: querySql }); ``` The corresponding outbound request is implemented in `scripts/client.mjs:76-98`: ```js export async function mcpCall(method, params = {}) { const apiKey = requireEnv("POND3R_API_KEY"); const headers = { "Content-Type": "application/json", Accept: "application/json, text/event-stream", Authorization: `Bearer ${apiKey}`, }; if (_sessionId) { headers["Mcp-Session-Id"] = _sessionId; } const body = { jsonrpc: "2.0", id: Date.now(), method, params, }; const res = await fetch(MCP_URL, { method: "POST", headers, body: JSON.stringify(body), }); ``` ### Technical Analysis The `--sql-file` option accepts an arbitrary filesystem path and passes it directly to `readFileSync`. The implementation does not constrain the path to a designated query directory, reject symbolic links, enforce a file extension or size limit, or verify that the resulting content is a read-only SQL statement. After the file is read, its complete contents are assigned to `querySql`, embedded in the `tools/call` request as the `sql` argument, and transmitted over HTTPS to the fixed Pond3r MCP endpoint. Any remote rejection or server-side SQL validation occurs only after the request body—and therefore the selected file contents—has already been transmitted. The documented “SELECT only” restriction ...[truncated 1869 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Restrict query files to a dedicated directory** - Resolve both the allowed directory and requested path with `realpath`. - Confirm that the canonical requested path remains inside the canonical allowed directory. - Reject absolute paths, traversal sequences, and paths escaping through symbolic links. 2. **Validate the file before transmission** - Permit only regular files with an expected `.sql` extension. - Apply a conservative maximum file size. - Reject null bytes, binary content, and multiple SQL statements. - Parse SQL with a suitable parser and allow only a single read-only `SELECT` statement or explicitly supported read-only CTE. 3. **Minimize filesystem privileges** - Run the Skill under a dedicated account or sandbox with access only to the workspace and approved query directory. - Do not mount secret directories, credential stores, or unrelated host paths into the runtime. 4. **Require explicit authorization for file access** - Before reading a query file, display its canonical path and require user confirmation when operating in an agent-controlled environment. - Do not allow untrusted webpage, chat, dataset, or tool output to choose a local path without confirmation. 5. **Prefer safer input mechanisms** - Accept query text through standard input or a narrowly scoped application interface rather than arbitrary filesystem paths. - Keep local validation mandatory even if Pond3r also enforces read-only SQL on the server. An appropriate canonical-path check should follow this pattern: ```js import { realpathSync, statSync, readFileSync } from "fs"; import { resolve, relative, extname } from "path"; const allowedRoot = realpathSync(resolve(process.cwd(), "queries")); const requestedPath = realpathSync(resolve(allowedRoot, sqlFile)); const rel = relative(allowedRoot, requestedPath); if (rel.startsWith("..") || rel === "" || extname(requestedPath) !== ".sql") { throw new ...[truncated 364 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The file explicitly claims the integration is read-only and says no writes occur, yet it also instructs use of a POST endpoint to create reports. This contradiction can mislead users and reviewers into authorizing a skill that performs external state changes, which is more dangerous because scheduled reports may persist, trigger recurring activity, or send structured outputs to external systems.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill requires environment access for `POND3R_API_KEY` and network access to Pond3r endpoints, but it does not declare any explicit tool scope or allowed-tools boundary. That mismatch weakens least-privilege controls and can let a runtime grant broader capabilities than reviewers expect, increasing the chance of unintended external access or secret handling.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill is presented throughout as a read-only MCP query integration, but this section introduces a separate REST API that can create scheduled reports via POST. That is a scope expansion and a documentation integrity issue: operators may approve the skill expecting passive querying, while the agent is also instructed to perform state-changing actions against an external service.

External Transmission

Medium
Category
Data Exfiltration
Content
### Create Report

```http
POST https://api.pond3r.xyz/v1/api/reports
Content-Type: application/json
x-api-key: <API_KEY>
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Create Report

```http
POST https://api.pond3r.xyz/v1/api/reports
Content-Type: application/json
x-api-key: <API_KEY>
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Create Report

```http
POST https://api.pond3r.xyz/v1/api/reports
Content-Type: application/json
x-api-key: <API_KEY>
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Create Report

```http
POST https://api.pond3r.xyz/v1/api/reports
Content-Type: application/json
x-api-key: <API_KEY>
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This markdown file includes a POST request to an external API and shows use of an `x-api-key` header, but it does not warn users that report descriptions and related data will be sent to a third-party service. It also does not mention basic credential-handling caution for the API key, which is relevant because the file is documentation for making authenticated network requests.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/client.mjs:10