Back to skill

Security audit

YieldVault Agent

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed DeFi automation skill, but it needs review because it can run unattended blockchain transactions with wallet keys and includes unsafe contract and key-handling guidance.

Install only for testnet or disposable wallets unless you independently audit the contracts and replace raw private-key handling with a hardware wallet or key vault. Review Telegram contents before enabling alerts, and do not fund or deploy the included YieldVault contracts for real users in their current form.

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

T09 · Insecure Skill Coding Practices

Error
Location
contracts/artifacts/build-info/a5d75f9256251cc8c46c7f853791cdf4.json:1
Finding
Repeatable Harvest Claims Can Drain Vault Underlying Assets## Vulnerability Details **File Location**: `contracts/artifacts/build-info/a5d75f9256251cc8c46c7f853791cdf4.json:1` **Vulnerability Type**: Missing reward-claim accounting and unbacked yield payment **Risk Level**: High The affected Solidity source is embedded in the Hardhat build-information artifact. The artifact is minified onto one line. ```solidity /** * @dev Harvest yields without reinvesting * In a real implementation, this would claim rewards from the underlying protocol */ function harvest() external whenNotPaused returns (uint256 yieldAmount) { require(shareBalance[msg.sender] > 0, "No shares to harvest"); // Stub: calculate yield based on shares and mock APR yieldAmount = calculateUserYield(msg.sender); require(yieldAmount > 0, "No yield available"); // Transfer yield to user (in real implementation, this would come from protocol) require( IERC20(underlying).transfer(msg.sender, yieldAmount), "Yield transfer failed" ); accumulatedYield += yieldAmount; // Emit events emit Harvest(msg.sender, yieldAmount); emit ExecutionRecorded( vaultId, "harvest", msg.sender, yieldAmount, 0, block.timestamp ); emit ActionExecuted( vaultId, "harvest", msg.sender, yieldAmount, true, "Harvest successful" ); return yieldAmount; } /** * @dev Calculate yield for a user (stub: 10% annual, daily accrual) */ function calculateUserYield(address user) public view returns (uint256) { if (shareBalance[user] == 0) { return 0; } uint256 userAssets = calculateAssetsFromShares(shareBalance[user]); // Stub: simple calculation (0.027% daily = ~10% APY) return (userAssets * 27) / 100000; } ``` ### Technical Analysis `calculateUserYield()` derives ...[truncated 2737 chars]
Remediation
## Remediation Suggestions 1. Replace the fixed per-call calculation with cumulative reward-index accounting: - Maintain a global reward-per-share accumulator. - Record each user's reward debt or last observed index. - Calculate only rewards accrued since the previous checkpoint. - Update the checkpoint before transferring tokens. 2. Base distributable rewards on realized assets: - Claim rewards from the underlying protocol first. - Measure the actual token balance increase. - Credit only the verified increase to a reward reserve. - Never pay nominal rewards directly from depositor principal. 3. Keep accounting synchronized: - If assets leave the vault, update the corresponding asset or reward-reserve accounting atomically. - Require the actual underlying balance to cover all accounted liabilities. - Add explicit solvency checks around harvest and withdrawal operations. 4. Apply checks-effects-interactions: - Consume the user's accrued reward and update accounting before the external token transfer. - Add a reentrancy guard to all state-changing functions that transfer tokens. 5. Use a safe ERC-20 transfer library, such as OpenZeppelin `SafeERC20`, to support tokens that do not return standard Boolean values. 6. Add invariant and adversarial tests proving that: - A second harvest without new accrual returns zero. - Repeated harvest calls cannot reduce depositor principal. - The actual token balance remains sufficient to satisfy accounted assets. - Total successful claims cannot exceed realized rewards. - Multiple users receive only their proportional accrued rewards. 7. Treat the current contract as a non-production stub and prevent deployment or funding until the reward model receives an independent smart-contract audit.

T09 · Insecure Skill Coding Practices

Error
Location
contracts/artifacts/build-info/a5d75f9256251cc8c46c7f853791cdf4.json:1
Finding
Compound Function Mints Unbacked Shares and Inflates Vault Assets## Vulnerability Details **File Location**: `contracts/artifacts/build-info/a5d75f9256251cc8c46c7f853791cdf4.json:1` **Vulnerability Type**: Unbacked asset accounting and unrestricted repeat compounding **Risk Level**: High The affected Solidity source is embedded in the minified Hardhat build-information artifact. ```solidity /** * @dev Compound yields by reinvesting them as new shares */ function compound() external whenNotPaused returns (uint256 newShares) { require(shareBalance[msg.sender] > 0, "No shares to compound"); // Calculate compounding yield uint256 yieldAmount = calculateUserYield(msg.sender); require(yieldAmount > 0, "No yield to compound"); // Calculate new shares from yield newShares = calculateSharesFromAssets(yieldAmount); // Update state shareBalance[msg.sender] += newShares; totalShares += newShares; totalAssets += yieldAmount; accumulatedYield += yieldAmount; // Emit events emit Compound(yieldAmount, newShares); emit ExecutionRecorded( vaultId, "compound", msg.sender, yieldAmount, newShares, block.timestamp ); emit ActionExecuted( vaultId, "compound", msg.sender, yieldAmount, true, "Compound successful" ); return newShares; } /** * @dev Convert assets to shares (simple stub: 1 asset = 1 share initially) */ function calculateSharesFromAssets(uint256 assets) public view returns (uint256) { if (totalAssets == 0 || totalShares == 0) { return assets; } return (assets * totalShares) / totalAssets; } /** * @dev Calculate yield for a user (stub: 10% annual, daily accrual) */ function calculateUserYield(address user) public view returns (uint256) { if (shareBalance[user] == 0) { return 0; } uint2 ...[truncated 2977 chars]
Remediation
## Remediation Suggestions 1. Require realized yield before minting shares: - Claim rewards from the underlying strategy. - Record the vault's underlying-token balance before and after the claim. - Treat only the verified positive balance delta as compoundable yield. - Revert if no new assets were received. 2. Use reward checkpoints: - Maintain a per-user reward index or reward debt. - Consume accrued rewards before minting new shares. - Prevent repeated calls from reusing the same accrual period. 3. Correct share issuance: - Mint shares only against assets actually added to the vault. - Use a well-reviewed ERC-4626-style conversion model where appropriate. - Define and test rounding behavior so that share issuance cannot favor callers at depositor expense. 4. Enforce solvency invariants: - Ensure accounted assets never exceed assets actually controlled by the vault, except for explicitly documented and safely valued receivables. - Validate the invariant after deposit, withdrawal, harvest, and compound operations. - Add circuit breakers that pause the vault if accounting and token balances diverge. 5. Separate principal from rewards: - Maintain explicit accounting for depositor principal and realized strategy rewards. - Do not increase `totalAssets` based solely on a mathematical APR estimate. 6. Add adversarial and invariant tests covering: - Repeated same-block and same-period compound calls. - Compound calls without newly received rewards. - Compound followed immediately by withdrawal. - Multiple users with different deposit times. - Equality between asset-accounting changes and actual token-balance changes. - Preservation of each depositor's proportional ownership. 7. Have the corrected accounting model independently audited before any mainnet deployment or user funding.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (112)

Credential Access

High
Category
Privilege Escalation
Content
cat > .gitignore << 'EOF'
node_modules/
.env
.env.local
*.log
.DS_Store
dist/
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
cat > .gitignore << 'EOF'
node_modules/
.env
.env.local
*.log
.DS_Store
dist/
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This variant identifies undeclared outbound Telegram notifications and local log persistence, which are materially relevant behaviors for a financial automation skill. Sending execution details to third-party services without clear disclosure can leak strategy, balances, or operational metadata, especially dangerous in an autonomous on-chain context.

Credential Access

High
Category
Privilege Escalation
Content
### 1. Configure

```bash
cp config.deployed.json .env.local
# Edit with your contract addresses and RPC endpoint
```
Confidence
80% confidence
Finding
The setup instructions direct users to create a .env.local file for runtime configuration, which strongly implies secret handling, but the skill does not pair this with secure credential-handling guidance. In an autonomous blockchain agent, mishandled environment secrets such as private keys, RPC credentials, or bot tokens could lead to wallet compromise, unauthorized transactions, or account abuse.

Ae1

High
Category
analysis-evasion
Content
- `SKILL.md` - This file
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
```bash
nano .env
# or
vim .env
```

**Fill in:**
Confidence
96% confidence
Finding
This section explicitly instructs users to place a raw blockchain private key into a plaintext `.env` file. In an autonomous agent or developer workstation context, plaintext hot-wallet storage materially increases the chance of theft through logs, shell history, backups, malware, accidental commits, or other local compromise.

Credential Access

High
Category
Privilege Escalation
Content
#### 1. **"PRIVATE_KEY is not set"**

```bash
# Ensure .env file exists and has PRIVATE_KEY
cat .env | grep PRIVATE_KEY

# Should output: PRIVATE_KEY=1234567890...
Confidence
97% confidence
Finding
The troubleshooting command `cat .env | grep PRIVATE_KEY` encourages printing the presence and potentially the contents of a secret-bearing file directly to the terminal. In many environments terminal output is logged, persisted, screen-shared, or captured by agent tooling, making secret exposure more likely.

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Ensure .env file exists and has PRIVATE_KEY
cat .env | grep PRIVATE_KEY

# Should output: PRIVATE_KEY=1234567890...
```
Confidence
98% confidence
Finding
The example output `PRIVATE_KEY=1234567890...` normalizes displaying secret material in terminal output, which is especially unsafe in agent, CI, or shared support contexts. Even partial key disclosure patterns can train users into unsafe troubleshooting behavior and increase accidental exposure risk.

Credential Access

High
Category
Privilege Escalation
Content
cd /home/ubuntu/.openclaw/workspace/skills/yield-farming-agent/contracts

# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
cd /home/ubuntu/.openclaw/workspace/skills/yield-farming-agent/contracts

# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
cd /home/ubuntu/.openclaw/workspace/skills/yield-farming-agent/contracts

# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
#   PRIVATE_KEY=...        (private key without 0x prefix)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
#   PRIVATE_KEY=...        (private key without 0x prefix)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
#   PRIVATE_KEY=...        (private key without 0x prefix)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
#   PRIVATE_KEY=...        (private key without 0x prefix)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Copy environment file
cp .env.example .env

# Edit .env with your values:
#   DEPLOYER_ADDRESS=0x... (your wallet address)
#   PRIVATE_KEY=...        (private key without 0x prefix)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.