Back to skill

Security audit

ens-manager

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform its stated ENS management purpose, but it asks agents to handle wallet secrets and execute irreversible mainnet transactions with under-scoped safeguards.

Review before installing. Use a dedicated low-value wallet, avoid command-line passwords or raw private keys, run read-only dry runs first, verify every mainnet transaction manually, and do not run the documented curl-to-sudo installer without independent verification. This is not malicious from the inspected artifacts, but it is high-risk for wallet operations as written.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
DEPENDENCIES.md:17
Finding
Mutable Remote Installation Script Executed with Root Privileges<![CDATA[ ## Vulnerability Details **File Location**: `DEPENDENCIES.md:17-20` **Vulnerability Type**: T03: Remote Payload Retrieval and Execution **Risk Level**: Critical ### Vulnerable Code ```bash **Install if needed:** - macOS: `brew install node` - Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs` - Windows: Download from https://nodejs.org ``` ### Technical Analysis The Ubuntu installation instructions download a mutable shell script from an external URL and immediately pipe it into `sudo bash`. The retrieved payload is not pinned to a specific version and is not verified using a cryptographic hash or trusted package signature before execution. Because the downloaded script executes with root privileges, its effective capabilities are not limited to installing Node.js. It can modify any system file, install services, create users, access locally stored data, or install additional software. The payload returned by the external server can also change after this Skill has been audited. This is classified as remote payload retrieval and execution even though the currently intended NodeSource script may be legitimate. The unsafe property is that the code actually executed by the user is externally controlled and cannot be established from the reviewed project. ### Attack Path 1. A user follows the documented Ubuntu installation instructions. 2. `curl` retrieves the current response from `https://deb.nodesource.com/setup_20.x`. 3. The response is passed directly to `sudo -E bash -` without local inspection or integrity verification. 4. If the upstream publishing account, server, DNS resolution, TLS trust path, or delivery infrastructure is compromised, the response can contain attacker-controlled shell commands. 5. Those commands execute as root. 6. The attacker can modify the operating system, steal credentials, install persistence, or compromise subsequent wallet operations. ### Impact Assessm ...[truncated 513 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `curl | sudo bash` pipeline from the documentation. 2. Prefer the operating system's signed Node.js packages where an acceptable version is available. 3. If NodeSource must be used: - Download a version-pinned installer or repository configuration file without executing it. - Verify its cryptographic hash or upstream signature. - Inspect the downloaded content before execution. - Execute only the minimum commands required to configure the repository. 4. Avoid preserving unnecessary environment variables through `sudo -E`. 5. Document the exact trusted signing key fingerprint and package verification procedure. 6. Prefer reproducible container or development-environment definitions that pin the Node.js distribution and digest. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create-subdomain.js:43
Finding
Wallet Passwords and Private Keys Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create-subdomain.js:43-75, 98-118` **Additional Locations**: `scripts/register-ens-name.js:39-69, 265-268`; `scripts/create-subdomain-ipfs.js:39-63, 109-115`; `DEPENDENCIES.md:92-133`; `SKILL.md:27-30, 51-53, 92-95, 167-169` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: High ### Vulnerable Code ```javascript console.error('Options:'); console.error(' --keystore PATH Encrypted keystore file'); console.error(' --password PASS Keystore password'); console.error(' --private-key-env VAR Environment variable with private key'); console.error(' --private-key KEY Private key (0x...)'); const options = { keystore: null, password: null, privateKeyEnv: null, privateKey: null, owner: null, resolver: PUBLIC_RESOLVER }; for (let i = 2; i < args.length; i += 2) { const key = args[i].replace('--', ''); const value = args[i + 1]; if (key === 'keystore') options.keystore = value; else if (key === 'password') options.password = value; else if (key === 'private-key-env') options.privateKeyEnv = value; else if (key === 'private-key') options.privateKey = value; else if (key === 'owner') options.owner = value; else if (key === 'resolver') options.resolver = value; } ``` ```javascript function getPrivateKey(options) { if (options.keystore && options.password) { console.log('🔐 Decrypting keystore...'); return decryptKeystore(options.keystore, options.password); } if (options.privateKeyEnv) { const key = process.env[options.privateKeyEnv]; if (!key) { throw new Error(`Environment variable ${options.privateKeyEnv} not set`); } console.log(`🔐 Using private key from env: ${options.privateKeyEnv}`); return key; } if (options.privateKey) { console.log('🔐 Using provided private key'); return options.privateKey; } throw new Error('No wallet credentials provided. Use --keystore + --pass ...[truncated 2198 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--private-key` option. 2. Do not accept passwords through command-line arguments. 3. Prompt for the password through a TTY with input echo disabled. 4. Support reading the password from a dedicated file descriptor or a permission-restricted secret file. 5. Prefer maintained wallet integrations, hardware wallets, or standard local signers so raw private keys do not enter application memory. 6. If environment-variable support remains available, clearly document that environment variables may be exposed through process dumps, CI configuration, and child processes. 7. Add warnings against storing secrets in shell history, scripts, aliases, notebooks, or CI command strings. 8. Clear sensitive buffers as soon as practical and ensure errors never include credential values. 9. Update every example in `SKILL.md`, `README.md`, `QUICK-START.md`, and `DEPENDENCIES.md` to use the secure input mechanism. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/register-ens-name.js:77
Finding
Custom Keystore Uses Unauthenticated AES-CBC Encryption<![CDATA[ ## Vulnerability Details **File Location**: `scripts/register-ens-name.js:77-91` **Additional Locations**: `scripts/create-subdomain.js:83-95`; `scripts/create-subdomain-ipfs.js:67-76`; `DEPENDENCIES.md:92-105` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: High ### Vulnerable Code ```javascript // Decrypt keystore function decryptKeystore(keystorePath, password) { const encrypted = readFileSync(keystorePath, 'utf8'); const { salt, iv, data } = JSON.parse(encrypted); const key = scryptSync(password, Buffer.from(salt, 'hex'), 32); const decipher = createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'hex')); const privateKey = Buffer.concat([ decipher.update(Buffer.from(data, 'hex')), decipher.final() ]).toString('utf8'); return privateKey; } ``` The documented custom format is: ```json { "salt": "hex-string", "iv": "hex-string", "data": "hex-encrypted-private-key" } ``` ### Technical Analysis AES-CBC provides confidentiality but does not provide ciphertext integrity or authenticity. The custom format contains no message authentication code and no authenticated-encryption tag. Consequently, the scripts cannot establish that the following values have not been modified: - Ciphertext in `data`. - Initialization vector in `iv`. - Key-derivation salt. - Keystore metadata. CBC ciphertext is malleable: changes to ciphertext blocks can produce controlled changes in portions of the following plaintext block. Modifications to the IV can alter the first decrypted block. Padding validation may detect some corruptions, but padding is not an authenticity mechanism and does not protect the complete plaintext. The format is also not the standard Ethereum Web3 Secret Storage format. Users may reasonably interpret the term “encrypted keystore” as implying the integrity and interoperability properties of a conventional Ethereum keystore, but those properties are not provided here. ### Attack Path 1 ...[truncated 1382 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the custom format with standard Ethereum Web3 Secret Storage JSON handled by a maintained and reviewed library. 2. Alternatively, use authenticated encryption such as AES-256-GCM or ChaCha20-Poly1305. 3. Authenticate all security-relevant metadata, including version, KDF parameters, salt, IV or nonce, and ciphertext. 4. Validate all decoded field lengths and reject malformed or unsupported formats before decryption. 5. Use explicit, versioned KDF parameters rather than relying on implicit defaults. 6. Verify that decrypted output is exactly a valid 32-byte secp256k1 private key. 7. Derive the account address and require user confirmation before signing transactions. 8. Clear plaintext private-key buffers and derived encryption keys as soon as practical. 9. Provide a secure migration process for existing custom keystores rather than silently interpreting them as a new format. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/package.json:1
Finding
Wallet-Handling Dependencies Are Mutable and Not Locked Reproducibly<![CDATA[ ## Vulnerability Details **File Location**: `scripts/package.json:1-9` **Additional Locations**: `DEPENDENCIES.md:24-70, 265-267` **Vulnerability Type**: T08: Insecure Dependencies **Risk Level**: Medium ### Vulnerable Code ```json { "name": "ens-manager-scripts", "version": "1.1.0", "description": "ENS management scripts - register names, create subdomains, publish IPFS", "dependencies": { "viem": "^1.20.0", "content-hash": "^2.5.2" } } ``` The installation documentation also recommends mutable installation commands: ```bash cd scripts/ npm install viem ``` ```bash cd scripts/ npm install content-hash ``` ```bash npm update ``` No package lockfile is present in the reviewed project structure. ### Technical Analysis Caret version ranges permit npm to install later compatible releases rather than the exact versions reviewed by the project author. The commands `npm install viem` and `npm install content-hash` are even less constrained because they request the registry's current matching release. Without a committed `package-lock.json`, dependency resolution is not reproducible. Two users installing the same project at different times can receive different direct and transitive package versions. These dependencies execute in a process that handles decrypted private keys and constructs or signs Ethereum transactions. A compromised or malicious dependency version would therefore run inside a highly sensitive trust boundary. No evidence was found that the currently named packages are typosquatted or malicious. The vulnerability is the inability to ensure that future installed code is the same dependency code that was reviewed. ### Attack Path 1. A user follows the documentation and runs `npm install`. 2. npm resolves the caret ranges or unversioned package names against the current registry state. 3. A newer allowed release or changed transitive dependency is installed. 4. If an upstream package version or maintainer account ...[truncated 948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct dependency to an exact reviewed version rather than using caret ranges. 2. Generate and commit `package-lock.json`. 3. Instruct users and CI systems to run `npm ci` rather than `npm install`. 4. Review and retain npm integrity hashes for all transitive packages. 5. Remove documentation that recommends unversioned package installation. 6. Avoid routine `npm update` instructions for wallet-handling environments. 7. Use automated dependency scanning, but require manual review before upgrading security-sensitive packages. 8. Consider npm configuration that disables unnecessary lifecycle scripts during installation where compatible: ```bash npm ci --ignore-scripts ``` 9. Record the reviewed Node.js and npm versions to improve reproducibility. 10. Re-audit transaction and key-handling behavior whenever `viem`, `content-hash`, or their transitive dependencies change. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (32)

Chaining Abuse

High
Category
Tool Misuse
Content
**Install if needed:**
- macOS: `brew install node`
- Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs`
- Windows: Download from https://nodejs.org

---
Confidence
97% confidence
Finding
Piping `curl` output directly into `sudo` is a high-risk command-chaining pattern because it executes remote content as root without inspection. In the context of a developer skill, users may copy-paste this blindly, making the documentation itself a vehicle for unsafe privileged execution.

Chaining Abuse

High
Category
Tool Misuse
Content
**Install if needed:**
- macOS: `brew install node`
- Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs`
- Windows: Download from https://nodejs.org

---
Confidence
97% confidence
Finding
Piping `curl` output directly into `sudo` is a high-risk command-chaining pattern because it executes remote content as root without inspection. In the context of a developer skill, users may copy-paste this blindly, making the documentation itself a vehicle for unsafe privileged execution.

Credential Access

High
Category
Privilege Escalation
Content
**Not published:**
- node_modules/ (gitignored)
- .env files (gitignored)
- Local testing files

---
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Self-Modification

High
Category
Rogue Agent
Content
clawdhub install YOUR-USERNAME/ens-manager
```

**Update skill README:**
Add install instructions at top:

```markdown
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Missing User Warnings

High
Confidence
99% confidence
Finding
The guide recommends supplying wallet passwords and even raw private keys directly on the command line, which can leak through shell history, process listings, CI logs, telemetry, or agent traces. In an autonomous-agent setting this is especially dangerous because secrets may be persisted or echoed by tooling outside the author's control, enabling wallet compromise and theft of all accessible assets.

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
Content
# ENS Manager

> Complete ENS workflow - register names, create subdomains, publish IPFS content in minutes

## The Problem

Managing ENS names requires multiple tools: app.ens.domains for registration, manual contract calls for subdomains, IPFS pinning services for content, and separate gateways for publishing. Each step takes time and technical knowledge.

## This Skill

Automates the complete ENS workflow from registration to published website - one command per operation, proper three-phase registration, automatic wrapped/unwrapped handling.

---

## 📋 Requirements

- Node.js 18+
- viem ^1.20.0
- content-hash ^2.5.2
- Ethereum wallet keystore
- ETH for gas + registration fees

---

## ⚡ What It Does

### Register New .eth Names
- **Check availa
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Broad capability claims combined with instructions to use local wallet/keystore material and send on-chain transactions create a trust and expectation gap. Even if some features are missing, the dangerous part is that the skill normalizes providing sensitive credentials and signing blockchain actions without a tightly scoped, accurate declaration of what will happen.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Broad capability claims combined with instructions to use local wallet/keystore material and send on-chain transactions create a trust and expectation gap. Even if some features are missing, the dangerous part is that the skill normalizes providing sensitive credentials and signing blockchain actions without a tightly scoped, accurate declaration of what will happen.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Broad capability claims combined with instructions to use local wallet/keystore material and send on-chain transactions create a trust and expectation gap. Even if some features are missing, the dangerous part is that the skill normalizes providing sensitive credentials and signing blockchain actions without a tightly scoped, accurate declaration of what will happen.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Broad capability claims combined with instructions to use local wallet/keystore material and send on-chain transactions create a trust and expectation gap. Even if some features are missing, the dangerous part is that the skill normalizes providing sensitive credentials and signing blockchain actions without a tightly scoped, accurate declaration of what will happen.

Ae1

High
Category
analysis-evasion
Content
node scripts/create-subdomain-ipfs.js yourname.eth subdomain QmIPFS123... \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/create-subdomain-ipfs.js yourname.eth subdomain QmIPFS123... \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/create-subdomain-ipfs.js yourname.eth subdomain QmIPFS123... \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The script decrypts a keystore to obtain a private key, but then creates a wallet client without binding that key as the signing account. As a result, transactions may be sent from whatever account the runtime/provider exposes, causing users to believe they are using the keystore account while actually spending funds from a different wallet or failing unpredictably.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Install if needed:**
- macOS: `brew install node`
- Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs`
- Windows: Download from https://nodejs.org

---
Confidence
90% confidence
Finding
The specific use of `sudo -E` preserves environment variables while executing as root, increasing risk because untrusted or unintended environment state can influence privileged execution. Combined with a fetched script, this creates a particularly unsafe installation pattern in documentation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Install if needed:**
- macOS: `brew install node`
- Ubuntu: `curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs`
- Windows: Download from https://nodejs.org

---
Confidence
90% confidence
Finding
The specific use of `sudo -E` preserves environment variables while executing as root, increasing risk because untrusted or unintended environment state can influence privileged execution. Combined with a fetched script, this creates a particularly unsafe installation pattern in documentation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation tells users to run `sudo chown -R $USER ~/.npm` to fix permissions, which performs a recursive ownership change with elevated privileges but does not explain the system-impact risks or safer alternatives. Recursive privileged ownership changes can unintentionally alter security-sensitive files, normalize unsafe troubleshooting practices, and mask an underlying permissions misconfiguration.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Fix npm permissions
sudo chown -R $USER ~/.npm
npm install
```
Confidence
92% confidence
Finding
This command requires `sudo` to recursively change ownership of the npm directory. While intended as troubleshooting, it can damage local security boundaries or fix the wrong problem if a user runs it blindly, especially because it modifies filesystem ownership under elevated privileges.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The instructions direct the user to run `gh repo create --public --source=. --push` and later `clawdhub publish .` without an explicit warning that these commands upload the current local repository contents to public remote services. In a skill workspace, users may incorrectly assume only selected files are published, increasing the risk of unintentionally exposing sensitive code, configs, notes, or other repository contents.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The troubleshooting section includes `gh repo delete ens-manager --yes` as a ready-to-run command without clearly warning that deletion is destructive and may permanently remove the remote repository and its contents. Users following troubleshooting steps under time pressure could delete the wrong repository or lose work unnecessarily.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The GitHub publishing instructions explicitly use `gh repo create ens-manager --public` without warning the user that all repository contents will become publicly accessible. In a skill that may contain operational scripts, wallet-related workflows, environment hints, or internal documentation, this increases the risk of accidental disclosure if users follow the commands verbatim.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The quick-start opens with 'For autonomous agent operations' and 'Copy-paste ready commands' while immediately presenting live ENS registration and subdomain creation workflows that incur real cost and produce irreversible on-chain effects. In an agent skill context, that framing materially increases the chance an agent or operator will execute mainnet transactions without explicit confirmation, budget checks, or rollback awareness.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The debugging section says testing on Sepolia is not supported and advises using small subdomains on mainnet for testing, normalizing experimentation with real funds and real ENS state. That guidance is risky because users or agents may treat testing as harmless and trigger unintended paid transactions or irreversible changes during validation and debugging.

Session Persistence

Medium
Category
Rogue Agent
Content
---

### Create Subdomain with Website

**Time: 1-2 minutes**
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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill describes handling wallet keystores, passwords, and on-chain transactions but does not declare any explicit tool scope or permission boundaries. That omission makes the sensitive capability opaque to users and host systems, increasing the risk of unintended access to environment-backed secrets or unsafe execution with wallet material.

Static analysis

No suspicious patterns detected.