Back to skill

Security audit

Web3dropper Crypto Price Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its identity-management purpose, but it stores powerful identity keys unencrypted with weak local protections and includes unrelated packaged crypto-price code, so it needs Review before installation.

Install only if you are comfortable with this skill creating long-lived identity credentials under $HOME/.openclaw/billions. Treat the host account as sensitive, do not import valuable private keys through the documented --key command, restrict file permissions manually if used, and review the unrelated nested crypto-price package before trusting the published artifact.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/shared/storage/base.js:27
Finding
Unencrypted Private Keys Stored Without Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/shared/storage/base.js:8-10, 27-31` - `scripts/shared/storage/keys.js:6-22` - `skills/web3dropper-verified-agent/scripts/shared/storage/base.js:8-10, 27-31` - `skills/web3dropper-verified-agent/scripts/shared/storage/keys.js:6-22` **Vulnerability Type**: Plaintext sensitive-data storage with insufficient access controls **Risk Level**: High ### Vulnerable Code ```js async ensureDirectory() { const dir = path.dirname(this.filePath); await fs.mkdir(dir, { recursive: true }); } async writeFile(data) { await this.ensureDirectory(); const json = JSON.stringify(data, null, 2); const tempPath = `${this.filePath}.tmp`; await fs.writeFile(tempPath, json, "utf-8"); await fs.rename(tempPath, this.filePath); } ``` ```js /** * File-based storage for cryptographic keys. * Implements AbstractPrivateKeyStore interface from js-sdk. * Stores keys in JSON format as an array of {alias, privateKeyHex} objects. */ class KeysFileStorage extends FileStorage { constructor(filename = "kms.json") { super(filename); } async importKey(args) { const keys = await this.readFile(); const index = keys.findIndex((entry) => entry.alias === args.alias); if (index >= 0) { keys[index].privateKeyHex = args.key; } else { keys.push({ alias: args.alias, privateKeyHex: args.key }); } await this.writeFile(keys); } } ``` ### Technical Analysis The Skill deliberately persists raw private keys in `$HOME/.openclaw/billions/kms.json`. This storage is necessary for persistent identity signing, but the implementation does not apply the minimum protections appropriate for cryptographic key material. `fs.mkdir()` and `fs.writeFile()` are called without explicit modes. Their resulting permissions depend on the process umask. Under a common `022` umask, the directory may be created as `0755` and the temporary key file as `0644`, permitting other local accounts to traverse the dir ...[truncated 1432 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the sensitive directory with mode `0700` and verify or repair the mode if it already exists: ```js await fs.mkdir(dir, { recursive: true, mode: 0o700 }); await fs.chmod(dir, 0o700); ``` 2. Create temporary key files with mode `0600`, using exclusive creation where practical: ```js await fs.writeFile(tempPath, json, { encoding: "utf-8", mode: 0o600, flag: "wx", }); ``` 3. Reject symbolic links and verify that the directory and destination are owned by the current user before reading or writing them. 4. Use randomized temporary filenames in the same protected directory, flush data as required, rename atomically, and enforce `0600` again on the final file. 5. Prefer encryption at rest through an operating-system keychain, hardware-backed keystore, or dedicated KMS. If file encryption is used, the decryption key must not be stored beside `kms.json`. 6. Apply the same correction to both shipped copies of the storage implementation. 7. Add automated tests that run under permissive umasks and verify that key directories and files remain inaccessible to group and other users. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/createNewEthereumIdentity.js:24
Finding
Private Keys Accepted Through Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/createNewEthereumIdentity.js:24-32` - `SKILL.md:37, 45-49` - `skills/web3dropper-verified-agent/scripts/createNewEthereumIdentity.js:24-32` - `skills/web3dropper-verified-agent/SKILL.md:37, 45-49` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```js // Use provided key or generate a new one let privateKeyHex = args.key; if (!privateKeyHex) { privateKeyHex = new SigningKey(Wallet.createRandom().privateKey) .privateKey; } // Create signer from private key const signer = new SigningKey(addHexPrefix(privateKeyHex)); ``` The documented interface explicitly instructs users to place the key on the command line: ```text node scripts/createNewEthereumIdentity.js --key <privateKeyHex> ``` ### Technical Analysis The Skill accepts an existing private key through `--key`. Command-line arguments are not a secure secret-transport mechanism. Depending on the operating system and deployment environment, argument vectors may be exposed through process inspection, diagnostic tooling, audit systems, shell history, terminal logs, job metadata, or orchestration telemetry. The key is not printed or intentionally transmitted by the script. Nevertheless, exposure occurs before or while the process runs because the secret is part of the invocation itself. Importing an existing key is consistent with the Skill’s identity-management function, but accepting it through a globally observable argument exceeds the minimum safe privilege and disclosure boundary required for that operation. ### Attack Path 1. A user follows the documented example and invokes the script with `--key`. 2. The complete private key is recorded in shell history or exposed in the process argument vector. 3. A local observer, monitoring agent, audit collector, or operator with access to that metadata retrieves the argument. 4. The observer imports the recovered key i ...[truncated 508 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--key <privateKeyHex>` as a supported secret-input mechanism. 2. Accept imported keys from one of these safer sources: - A non-echoing interactive prompt. - Standard input with explicit user confirmation. - A permission-checked file descriptor. - An operating-system keychain or external KMS. 3. If standard input is used, clearly warn users not to provide the secret through shell interpolation or an environment variable. 4. Ensure errors never include the submitted key and clear avoidable in-memory copies after import where runtime behavior permits. 5. Update all README and Skill examples so they no longer encourage command-line secret handling. 6. Apply the change to both copies of `createNewEthereumIdentity.js`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verifySignature.js:53
Finding
Authentication Challenges Remain Replayable Indefinitely<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/generateChallenge.js:18-21` - `scripts/shared/storage/challenge.js:7-20, 28-31` - `scripts/verifySignature.js:17-22, 53-61` - Corresponding files under `skills/web3dropper-verified-agent/scripts/` **Vulnerability Type**: Missing challenge expiration and one-time consumption **Risk Level**: Medium ### Vulnerable Code Challenge generation uses a value below ten billion: ```js // Generate random challenge const challenge = randomInt(0, 10000000000).toString(); // Save challenge to storage await challengeStorage.save(args.did, challenge); ``` The storage records a creation time but retrieval does not enforce it: ```js async save(did, challenge) { const entries = await this.readFile(); const created_at = new Date(); const index = entries.findIndex((entry) => entry.did === did); if (index >= 0) { // Update existing entry entries[index] = { did, challenge, created_at }; } else { // Add new entry entries.push({ did, challenge, created_at }); } await this.writeFile(entries); } async getChallenge(did) { const entry = await this.find(did); return entry?.challenge; } ``` Verification compares the token against the stored challenge but does not delete it after success: ```js // Verify the challenge matches const payload = basicMessage.body; if (payload.message !== challenge) { console.error( `Error: Invalid signature: challenge mismatch ${payload.message} !== ${challenge}`, ); process.exit(1); } outputSuccess("Signature verified successfully"); ``` ### Technical Analysis A secure challenge-response protocol requires challenges to be unpredictable, short-lived, purpose-bound, and consumed exactly once. The implementation records `created_at`, but `getChallenge()` returns the challenge regardless of its age. `verifySignature.js` does not delete or invalidate the challenge after successful verification. A captured valid token can consequently be submitted ...[truncated 1258 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate challenges with at least 128 bits of cryptographically secure randomness: ```js const { randomBytes } = require("crypto"); const challenge = randomBytes(16).toString("hex"); ``` 2. Store an explicit expiration time and reject stale challenges during verification. 3. Bind each challenge to its intended DID, verifier, audience, protocol purpose, and transaction or session identifier. 4. Atomically consume the challenge after successful verification. The compare-and-delete operation should be protected against concurrent verification attempts. 5. Consider marking the challenge as consumed before reporting success, with transactional recovery behavior if persistence fails. 6. Avoid including the received challenge value in detailed error output where logs could disclose protocol material. 7. Add tests for expired challenges, duplicate token submission, concurrent replay attempts, and challenge replacement. 8. Apply the same fixes to the duplicate implementation under `skills/web3dropper-verified-agent/scripts/`. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (68)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
There is a clear mismatch between the declared purpose and the actual code. The description says the skill provides identity/authentication functions using Billions/Iden3, but the supplied code only retrieves Bitcoin price data from Binance and prints it. No identity-related logic, cryptographic proof handling, signing, verification, or account linking is present. The primary purpose, external resource accessed, and implemented capability are all materially different from the declaration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Most of the code aligns with identity-management functionality: DID processing, DID document generation, key-path normalization, and authorization response message creation. However, the code also includes an unrelated outbound messaging capability, `sendDirectMessage`, which validates a target/message and invokes an external CLI (`openclaw message send`) using `execFileSync`. The declared description mentions authentication, identity management, linking, proof, signing, and verifying, but does not mention messaging or external command execution. That is a material undeclared capability rather than a mere implementation detail, so this should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Most of the code aligns with the declared identity-management purpose: DID/Ethereum address derivation, DID document creation, key normalization, and authorization response message generation are consistent with Iden3/PolygonID authentication tooling. However, the `sendDirectMessage` function adds a distinct capability not described in the declaration: sending messages to external targets through a child process call to `openclaw`. This is an actionable outbound communication capability, not merely a supporting detail of identity proof/sign/verify. The CLI parsing/output helpers are less significant, but they also indicate command-line utility behavior beyond the stated description. Therefore, the description does not fully and accurately represent the code's actual behavior.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill encourages users to create identities and potentially import private keys before prominently warning that identity data, including unencrypted private keys, is stored locally under `$HOME/.openclaw/billions`. This can lead operators to expose highly sensitive cryptographic material without informed consent, especially in shared or weakly isolated environments.

Credential Access

High
Category
Privilege Escalation
Content
- `kms.json` - **CRITICAL**: Contains unencrypted private keys
- `defaultDid.json` - DID identifiers and public keys
- `challenges.json` - Authentication challenges history
- `credentials.json` - Verifiable credentials
- `identities.json` - Identity metadata
- `profiles.json` - Profile data
Confidence
98% confidence
Finding
The skill explicitly documents storage of highly sensitive identity artifacts, including `kms.json` with unencrypted private keys and `credentials.json` with verifiable credentials. In an agent environment, any over-broad file access, accidental logging, backup leakage, or compromise of the host can expose those credentials and enable identity theft, impersonation, or unauthorized signing.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The README content describes a cryptocurrency price-fetching skill, while the declared skill metadata says the package provides Billions/Iden3 authentication and identity-management capabilities. This kind of capability/identity mismatch is dangerous because it can hide the true behavior of a skill from reviewers and users, enabling deceptive packaging, incorrect trust decisions, or substitution of unrelated code under a trusted identity-oriented name.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The SKILL.md content says this is a 'Simple test skill for OpenClaw agent,' which conflicts with the declared purpose of providing Billions/Iden3 authentication and identity-management capabilities. This mismatch can mislead reviewers and users about what the skill actually does, weakening trust, review quality, and safe deployment decisions for a security-sensitive identity skill.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The code behavior does not match the declared skill purpose of identity/authentication and instead performs an unrelated cryptocurrency price lookup. This kind of capability mismatch is dangerous because it indicates the skill may be mislabeled, making review and trust decisions unreliable and enabling hidden or substituted behavior under a benign-looking manifest.

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding
`axios` 1.13.6 is flagged with multiple advisories including SSRF-related proxy bypass and prototype-pollution-assisted request/response compromise. In an agent identity skill, outbound HTTP is especially sensitive because requests may carry credentials, proofs, tokens, or verification material; a vulnerable HTTP client can enable credential theft, request redirection, or manipulation of trust decisions.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
93% confidence
Finding
`form-data` 4.0.5 is flagged for CRLF injection via unescaped multipart field names/filenames, which can corrupt multipart requests or inject attacker-controlled headers/content. In a skill handling identity documents, proofs, or signed artifacts, malformed multipart construction could enable request smuggling-like effects, tamper with uploads, or exfiltrate sensitive material to downstream services.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The package metadata claims this skill is a crypto price lookup tool using the Binance API, which directly conflicts with the declared skill purpose of agent identity/authentication. This kind of capability mismatch is dangerous because it can conceal undeclared behavior, evade review, and cause operators to grant trust or permissions to a package that is not what it claims to be.

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
92% confidence
Finding
The package depends on axios through a version range that can include versions reported as vulnerable, including SSRF-related and prototype-pollution-adjacent issues. In an agent skill, HTTP client flaws are especially concerning because agents often fetch remote resources, handle credentials, and may run in privileged network environments.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The manifest metadata conflicts with the declared skill context: a package presented for Billions/Iden3 authentication instead identifies itself as a Binance BTC price fetcher. This kind of identity mismatch is dangerous because it can conceal unrelated functionality, defeat review expectations, and enable supply-chain style deception where operators grant trust or permissions based on a false description.

Known Vulnerable Dependency: ws==8.18.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
95% confidence
Finding
ws 8.18.0 is flagged for memory disclosure and memory-exhaustion denial of service issues. In an agent identity/authentication skill that may maintain websocket connections to blockchain or verifier infrastructure, a vulnerable websocket library is materially relevant because malformed remote traffic could crash the process or expose memory contents.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
90% confidence
Finding
brace-expansion 2.0.2 is flagged for multiple denial-of-service conditions involving pathological expansion patterns. This is a real dependency weakness, although it is usually only exploitable if untrusted input is passed into glob/brace processing, so the risk is contextual rather than automatically exposed by presence alone.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
94% confidence
Finding
fast-uri 3.1.0 is flagged for multiple host-confusion and SSRF-related parsing flaws. This is particularly relevant in an authentication/identity skill because such systems often dereference DIDs, schemas, JSON-LD contexts, RPC endpoints, or verifier URLs; a flawed URI parser can enable outbound requests to unintended internal or attacker-chosen destinations.

Credential Access

High
Category
Privilege Escalation
Content
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
Confidence
84% confidence
Finding
The code stores credential data in a local file (credentials.json), which can expose sensitive identity artifacts, claims, or metadata if the file is readable by unauthorized users or included in logs/backups. In an agent identity-management context, credential storage is expected, but persisting it to a flat local file without visible access controls or encryption still creates a real confidentiality risk.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
---
name: verified-agent-identity
description: Billions/Iden3 authentication and identity management tools for agents. Link, proof, sign, and verify.
metadata: { "category": "identity", "clawbot": { "requires": { "bins": ["node", "openclaw"] } }}
homepage: https://billions.network/
---

## When to use this Skill

Lets AI agents create and manage their own identities on the Billions Network, and link those identities to a human owner.

1. When you need to link your agent identity to an owner.
2. When you need sign a challenge.
3. When you need link a human to the agent's DID.
4. When you need to verify a signature to confirm identity ownership.
5. When use shared JWT tokens for authentication.
6. When you need to create and manage decentralized identities.

### After installing the plugin run the following commands to create an identity and link it to your human DID:

```bash
cd scripts && npm install && cd
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
---
name: verified-agent-identity
description: Billions/Iden3 authentication and identity management tools for agents. Link, proof, sign, and verify.
metadata: { "category": "identity", "clawbot": { "requires": { "bins": ["node", "openclaw"] } }}
homepage: https://billions.network/
---

## When to use this Skill

Lets AI agents create and manage their own identities on the Billions Network, and link those identities to a human owner.

1. When you need to link your agent identity to an owner.
2. When you need sign a challenge.
3. When you need link a human to the agent's DID.
4. When you need to verify a signature to confirm identity ownership.
5. When use shared JWT tokens for authentication.
6. When you need to create and manage decentralized identities.

### After installing the plugin run the following commands to create an identity and link it to your human DID:

```bash
cd scripts && npm install && cd
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Credential Access

High
Category
Privilege Escalation
Content
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
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
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
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
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
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
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The README instructs users to install and run `npx clawhub@latest`, which pulls the latest package version at execution time rather than a reviewed, pinned version. This creates a supply-chain risk: if the package is compromised or a breaking/malicious update is published, users may execute untrusted code during installation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
This is the same supply-chain issue repeated in the human installation instructions: `npx clawhub@latest` executes whatever version is current at runtime. Because `npx` may download and run code immediately, a compromised upstream package could lead to arbitrary code execution on the user's system.

Static analysis

No suspicious patterns detected.