Back to skill

Security audit

Stakingverse Ethereum

Security checks for vulnerabilities and agentic risk

Overview

This skill appears aimed at StakeWise staking, but it can submit real Ethereum mainnet transactions using a raw private key without adequate confirmation, validation, or safety warnings.

Review this carefully before installing. Use only a dedicated low-balance wallet, verify the vault, chain, amount, and receiver before every run, and avoid placing a valuable raw private key in the environment. Treat the staking command as a live Ethereum mainnet transaction that can spend funds and incur gas immediately.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/stake.mjs:96
Finding
Unvalidated Receiver Can Redirect Staking Assets<![CDATA[ ## Vulnerability Details **File Location**: `scripts/stake.mjs`, lines 5-6, 68-69, and 96-101 **Vulnerability Type**: Unvalidated asset receiver configuration **Risk Level**: High ### Vulnerable Code ```javascript const PRIVATE_KEY = process.env.ETH_PRIVATE_KEY || 'YOUR_PRIVATE_KEY'; const MY_ADDRESS = process.env.MY_ADDRESS || 'YOUR_ADDRESS'; // ... const provider = new ethers.JsonRpcProvider(RPC_URL); const wallet = new ethers.Wallet(PRIVATE_KEY, provider); // ... const tx = await vault.updateStateAndDeposit( MY_ADDRESS, deadline, harvestParams, { value: amountWei } ); ``` ### Technical Analysis The ETH used for staking is supplied and signed by the wallet derived from `ETH_PRIVATE_KEY`, while the receiver of the resulting staking position is independently supplied through `MY_ADDRESS`. The script does not: - Verify that `MY_ADDRESS` is a valid checksummed Ethereum address. - Bind the receiver to `wallet.address`. - Warn when the receiver differs from the signing wallet. - Require explicit confirmation before transferring value to a third-party receiver. Consequently, a poisoned, stale, or mistyped `MY_ADDRESS` can cause the signer to fund a staking transaction whose resulting assets are assigned to another address. This violates the principle of secure transaction construction for an operation involving irreversible transfers. ### Attack Path 1. An attacker modifies `MY_ADDRESS` in the victim's environment, shell profile, deployment configuration, or execution wrapper. 2. The victim retains control of their legitimate `ETH_PRIVATE_KEY`. 3. The victim runs the documented command, such as `node scripts/stake.mjs 0.1`. 4. The script constructs a transaction funded and signed by the victim's wallet. 5. `updateStateAndDeposit` receives the attacker-controlled `MY_ADDRESS` as the receiver. 6. The staking output is assigned to the unintended address, potentially making recovery impossible. The same outcome can occur without an attac ...[truncated 493 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use the signing wallet as the default and preferred receiver: ```javascript const receiver = wallet.address; ``` 2. If third-party receivers are required, make that behavior explicit rather than relying on a general environment variable: ```javascript const receiver = process.env.STAKE_RECEIVER ? ethers.getAddress(process.env.STAKE_RECEIVER) : wallet.address; ``` 3. Require an explicit command-line option such as `--allow-third-party-receiver` whenever `receiver !== wallet.address`. 4. Before signing, display and confirm: - Ethereum chain ID - Signing wallet - Receiver - Vault contract - ETH amount - Estimated gas cost 5. Validate the active network and contract configuration: ```javascript const network = await provider.getNetwork(); if (network.chainId !== 1n) { throw new Error(`Unexpected chain ID: ${network.chainId}`); } ``` 6. Abort if the receiver is the zero address, malformed, or unexpectedly differs from the signer. 7. Prefer hardware-wallet or external-signer integration so raw private keys do not need to be placed in process environment variables. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:8
Finding
Unpinned Wallet Runtime Dependency<![CDATA[ ## Vulnerability Details **File Location**: `README.md`, lines 8-11 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash git clone https://github.com/LUKSOAgent/stakingverse-ethereum-skill.git cd stakingverse-ethereum-skill npm install ethers ``` ### Technical Analysis The installation instructions install the currently resolved version of `ethers` without a project manifest specifying an audited version and without a committed lockfile. The reviewed project structure contains no `package.json` or package lockfile. As a result: - Installations are not reproducible. - Future users may execute a dependency version that was never reviewed with this skill. - Breaking or security-relevant dependency changes can alter transaction construction and signing behavior. - A future upstream package or distribution compromise would execute in a process that handles `ETH_PRIVATE_KEY`. No evidence was found that the current `ethers` package is malicious. The vulnerability is the unsafe, unpinned dependency workflow in a security-sensitive wallet application. ### Attack Path 1. A future upstream release or package-distribution event introduces malicious or compromised code into the dependency resolved as `ethers`. 2. A user follows the README and runs `npm install ethers`. 3. npm installs the then-current dependency and its transitive dependency graph without enforcing a previously audited lockfile. 4. The user runs `scripts/stake.mjs`. 5. The imported dependency executes in the same Node.js process that reads `ETH_PRIVATE_KEY` and signs transactions. 6. Malicious dependency code could read process environment data, alter transaction parameters, or transmit secrets over the network. This path depends on a future supply-chain compromise or unsafe upstream change; the audit did not identify an existing malicious dependency payload. ### Impact Assessment A compromised runtime dependency would ...[truncated 517 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a `package.json` that pins an exact, reviewed `ethers` version rather than using a floating installation command. 2. Generate and commit a lockfile, such as `package-lock.json`, to fix the complete transitive dependency graph. 3. Replace the documented installation command with: ```bash npm ci ``` 4. Review dependency and lockfile changes before accepting automated upgrades. 5. Use automated vulnerability and provenance checks, including: ```bash npm audit npm ls ``` 6. Consider dependency update tooling that opens reviewable pull requests instead of silently resolving the latest release during installation. 7. Document the expected Node.js and npm versions to improve reproducibility. 8. For a workflow that controls financial assets, test dependency upgrades against fixed transaction vectors and verify signer, receiver, chain ID, contract address, and transaction value before release. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description presents a broader StakeWise staking skill with stake, unstake, position checking, and state update support. The supplied code chunk is strictly a read-only position checker: it uses ethers to call balanceOf, convertToAssets, and totalAssets on a hardcoded vault, using an address from environment variables. There are no write transactions, no stake/unstake methods, no signer usage beyond unused private key configuration, and no subgraph, keeper, or harvest proof logic. This is a material description-to-behavior mismatch because the implemented primary behavior is only one subset of the declared functionality.

Missing User Warnings

High
Confidence
97% confidence
Finding
The script submits an irreversible on-chain staking transaction immediately after computing parameters, with no human confirmation, simulation, or transaction summary. In a staking skill that moves real ETH, this is especially dangerous because a mistaken amount, wrong receiver address, stale subgraph data, or malicious invocation can cause immediate and non-recoverable fund commitment.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README instructs users to export a raw Ethereum private key into an environment variable without any warning about secret handling, shell history, process exposure, or safer alternatives. In a skill that directly manages on-chain funds, this increases the chance of credential leakage and wallet compromise, which could result in total loss of assets.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The staking command is presented like a routine script invocation but does not explicitly warn that it will submit a live Ethereum mainnet transaction using the user's wallet and funds. In the context of a staking skill, this omission is dangerous because users may run the command without understanding that it can irreversibly transfer ETH, incur gas costs, and interact with protocol state fetched from external infrastructure.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill documents access to sensitive environment variables, including a raw private key, but does not declare any explicit tool scope or permission boundary. In an agent setting, missing scope metadata weakens reviewability and increases the chance the skill is invoked with broader access than users expect.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The documentation tells users to export a raw PRIVATE_KEY directly into the environment without explaining the sensitivity of that secret or safer alternatives. This increases the risk of credential theft through shell history, process inspection, logs, shared environments, or accidental disclosure to other tools in the agent runtime.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs users to run staking and unstaking commands that can submit irreversible on-chain transactions spending ETH or burning osETH, but it omits a clear warning about financial risk, finality, gas costs, and recipient/address validation. In an agent or automation context, users may execute these commands without appreciating that real funds will be moved immediately.

External Transmission

Medium
Category
Data Exfiltration
Content
}
  };

  const response = await fetch('https://graphs.stakewise.io/mainnet-a/subgraphs/name/stakewise/prod', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subgraphQuery)
Confidence
60% 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
}
  };

  const response = await fetch('https://graphs.stakewise.io/mainnet-a/subgraphs/name/stakewise/prod', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subgraphQuery)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script directly consumes a private key from the environment and constructs a signing wallet without any explicit safety notice, secure key handling guidance, or protective controls. In an agent skill context that performs financial actions, this increases the chance that users supply hot-wallet credentials to automation they may not fully understand, leading to accidental exposure or misuse of signing authority.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes a broader skill scope including unstaking ETH and checking staked positions on StakeWise V3 vaults. In this file, the only implemented operation is stakeETH, which performs a deposit transaction; there is no code for withdrawal/unstake flows or for querying and returning position data beyond an internal state-update check.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The inline comment states 'Simple deposit if no state update needed' and the log says 'using simple deposit', which communicates that the branch performs a deposit flow. In reality, the branch is unimplemented and immediately throws an error claiming state update is always required, directly contradicting the documented intent of that block.

Static analysis

No suspicious patterns detected.