Back to skill

Security audit

Morpho Earn - earn safe yield on your USDC on Base

Security checks across malware telemetry and agentic risk

Overview

This DeFi skill appears purpose-built rather than malicious, but it needs review because it can use a wallet key to perform real on-chain transactions and can add future auto-compounding instructions.

Install only if you are comfortable giving this skill signing access to a dedicated, low-balance hot wallet. Do not use a main wallet. Disable auto-compound unless you explicitly want future agent-driven transactions, review any HEARTBEAT.md changes after setup, and inspect/confirm every claim, approval, swap, deposit, and withdrawal before relying on automation.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (28)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill documents and instructs use of capabilities that touch environment variables, networked RPC/API access, and shell execution (`npm install`, `npx tsx ...`) while declaring no permissions. That mismatch undermines least-privilege controls and can cause an agent or reviewer to authorize a skill without understanding its real execution and data-access surface, which is especially risky because the skill handles wallet credentials and on-chain funds.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The documentation advertises reward-claiming and auto-compounding capabilities that go beyond the skill metadata's stated scope. In an agentic setting, scope mismatches are dangerous because they can cause an orchestrator or user to authorize actions involving additional transactions, token handling, and protocol interactions they did not expect.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
Swapping reward tokens through Odos materially broadens the trust and risk surface beyond simple USDC vault deposit/withdraw operations. This introduces third-party routing, token swaps, slippage, and approval risks that a user or calling agent may not anticipate from the manifest, making unauthorized or insufficiently explained asset conversions more likely.

Intent-Code Divergence

Low
Confidence
86% confidence
Finding
The file states that transaction previews should always be shown, but the documented execution flows present direct deposit, compound, and withdraw commands without a preview step. For a real-funds DeFi skill, that inconsistency can lead agents or users to execute irreversible on-chain actions without reviewing destination, amount, approvals, swap route, or slippage assumptions.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest description says the skill is for depositing, withdrawing, checking position/APY, and wallet setup, but the body also advertises rewards claiming and token swapping through an aggregator. Those omitted capabilities are materially more sensitive because they enable additional token movements and interaction with third-party routing logic, so users and security systems may underestimate the operational and financial risk.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The security section states that keys are never written to disk, yet the setup and config examples explicitly support a private key file path and say the wizard configures wallet storage from a file. This contradiction can mislead users into weaker key-handling choices under false assurances, increasing the chance of credential theft and direct loss of funds from a hot wallet used for DeFi transactions.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The script explicitly performs reward claiming and token swaps, which exceeds the skill’s stated scope of depositing, withdrawing, checking position/APY, and setting wallet credentials. Expanding a DeFi skill from simple vault interaction into autonomous trading materially increases authority and risk, especially because it can move and convert wallet-held assets the user may not expect to be touched.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The code enumerates wallet token balances, approves an external router, and executes swaps for any detected reward-token balances. In the context of a vault-focused USDC yield skill, this is an unjustified asset-conversion capability that can unexpectedly trade user-held tokens and grant spending approvals to a third-party router based on off-chain API output.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The setup script offers to modify a local HEARTBEAT.md control/automation file and injects instructions for recurring monitoring and optional auto-compounding. That expands the skill's behavior beyond simple wallet/yield setup into persistence-like agent task configuration, which can influence future automated actions and create a larger attack surface if the skill is installed or trusted without careful review.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Writing into HEARTBEAT.md is unrelated to the core function of depositing/withdrawing/checking yield positions and introduces coupling to a local agent control surface. In the skill context, this is more dangerous because the added content can shape future autonomous behavior, including running report and compound commands on a schedule, which may lead to unintended financial actions.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
This test script performs asset swaps from USDC into WELL and MORPHO, which materially expands the skill's behavior beyond the declared USDC vault deposit/withdraw/APY scope. In an agent skill context, scope drift is dangerous because users or orchestrators may trust the manifest and unintentionally authorize trading activity that introduces market, routing, and approval risk unrelated to the advertised function.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The code depends on an external DEX aggregator API to construct swap transactions and then signs/broadcasts the returned calldata with minimal validation of what the assembled transaction actually does. This creates a dangerous trust boundary: a compromised, spoofed, or malfunctioning API could return transaction data that transfers assets in unintended ways, especially since the script also grants token approval to the router.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The setup instructions tell users to place a raw private key in a file and export it in the shell environment, but they do not warn that `echo "0xYOUR_PRIVATE_KEY" > file` can leak secrets through shell history and that both file- and env-based secrets may be exposed via backups, process inspection, logs, or misconfigured home-directory permissions. In a DeFi wallet context, exposure of a private key directly enables theft of all wallet funds and takeover of on-chain actions, so the omission materially increases operational secret-handling risk.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The script calls third-party pricing infrastructure and, per the finding, does so without user-facing disclosure of the privacy implications. In a DeFi wallet-reporting skill, undisclosed external lookups can leak metadata such as IP address, usage timing, and correlation with wallet-monitoring behavior to outside services, which is a real privacy concern even if the wallet address is not explicitly embedded in the URL shown here.

External Transmission

Medium
Category
Data Exfiltration
Content
tokenOut: Address,
  userAddress: Address
): Promise<OdosQuoteResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/quote/v2', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
89% confidence
Finding
Fetch('https://api.odos.xyz/sor/quote/v2', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
pathId: string,
  userAddress: Address
): Promise<OdosAssembleResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
95% confidence
Finding
Fetch('https://api.odos.xyz/sor/assemble', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
tokenOut: Address,
  userAddress: Address
): Promise<OdosQuoteResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/quote/v2', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
89% confidence
Finding
https://api.odos.xyz/

External Transmission

Medium
Category
Data Exfiltration
Content
pathId: string,
  userAddress: Address
): Promise<OdosAssembleResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
95% confidence
Finding
https://api.odos.xyz/

External Transmission

Medium
Category
Data Exfiltration
Content
*/
export async function fetchVaultAPY(): Promise<number> {
  try {
    const response = await rateLimitedFetch('https://blue-api.morpho.org/graphql', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
Confidence
83% confidence
Finding
Fetch('https://blue-api.morpho.org/graphql', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
try {
    const res = await rateLimitedFetch(
      `https://api.coingecko.com/api/v3/simple/price?ids=${id}&vs_currencies=usd`
    );
    
    if (!res.ok) return 0;
Confidence
94% confidence
Finding
https://api.coingecko.com/

External Transmission

Medium
Category
Data Exfiltration
Content
}

async function fetchRewards(userAddress: string): Promise<TokenReward[]> {
  const url = `https://api.merkl.xyz/v4/users/${userAddress}/rewards?chainId=${BASE_CHAIN_ID}`;
  
  const response = await fetch(url);
  if (!response.ok) {
Confidence
77% confidence
Finding
https://api.merkl.xyz/

External Transmission

Medium
Category
Data Exfiltration
Content
tokenOut: Address,
  userAddress: Address
): Promise<OdosQuoteResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/quote/v2', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
79% confidence
Finding
Fetch('https://api.odos.xyz/sor/quote/v2', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
pathId: string,
  userAddress: Address
): Promise<OdosAssembleResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
87% confidence
Finding
Fetch('https://api.odos.xyz/sor/assemble', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
tokenOut: Address,
  userAddress: Address
): Promise<OdosQuoteResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/quote/v2', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
79% confidence
Finding
https://api.odos.xyz/

External Transmission

Medium
Category
Data Exfiltration
Content
pathId: string,
  userAddress: Address
): Promise<OdosAssembleResponse | null> {
  const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
Confidence
87% confidence
Finding
https://api.odos.xyz/

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/config.ts:305

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/config.ts:197