Back to skill

Security audit

Stakingverse Lukso

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real LUKSO staking helper, but it asks for a wallet/controller private key and can send mainnet transactions without enough guardrails or secret-handling warnings.

Review this skill before installing or running it with real funds. Use a dedicated low-value, least-privileged controller key if possible; do not paste private keys into scripts, repositories, shell history, logs, or shared automation. Verify the LUKSO mainnet, Universal Profile, Key Manager, vault address, and amount before every run, and expect gas costs and irreversible on-chain effects. Be aware that the unstake and claim scripts appear to have ABI defects, and SKILL.md references a check-claim.js file that is not present.

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

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:28
Finding
Unsafe Private-Key Configuration Guidance## Vulnerability Details **File Location**: `SKILL.md:28-35` **Vulnerability Type**: Plaintext secret exposure through insecure configuration guidance **Risk Level**: Medium ### Vulnerable Code ```bash Set these environment variables or edit the scripts: export STAKINGVERSE_VAULT="0x9F49a95b0c3c9e2A6c77a16C177928294c0F6F04" export MY_UP="your_universal_profile_address" export CONTROLLER="your_controller_address" export PRIVATE_KEY="your_controller_private_key" export RPC_URL="https://rpc.mainnet.lukso.network" ``` ### Technical Analysis The documentation explicitly permits users to edit the scripts to provide configuration values, including the controller's private key. Embedding a private key in source code places a high-value credential in a file that may subsequently be committed to version control, copied into archives, uploaded for support, cached by development tools, or distributed with the skill. The scripts use this credential to instantiate an `ethers.Wallet` capable of signing blockchain transactions. Consequently, disclosure is not limited to account identification: it exposes all transaction authority granted to that controller. The environment-variable alternative is safer than source embedding but still leaves the key accessible to the process and potentially to process inspection, crash diagnostics, or insecure shell history. The documentation does not recommend a secret manager, hardware-backed signer, or restricted credential lifecycle. ### Attack Path 1. A user follows the instruction allowing configuration values to be inserted directly into the scripts. 2. The user places the controller private key in a project file. 3. The modified project is committed, archived, uploaded, shared, or otherwise exposed. 4. An attacker retrieves the plaintext private key. 5. The attacker imports the key into a wallet or signing program. 6. The attacker submits any transaction permitted by that controller, ...[truncated 483 chars]
Remediation
## Remediation Suggestions - Remove the phrase permitting users to edit scripts with configuration values. - Explicitly prohibit storing private keys in source files, repositories, shell history, logs, or project archives. - Use a dedicated secret manager, encrypted keystore, hardware wallet, or external signing service. - If environment variables must be supported, document their residual exposure risks and recommend short-lived, least-privileged controller keys. - Validate that the controller has only the minimum permissions required for staking, withdrawal, and claim operations. - Add secret-scanning controls such as pre-commit hooks and CI checks. - Document an immediate key-revocation and rotation procedure for accidental exposure.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/stake.js:35
Finding
Unvalidated Transaction Destination Derived from Profile Storage## Vulnerability Details **File Location**: `scripts/stake.js:35-58` **Vulnerability Type**: Untrusted address resolution for a value-bearing blockchain transaction **Risk Level**: Medium ### Vulnerable Code ```javascript const provider = new ethers.JsonRpcProvider(RPC_URL); const wallet = new ethers.Wallet(PRIVATE_KEY, provider); // Get Key Manager address const up = new ethers.Contract(MY_UP, UP_ABI, provider); const keyManagerBytes = await up.getData('0xdf30dba06db6ede4cd4a817e2b67b0eb0e9e6e8c2e5a5b6e5d6c7e8f9a0b1c2d'); // LSP6KEY_KEYMANAGER_INTERNAL const keyManager = '0x' + keyManagerBytes.slice(26, 66); console.log('Key Manager:', keyManager); // Encode deposit call const vaultInterface = new ethers.Interface(VAULT_ABI); const depositData = vaultInterface.encodeFunctionData('deposit', [MY_UP]); // Encode UP.execute const amountWei = ethers.parseEther(amountLYX.toString()); const upInterface = new ethers.Interface(UP_ABI); const upExecuteData = upInterface.encodeFunctionData('execute', [ 0, // CALL STAKINGVERSE_VAULT, amountWei, depositData ]); console.log('Sending transaction...'); const keyManagerContract = new ethers.Contract(keyManager, KEY_MANAGER_ABI, wallet); const tx = await keyManagerContract.execute(upExecuteData, { value: amountWei }); ``` The same unchecked extraction pattern also appears in: - `scripts/unstake-request.js:29-31,52-53` - `scripts/claim.js:43-45,66-67` Those two scripts currently contain a separate reliability defect because their `UP_ABI` declarations omit `getData`, so they are expected to fail before reaching the transaction. The immediately exploitable value-bearing path is in `scripts/stake.js`. ### Technical Analysis The script accepts `MY_UP` from the environment and queries that address for an alleged Key Manager storage value. It then slices bytes at fixed offsets and treats the result as the destination of a signed transa ...[truncated 1935 chars]
Remediation
## Remediation Suggestions - Validate `MY_UP` with `ethers.isAddress` and reject the zero address. - Query and enforce the expected LUKSO Mainnet chain ID before resolving addresses or signing transactions. - Use the canonical LSP6 storage key and decoding procedure from a reviewed library rather than manually slicing unvalidated bytes. - Require the returned value to have the exact expected length and encoding. - Verify that bytecode exists at both the profile and resolved Key Manager addresses. - Verify the relationship between the Universal Profile, Key Manager, and configured controller using canonical interface and ownership checks. - Display the network, profile, Key Manager, vault, method, and value before signing. - Require explicit user confirmation for every value-bearing transaction. - Consider allowing users to configure an independently verified Key Manager address and compare it against the on-chain result. - Add balance and amount validation, including rejection of zero, negative, non-finite, malformed, or unexpectedly large values. - Add `getData(bytes32)` to the `UP_ABI` declarations in the withdrawal and claim scripts, then apply the same validation controls there before making those paths operational.

T08 · Insecure Dependencies

Note
Location
README.md:8
Finding
Unpinned Wallet Runtime Dependency## Vulnerability Details **File Location**: `README.md:8-12` **Vulnerability Type**: Unpinned third-party dependency in a private-key signing workflow **Risk Level**: Low ### Vulnerable Code ```bash git clone https://github.com/LUKSOAgent/stakingverse-lukso-skill.git cd stakingverse-lukso-skill npm install ethers ``` ### Technical Analysis The installation instructions install `ethers` without a version constraint. The audited project structure also contains no `package.json` or lockfile that records an exact dependency version and integrity metadata. As a result, the package code installed and executed by a future user is not uniquely determined by the audited repository. A later release may introduce incompatible behavior, a compromised registry account could publish malicious code, or dependency resolution could otherwise produce code that was never reviewed. This is particularly sensitive because `ethers` runs in the same Node.js process as the scripts and therefore has access to the environment, including `STAKING_PRIVATE_KEY`. It also participates directly in wallet construction, RPC communication, transaction encoding, and signing. ### Attack Path 1. A user follows the documented installation command at a later date. 2. npm resolves the then-current `ethers` release and its transitive dependency graph. 3. The resolved package differs from the version assumed during the audit or has been compromised. 4. The user runs a staking, withdrawal, claim, or balance script. 5. The dependency executes in the same process and can access environment variables and transaction data. 6. Malicious package code could exfiltrate the private key, alter transaction destinations or amounts, or sign unintended transactions. No malicious dependency is present in the supplied project evidence; this finding concerns the absence of reproducible and integrity-controlled dependency resolution. ### Impact Assessment If dependenc ...[truncated 367 chars]
Remediation
## Remediation Suggestions - Add and commit a `package.json` containing an exact reviewed `ethers` version. - Generate and commit a package lockfile with integrity hashes. - Replace `npm install ethers` with `npm ci` in the documented installation process. - Review dependency changes before updating the lockfile. - Run dependency vulnerability and provenance checks in CI. - Use trusted registries and enforce lockfile integrity. - Avoid broad npm lifecycle-script execution where it is not required. - Prefer hardware-backed or external signing so third-party JavaScript dependencies do not receive raw private-key material.
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 (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a broader staking skill covering stake, unstake, claiming rewards, and balance checks on Stakingverse. The supplied code chunk implements only one operational path: deposit/stake LYX into the Stakingverse vault using UP.execute through a Key Manager, then query balanceOf for the configured UP. There is no callable function or CLI path for withdraw, claim, claimable checking, withdrawal requests, or any oracle-based claim flow. The accessed resource (Stakingverse vault on Lukso mainnet) is consistent with the description, so the mismatch is not about destination or permissions, but about overstating supported capabilities relative to the actual code.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README instructs users to export a controller private key directly into an environment variable but provides no warning about secret handling, shell history exposure, process inspection, or safer alternatives. Because this skill is specifically used to control a LUKSO Universal Profile and sign staking transactions, compromise of that key could enable unauthorized on-chain actions and loss of funds.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The README tells users how to stake, request unstake, and claim assets, but does not clearly warn that these are real on-chain transactions involving wallet authority, gas costs, timing delays, token burns during withdrawal requests, and possible irreversible mistakes from wrong amounts or wrong network use. In a staking skill, omission of transaction-risk warnings is more dangerous because the documented commands directly affect user funds and operational custody.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill contains code and instructions that rely on sensitive environment variables, including a private key and on-chain target addresses, but it declares no explicit tool scope or permissions boundary. In an agent setting, missing scope metadata can cause the runtime or reviewer to underestimate that the skill can access secrets and initiate blockchain transactions, increasing the chance of unsafe invocation or overbroad execution context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs users to place a controller private key in an environment variable without any warning about secret handling, storage, shell history, process inspection, CI logs, or using safer signing methods. Because this key can authorize KeyManager calls and move staking-related assets, accidental exposure could let an attacker stake, unstake, redirect claims, or otherwise control the user's Universal Profile actions.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script directly consumes a raw private key from an environment variable and then uses it to submit on-chain transactions, but provides no guardrails, warnings, or safer credential-handling pattern. In an agent skill context, this is more dangerous because users may run the skill in automated environments where secrets are broadly exposed to logs, subprocesses, or misconfiguration, increasing the risk of wallet compromise and unauthorized staking-related transactions.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
At L41 the comment says 'Get Key Manager', and L42 instantiates the contract with an ABI containing only execute(). However, L43 calls up.getData(...), which is not present in the declared ABI. This is an intent-code contradiction in the inline documentation/context because the code as written does not actually match the documented retrieval approach.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The script directly loads a signing key from `STAKING_PRIVATE_KEY` and uses it to submit an on-chain transaction, but provides no explicit safeguard, confirmation step, or warning that the operator is exposing a high-value key to an automation script. In a staking skill that interacts with a Universal Profile/Key Manager flow, misuse of the configured key or running the script in an unsafe environment could lead to unauthorized unstake requests or broader account compromise if the key has elevated permissions.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The script describes and implements an unstake request on Stakingverse, but its declared UP_ABI only includes execute(...) while the code later invokes up.getData(...) at L30. This is a direct mismatch between the code's stated contract interface/documented behavior and the operations it actually performs, indicating the file does not accurately represent what is needed for its advertised flow.

Static analysis

No suspicious patterns detected.