Back to skill

Security audit

Virtuals

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it asks users to paste and persist a crypto private key in plaintext while overstating trading/create features and security.

Review carefully before installing. Do not provide a real wallet private key to this skill; use a throwaway wallet only, and treat any key already entered through the documented command as potentially exposed through shell history and the plaintext config file. The market-data and balance features appear coherent, but the advertised trading/creation capability is not actually implemented in the inspected code.

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
src/cli.ts:259
Finding

Unnecessary Collection and Plaintext Storage of Cryptocurrency Private Keys

Content
View full analysis
--private-key '); return; } ``` ```ts program .command('config') .description('Configure wallet for trading') .option('--wallet ', 'Wallet address') .option('--private-key ', 'Private key (stored securely)') .option('--show', 'Show current config') .action(async (options) => { if (options.show) { const config = loadConfig(); console.log('\n⚙️ Virtuals Configuration'); console.log('═══════════════════════════════════════'); console.log(` Wallet: ${config.wallet || 'Not set'}`); console.log(` Key: ${config.privateKey ? '••••••••' : 'Not set'}`); console.log('═══════════════════════════════════════'); return; } const config = loadConfig(); if (options.wallet) { config.wallet = options.wallet; } if (options.privateKey) { config.privateKey = options.privateKey; } saveConfig(config); console.log('✅ Configuration saved'); }); ``` The documented invocation also directs users to expose the key through a command-line argument: ```bash virtuals config --wallet --private-key ``` ### Technical Analysis The Skill requests a cryptocurrency private key as a command-line argument and persists it as unencrypted JSON in `~/.openclaw/virtuals/config.json`. ...[truncated 3057 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This is a stronger form of the same issue: the skill claims trading and agent creation features while actually storing private keys locally, relying on undeclared resource access, and only redirecting users externally for core actions. Such deceptive or inaccurate documentation can lead to credential exposure and unsafe operational assumptions in a financial context.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This is a stronger form of the same issue: the skill claims trading and agent creation features while actually storing private keys locally, relying on undeclared resource access, and only redirecting users externally for core actions. Such deceptive or inaccurate documentation can lead to credential exposure and unsafe operational assumptions in a financial context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The CLI accepts and persists a raw private key in a local JSON config file, even though the current code does not need signing functionality. Storing long-lived wallet secrets on disk greatly increases the chance of key theft through local compromise, backups, logs, malware, or accidental disclosure, and here the risk is especially unnecessary because no transaction flow is implemented.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The option text claims the private key is 'stored securely', but the implementation writes it directly to plaintext JSON on disk. This is dangerous because it gives users false confidence and may cause them to expose real wallet credentials under the mistaken belief that the application provides hardened secret handling.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: axios==1.13.5 — 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

The lockfile pins axios 1.13.5, which the scanner reports as affected by multiple advisories including SSRF/proxy-bypass and prototype-pollution-related request hijacking issues. In a skill that integrates with external protocols and likely performs network calls, a vulnerable HTTP client can enable request redirection, credential leakage, or access to internal resources if attacker-controlled URLs, redirects, or proxy settings are involved.

Content

No source excerpt is available for this finding.

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
90% confidence
Finding

form-data 4.0.5 is reported as vulnerable to CRLF injection through unescaped multipart field names/filenames. If this skill ever builds multipart requests from user-controlled inputs, an attacker may be able to smuggle additional multipart headers or alter request structure, which can lead to request tampering or downstream parser confusion.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.17.1 — 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
92% confidence
Finding

ws 8.17.1 is flagged for memory disclosure and memory-exhaustion denial-of-service issues. In a blockchain/agent-trading integration, WebSocket connections may be used for live events or provider streams, so malformed or hostile peer traffic could crash the process, degrade availability, or potentially expose process memory contents.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: axios==1.13.5 — 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
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The CLI claims the private key is 'stored securely', but saveConfig writes it as plaintext JSON to disk. Even with chmod 0600, malware, backup systems, local compromise, shell history exposure, or other processes running as the same user can recover the key and fully drain the wallet.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
81% confidence
Finding

The skill advertises capabilities that involve environment/config access but does not declare an explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, missing scope declarations weaken user visibility and policy enforcement, making it easier for a skill to access sensitive local state or behave beyond what its manifest suggests.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
- 📊 **List agents** - Browse top AI agents on Virtuals
- 💰 **Check prices** - Get agent token prices and market data
- 🔍 **Agent details** - View agent info, holders, transactions
- 🚀 **Create agent** - Launch your own tokenized AI agent
- 💸 **Trade** - Buy/sell agent tokens

## Installation

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs users to pass a private key directly on the command line without explicit secure-handling guidance. Private keys entered this way may be exposed through shell history, process listings, logs, or insecure local config storage, which can directly lead to wallet compromise and fund loss.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · dist/cli.js (reported line 91)May include surrounding context.

js
}
async function getVirtualPrice() {
    try {
        const response = await axios_1.default.get('https://api.coingecko.com/api/v3/simple/price?ids=virtual-protocol&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true');
        const data = response.data['virtual-protocol'];
        return {
            price: data.usd,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · src/cli.ts (reported line 68)May include surrounding context.

ts
}
async function getVirtualPrice() {
    try {
        const response = await axios_1.default.get('https://api.coingecko.com/api/v3/simple/price?ids=virtual-protocol&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true');
        const data = response.data['virtual-protocol'];
        return {
            price: data.usd,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · dist/cli.js (reported line 110)May include surrounding context.

js
// For now, return placeholder
    try {
        // Try to get from their API if it exists
        const response = await axios_1.default.get('https://api.virtuals.io/agents?limit=10', {
            timeout: 5000,
        }).catch(() => null);
        if (response?.data) {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · src/cli.ts (reported line 88)May include surrounding context.

ts
// For now, return placeholder
    try {
        // Try to get from their API if it exists
        const response = await axios_1.default.get('https://api.virtuals.io/agents?limit=10', {
            timeout: 5000,
        }).catch(() => null);
        if (response?.data) {

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description presents active protocol integration for creating, managing, and trading agents on Base. In code, the create command only prints instructions to use an external website, while no commands perform onchain writes, agent management, or trading transactions; the implemented behavior is limited to price/balance queries and config storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI accepts a private key without presenting a clear upfront warning that the secret will be stored locally and may be exposed if the host is compromised. In a crypto-related skill, users may paste production wallet keys, so missing safety prompts materially raises the risk of inadvertent credential exposure and financial loss.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes an integration that can create, manage, and trade tokenized AI agents on Base. In the code, the create command only checks for a stored private key and then tells the user to use an external website because smart contract integration is 'coming soon', and there are no trading or management commands at all.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The tool accepts a private key on the command line and persists it locally without any explicit warning about the sensitivity of that secret. In a crypto-wallet context this is especially dangerous because CLI arguments may be exposed via shell history, process listings, logs, or copied command transcripts before the key is even written to disk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: follow-redirects==1.15.11 — 1 advisory(ies): CVE-2026-40895 (follow-redirects leaks Custom Authentication Headers to Cross-Domain Redirect Ta)

Low
Category
Supply Chain
Confidence
89% confidence
Finding

follow-redirects 1.15.11 is flagged for leaking custom authentication headers across cross-domain redirects. Because axios depends on this package, any authenticated HTTP request that follows attacker-influenced redirects could expose API keys, bearer tokens, or other sensitive headers to a different origin.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency uses a caret range (^12.1.0), which allows npm to install newer compatible releases rather than a single fixed version. This weakens supply-chain determinism and can unexpectedly pull in a compromised or breaking release during future installs, though by itself it is a common package management practice rather than an immediately exploitable flaw.

Content

Scanner excerpt · package.json (reported line 17)May include surrounding context.

json
"author": "IntechChain",
  "license": "MIT",
  "dependencies": {
    "commander": "^12.1.0",
    "ethers": "^6.9.0",
    "axios": "^1.6.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The ethers dependency is specified with a caret range, so installs may resolve to newer package versions over time. In a blockchain-integrated skill that may handle wallets, transactions, or signing logic, non-deterministic dependency resolution increases supply-chain risk if an upstream release is malicious or unexpectedly insecure.

Content

Scanner excerpt · package.json (reported line 18)May include surrounding context.

json
"license": "MIT",
  "dependencies": {
    "commander": "^12.1.0",
    "ethers": "^6.9.0",
    "axios": "^1.6.0"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The axios dependency is version-ranged with a caret, allowing future installs to pull different releases. Because this skill integrates with external services and likely performs network requests, an unpinned HTTP client increases supply-chain exposure and can also make it easier to inherit vulnerable upstream versions without explicit review.

Content

Scanner excerpt · package.json (reported line 19)May include surrounding context.

json
"dependencies": {
    "commander": "^12.1.0",
    "ethers": "^6.9.0",
    "axios": "^1.6.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
83% confidence
Finding

The @types/node devDependency is also unpinned, which affects build reproducibility. Although devDependencies are generally less dangerous at runtime, compromised or incompatible development tooling can still affect builds, generated artifacts, or developer environments.

Content

Scanner excerpt · package.json (reported line 22)May include surrounding context.

json
"axios": "^1.6.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0"
  }
}

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
dist/cli.js:49

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/cli.ts:13

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
dist/cli.js:270

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/cli.ts:271