Back to skill

Security audit

zscore

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for Zeru agent registration, but it uses a funded blockchain private key for irreversible on-chain actions and automatically fetches untrusted metadata URLs.

Install only if you are comfortable giving this skill a dedicated wallet private key and letting it submit on-chain transactions. Prefer a testnet or low-balance wallet, avoid using a primary funded key, review every write command before running it, and be cautious reading unknown agent IDs because their metadata URL may trigger outbound requests from your environment.

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
lib/get-agent.js:13
Finding
Unrestricted Fetch of Attacker-Controlled On-Chain URI Enables SSRF## Vulnerability Details **File Location**: `lib/get-agent.js:13-29` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: Medium ### Vulnerable Code ```js const [owner, agentURI, wallet] = await Promise.all([ registry.ownerOf(id), registry.tokenURI(id), registry.getAgentWallet(id), ]); const ZERO = "0x0000000000000000000000000000000000000000"; const result = { owner, agentURI, agentWallet: wallet === ZERO ? null : wallet, }; // Try to fetch and parse the agentURI if (agentURI && agentURI.startsWith("http")) { try { const res = await fetch(agentURI); if (res.ok) result.parsedJson = (await res.json()); } catch { // skip — optional } } ``` ### Technical Analysis The `agentURI` value is read directly from an on-chain token and may be controlled by an arbitrary registry participant. The implementation automatically dereferences that URI whenever it begins with the text `http`. This prefix check is not an adequate security boundary. The code does not: - Parse and validate the URI using a strict URL parser. - Restrict requests to approved metadata services. - Reject loopback, private, link-local, multicast, or cloud metadata addresses. - Resolve hostnames and validate their resulting IP addresses. - Validate redirect destinations. - Restrict destination ports. - Apply a request timeout. - Limit the response size. - Validate the response content type before parsing it as JSON. The request does not explicitly include the configured private key, environment variables, authentication headers, or other local secrets. Therefore, this is not evidence of direct private-key exfiltration. Nevertheless, it creates an SSRF primitive because an untrusted on-chain participant can choose a URL that the victim's runtime will request. ### Attack Path 1. An attacker registers or updates an agent ...[truncated 1853 chars]
Remediation
## Remediation Suggestions 1. **Make remote metadata retrieval opt-in** - Separate on-chain reads from URI retrieval. - Return `owner`, `agentURI`, and `agentWallet` by default. - Require an explicit option such as `fetchMetadata: true` before making a network request. 2. **Use a strict destination allowlist** - Prefer fetching only from approved Agent URI hosts or trusted content gateways. - Compare normalized hostnames rather than using string-prefix checks. - If broad Internet retrieval is essential, apply all of the network restrictions below. 3. **Validate the URL and protocol** - Parse the value with `new URL(agentURI)`. - Allow only explicitly supported protocols, preferably HTTPS. - Reject embedded credentials, unusual ports, malformed hosts, and unsupported schemes. 4. **Block internal network destinations** - Resolve the hostname before connecting. - Reject IPv4 and IPv6 loopback, private, link-local, multicast, unspecified, and reserved address ranges. - Explicitly block cloud metadata destinations. - Repeat validation for every DNS resolution and redirect to mitigate DNS rebinding and redirect-based bypasses. 5. **Control redirects** - Disable automatic redirects with `redirect: "manual"`, or validate every redirect target before following it. - Set a small maximum redirect count. 6. **Apply resource limits** - Use `AbortController` to enforce a short timeout. - Validate `Content-Type` before JSON parsing. - Stream the body and enforce a strict maximum byte size. - Reject excessively deep or otherwise resource-intensive JSON structures where applicable. 7. **Isolate outbound retrieval** - Route metadata fetching through a hardened proxy with egress restrictions. - Run the retrieval component without access to sensitive internal networks whenever possible. 8. **Treat metadata as untrusted** - Do not execute fetched content ...[truncated 120 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description says the skill can 'manage wallets,' but the documented command set only supports unsetting an agent wallet, which could mislead users about scope and safety. The registration path also requires reading a local JSON file via `--json`, an input-handling behavior not surfaced in the high-level description; this matters because file ingestion can expand attack surface and confuse operators about what data is consumed.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description says the skill can 'manage wallets,' but the documented command set only supports unsetting an agent wallet, which could mislead users about scope and safety. The registration path also requires reading a local JSON file via `--json`, an input-handling behavior not surfaced in the high-level description; this matters because file ingestion can expand attack surface and confuse operators about what data is consumed.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description says the skill can 'manage wallets,' but the documented command set only supports unsetting an agent wallet, which could mislead users about scope and safety. The registration path also requires reading a local JSON file via `--json`, an input-handling behavior not surfaced in the high-level description; this matters because file ingestion can expand attack surface and confuse operators about what data is consumed.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill requires sensitive capabilities (`PRIVATE_KEY`, network access, package execution) but does not declare an explicit tool scope such as permissions or allowed-tools. This increases the chance that an agent or operator will invoke broader capabilities than intended, especially for blockchain write operations that can spend funds or alter on-chain state.

External Transmission

Medium
Category
Data Exfiltration
Content
"services": [
    {
      "name": "MCP",
      "endpoint": "https://api.dataanalyst.ai/mcp",
      "version": "2025-06-18",
      "mcpTools": ["analyze_wallet", "trace_transactions", "detect_anomalies"],
      "capabilities": []
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
"services": [
    {
      "name": "MCP",
      "endpoint": "https://api.dataanalyst.ai/mcp",
      "version": "2025-06-18",
      "mcpTools": ["analyze_wallet", "trace_transactions", "detect_anomalies"],
      "capabilities": []
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Session Persistence

Medium
Category
Rogue Agent
Content
```

**Steps to register:**
1. Create a JSON file following the structure above (e.g. `agent.json`)
2. Run: `npx tsx {baseDir}/scripts/zeru.ts register --json agent.json`

The SDK automatically adds `type`, `registrations` (with `agentId: 0` placeholder), and defaults for missing optional fields. After minting, it updates the document with the real `agentId`.
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Using `npx tsx` without pinning an exact package version creates supply-chain risk because package resolution may fetch unexpected code or different versions over time. In a skill that can access a private key and send transactions, execution of an unpinned package materially increases the blast radius of compromise.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The documentation instructs users to place a funded `PRIVATE_KEY` directly into a config example without an explicit warning against hardcoding or exposing it. This creates a realistic risk of credential leakage through copied configs, shell history, backups, screenshots, or repository commits, and the credential directly controls blockchain funds and write permissions.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes the skill as focused on registering agents, managing wallets and metadata, and reading on-chain state. This index file also exposes agent discovery via searchAgents and a separate reputation feature via getReputation, which are not mentioned in the manifest description and expand the skill's apparent behavior beyond the stated scope.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The shebang uses `npx tsx`, which can resolve and execute a package version that is not pinned locally, creating a supply-chain risk. In a skill that handles `PRIVATE_KEY` and performs on-chain writes, executing an unexpected `tsx` version could expose secrets or alter transaction behavior before any blockchain operation occurs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
`unset-wallet` triggers an irreversible on-chain state change immediately, without a confirmation prompt, dry-run summary, or explicit warning. In this skill's context, where real blockchain transactions are signed with a live `PRIVATE_KEY`, a mistaken invocation, prompt-injection-driven tool use, or operator error can permanently disconnect an agent wallet and disrupt agent operation.

Missing User Warnings

Low
Confidence
77% confidence
Finding
This code constructs URLs for external API and RPC usage, and the configuration also includes a discovery API key field. There is no user-facing log, comment, or warning in this file explaining that the skill may contact remote services and transmit configuration-derived data.

Intent-Code Divergence

Low
Confidence
91% confidence
Finding
The CLI advertises and earlier logs a successful registration using the provided agent input, but the final success output prints `${name}` even though `name` is only defined inside the simple-flag branch and not in the surrounding function scope. This contradicts the apparent intent of the success message and can cause the command to fail or misreport at the end of an otherwise successful registration flow.

Static analysis

No suspicious patterns detected.