Back to skill

Security audit

ENS (Ethereum Name Service)

Security checks for vulnerabilities and agentic risk

Overview

This ENS skill is coherent, but it needs review because it silently sends wallet/name lookups to third parties, stores ENS identity data, and includes an unsafe command example.

Review before installing. Basic ENS resolution is expected, but this skill may reveal lookup activity to third-party services and keep ENS-related identity data over time. Avoid using its raw node -e fallback with untrusted names; prefer a fixed script or argument-based resolver, and require explicit approval before storing ENS data or making ENS-changing transactions.

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

Error
Location
SKILL.md:68
Finding

User-Controlled ENS Name Injection in Node.js Fallback Command

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 68–80
Vulnerability Type: Command and JavaScript code injection through unsafe input interpolation
Risk Level: High

Vulnerable Code

bash
node --input-type=module -e "
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
import { normalize } from 'viem/ens';
const c = createPublicClient({ chain: mainnet, transport: http('https://eth.llamarpc.com') });
const addr = await c.getEnsAddress({ name: normalize('REPLACE_NAME') });
console.log(JSON.stringify({ address: addr }));
"

The subsequent instruction states:

text
Replace `REPLACE_NAME` with the actual ENS name.

Technical Analysis

The skill instructs the Agent to replace REPLACE_NAME directly with an ENS name supplied through user input. The value is embedded inside a JavaScript string literal contained in a shell command, but the instructions do not require strict ENS validation, escaping, or separation of code from data.

A crafted input containing quote characters and JavaScript syntax could terminate the normalize('...') string and inject statements into the program passed to node -e. Depending on how the Agent performs substitution and executes the resulting command, shell metacharacters or command substitutions could also be interpreted by the surrounding shell.

The skill's name-detection rule is broad—any token matching *.eth is considered likely to be an ENS name—and does not establish a restrictive validation boundary before the fallback command is generated. Although normalize() validates its argument at runtime, it cannot protect against injection that alters the JavaScript source before normalize() is called.

Attack Path

  1. An attacker submits a crafted value that appears to end in .eth but contains quote characters and executable JavaScript or shell syntax.
  2. The Agent classifies the value as an ENS n ...[truncated 1415 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not interpolate user input into executable source code. Keep the JavaScript program static and pass the ENS name as a separate process argument. Read it through process.argv inside the program.

  2. Avoid shell execution. Invoke Node.js through an argument-array API such as spawn or execFile with shell: false. This prevents shell metacharacters and command substitutions from being evaluated.

  3. Validate before execution. Apply ENS-compatible normalization and reject invalid input before performing resolution. Enforce a reasonable maximum length and reject control characters, quotes, newlines, shell metacharacters, and malformed labels. Validation should support legitimate internationalized ENS names through the canonical ENS normalization implementation rather than an improvised ASCII-only expression.

  4. Use a fixed script or safe argument pattern. For example, the static program can read the name from an argument:

    javascript
    import { createPublicClient, http } from 'viem';
    import { mainnet } from 'viem/chains';
    import { normalize } from 'viem/ens';
    
    const rawName = process.argv[2];
    if (!rawName) throw new Error('ENS name is required');
    
    const name = normalize(rawName);
    const client = createPublicClient({
      chain: mainnet,
      transport: http('https://eth.llamarpc.com'),
    });
    
    const address = await client.getEnsAddress({ name });
    console.log(JSON.stringify({ address }));
    

    Invoke it with the ENS name as a distinct argument and without a shell.

  5. Fail closed. If normalization or validation fails, report that the ENS name is invalid and do not attempt to repair, guess, or execute it.

  6. Reduce execution privileges. Run the resolution process in a restricted environment without wallet secrets, unnecessary filesystem access, or broad network permissions.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: ens
description: Resolve ENS names (.eth) to Ethereum addresses and vice versa. Use when a user provides an .eth name (e.g. "send to vitalik.eth"), when displaying addresses (show ENS names), looking up ENS profiles, or helping users register, renew, or manage .eth names.
homepage: https://docs.ens.domains/
metadata:
  openclaw:
    emoji: "🏷️"
    requires: { env: [] }
---

# ENS (Ethereum Name Service) — Skill

## What this skill does

Enables Gundwane to:
1. **Resolve ENS names** to Ethereum addresses (forward resolution)
2. **Resolve addresses** to ENS names (reverse resolution)
3. **Lo

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 149)May include surrounding context.

md
Use this URL when displaying a user's ENS avatar in messages.

## Display Rules

### When showing addresses
- After getting a user's wallet via `defi_get_wallet`, optionally check for a reverse ENS name.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly directs the agent to send user-provided ENS names and addresses to third-party services such as The Graph and web3.bio, but it does not instruct the agent to disclose that off-platform transmission is occurring. Even though ENS data is often public on-chain, the specific lookup activity can still reveal user intent, associations, and timing metadata to external providers.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This call transmits queried ENS names and related lookup parameters to The Graph gateway, an external service, without any privacy guardrails in the skill. That exposes user activity and potentially links addresses, names, and timing of actions to a third party.

Content

Scanner excerpt · SKILL.md (reported line 49)May include surrounding context.

Best for detailed data (expiry, registrant, resolver). Requires GRAPH_API_KEY env var.

bash
curl -s -X POST \
  --url "https://gateway.thegraph.com/api/$GRAPH_API_KEY/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" \
  --header 'Content-Type: application/json' \
  --data '{"query":"{ domains(where: { name: \"vitalik.eth\" }) { name resolvedAddress { id } expiryDate registration { registrant { id } expiryDate } } }"}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

Using web3.bio for forward resolution sends the ENS name being queried to a third-party profile service, which can log and correlate the lookup with other activity. The skill treats this as a default convenience path without any privacy disclosure or consent step.

Content

Scanner excerpt · SKILL.md (reported line 62)May include surrounding context.

Good for quick resolution + profile data in one call.

bash
curl -s "https://api.web3.bio/profile/vitalik.eth"

Returns JSON with address, identity, displayName, avatar, description, and linked social profiles. Use the address field for the resolved 0x address.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

Reverse-resolution via web3.bio transmits the user's wallet address to a third-party service, which can enable cross-session tracking or enrichment by that provider. The skill does not acknowledge this privacy risk despite recommending optional automatic display enhancements.

Content

Scanner excerpt · SKILL.md (reported line 104)May include surrounding context.

Via web3.bio

bash
curl -s "https://api.web3.bio/profile/0xd8da6bf26964af9d7eed9e03e53415d37aa96045"

Returns ENS name and profile if a primary name is set.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

Profile lookup requests to web3.bio disclose which ENS identity the user is investigating and can return enriched social data that increases profiling sensitivity. The skill frames these lookups as routine but omits any notice that a third party receives the query.

Content

Scanner excerpt · SKILL.md (reported line 126)May include surrounding context.

Get ENS profile details: avatar, description, social links, text records.

bash
curl -s "https://api.web3.bio/profile/nick.eth"

Common text record keys (for reference):

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The availability-check query sends requested ENS labels to an external Graph endpoint, which can reveal names a user intends to register. That information may be commercially sensitive and can expose user interest patterns even if not directly exploitable on-chain.

Content

Scanner excerpt · SKILL.md (reported line 194)May include surrounding context.

Via the ENS subgraph:

bash
curl -s -X POST \
  --url "https://gateway.thegraph.com/api/$GRAPH_API_KEY/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" \
  --header 'Content-Type: application/json' \
  --data '{"query":"{ registrations(where: { labelName: \"myname\" }) { labelName expiryDate } }"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs persistent storage of ENS names, expiry dates, preferences, and related narrative memory in per-user strategy data without requiring clear disclosure or consent for retention. This can create unnecessary long-lived profiling about wallet identity and behavior, especially when tied to reminders and heartbeat monitoring.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.