Back to skill

Security audit

Gekko Yield

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its DeFi yield purpose, but its auto-compound command can sign third-party-built swap transactions and deposit all wallet USDC without clear confirmation.

Review this before installing or running it with real funds. Use only a dedicated hot wallet with limited balances, be aware that auto-compound relies on Odos and can move all USDC in that wallet into the vault, and avoid running compound.ts unless you have independently reviewed the assembled transaction and intended deposit amount.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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

Error
Location
scripts/compound.ts:166
Finding

External Odos API response is signed without destination or calldata validation

Content
View full analysis
{ const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userAddr: userAddress, pathId, simulate: false, }), }); if (!response.ok) return null; const data = await response.json() as OdosAssembleResponse; if (!data.transaction?.to || !data.transaction?.data) return null; return data; } ``` ```ts console.log(` Executing swap...`); const gasEstimate = BigInt(assembled.transaction.gas); const gasWithBuffer = gasEstimate + (gasEstimate * 50n / 100n); const nonce = await getFreshNonce(publicClient, account.address); try { const swapHash = await walletClient.sendTransaction({ to: assembled.transaction.to as Address, data: assembled.transaction.data as Hex, value: BigInt(assembled.transaction.value), gas: gasWithBuffer, nonce, }); const receipt = await waitForTransaction(publicClient, swapHash); if (receipt.status === 'success') { console.log(` ✅ Swapped! Tx: ${swapHash}\n`); } else { console.log(` ❌ Swap reverted\n`); } } catch (err) { console.log(` ❌ Swap failed\n`); } ``` ### Technical Analysis The Odos assemble endpoint controls the transaction destination, calldata, native token value, and gas estimate. The response validation only confirms that `transaction.to` and `transaction.data` are present. The implementation does not: - Require the destination to equal the hard-coded `ODOS_ROUTER`. - Decode and validate the calldata. - Verify the input token, output token, amount, recipient, or minimum output. - Restrict the native ETH value. ...[truncated 2111 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/compound.ts:201
Finding

Auto-compound deposits the wallet's entire USDC balance instead of only swap proceeds

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Note
Location
scripts/config.ts:621
Finding

Read-only status and reporting commands unnecessarily load the private key

Content
View full analysis
{ const config = loadConfig(); const { publicClient, account } = getClients(config); ``` ```ts // scripts/config.ts export function getClients(config: Config) { const privateKey = getPrivateKey(config); const account = privateKeyToAccount(privateKey); const rpcUrl = config.rpc || 'https://mainnet.base.org'; const transport = createRetryTransport(rpcUrl); const publicClient = createPublicClient({ chain: base, transport, }); const walletClient = createWalletClient({ account, chain: base, transport, }); return { publicClient, walletClient, account }; } ``` ### Technical Analysis Both `status.ts` and `report.ts` perform only public blockchain reads and external public-data requests. Nevertheless, both call `getClients`, which: 1. Reads the configured private key from an environment variable. 2. Converts it into a signing account. 3. Creates a wallet client capable of signing transactions. These commands need only a public wallet address and a public RPC client. Loading the private key and creating a signing client provides no functional benefit for status or report generation and violates the principle of least privilege. The audit found no evidence that the key is logged, written to disk, or intentionally transmitted. RPC and API calls use public addresses and public blockchain data. The risk arises from unnecessarily exposing the secret to the process and its dependency graph during routine read-only operations. ### Attack Path 1. A user ...[truncated 961 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (98)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented purpose emphasizes simple vault operations, but the skill also describes auto-compounding by swapping reward tokens through Odos, introducing additional counterparties, approvals, routing logic, and price/execution risk not clearly captured in the top-level description. In a financial automation context, this mismatch can cause users to authorize broader behavior than they intended.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/setup.ts (reported line 42)May include surrounding context.

ts
// Check existing config
  if (fs.existsSync(CONFIG_PATH)) {
    console.log('✅ Existing configuration found.\n');
    const overwrite = await ask(rl, 'Overwrite existing config? [y/N]: ');
    if (overwrite.toLowerCase() !== 'y') {
      console.log('\nSetup cancelled. Existing config preserved.');
      rl.close();

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The auto-compound section describes a workflow that will swap reward tokens via an aggregator and redeposit proceeds, but it does not explicitly warn that this triggers real token swaps, price impact/slippage exposure, approval flows, and reinvestment of funds. In an agent-executed DeFi skill, omission of this warning can cause users to authorize materially different actions than they expect, increasing the chance of unintended asset movements or losses.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares capabilities that require environment-variable access and network interaction, but it does not explicitly scope or declare those permissions. In a funds-managing DeFi skill, undeclared access to secrets and external endpoints reduces transparency and can enable overbroad execution in a way users may not anticipate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The claim that the vault is one of the 'safest places' to earn yield is an unqualified safety assertion in a real-funds DeFi context. Such language can socially engineer users into underestimating smart-contract, counterparty, liquidity, governance, or bridge risks, making dangerous operations more likely to be trusted and executed.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using 'npx tsx' without pinning an exact package version can fetch whatever version is current at execution time, creating a supply-chain risk. For a skill that handles private keys and signs real transactions, a compromised or breaking upstream package could directly lead to fund loss or secret exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The shebang invokes npx tsx without pinning a version, so execution depends on whatever package version npx resolves at runtime. If the registry, dependency resolution, or local environment is compromised, an unexpected tsx version could execute arbitrary code before the script logic runs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill metadata says it is for depositing, withdrawing, checking positions, and reporting yield, but this script also swaps arbitrary reward tokens through Odos. That broader behavior introduces materially different risk: approvals to a third-party router, reliance on offchain quote assembly, and asset transformation that a user may not expect from a vault-management skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The header says the script auto-compounds rewards, but after swaps it deposits the entire wallet USDC balance, not just newly realized rewards. This can unexpectedly move unrelated user funds into the vault, violating least surprise and potentially locking funds into a strategy the user did not intend.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The usage instruction tells operators to run npx tsx compound.ts, again relying on unpinned package resolution at execution time. In a wallet-managing script, this expands the trust boundary to the npm ecosystem and can enable supply-chain code execution before any onchain safeguards apply.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The hardcoded Odos API endpoint expands the trust boundary to an external third-party service for swap routing. While using a routing API is common, in a wallet automation script this dependency is security-relevant because endpoint compromise, DNS/TLS interception, or service abuse can influence trading behavior and leak financial metadata.

Content

Scanner excerpt · scripts/compound.ts (reported line 66)May include surrounding context.

ts
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({

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The hardcoded Odos API endpoint expands the trust boundary to an external third-party service for swap routing. While using a routing API is common, in a wallet automation script this dependency is security-relevant because endpoint compromise, DNS/TLS interception, or service abuse can influence trading behavior and leak financial metadata.

Content

Scanner excerpt · scripts/compound.ts (reported line 66)May include surrounding context.

ts
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({

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The hardcoded assemble endpoint is especially dangerous because its response is used to construct the signed transaction payload. In the context of a yield skill, this is more dangerous than ordinary telemetry because the external service effectively dictates executable wallet actions outside the manifest’s narrow deposit/withdraw/report expectations.

Content

Scanner excerpt · scripts/compound.ts (reported line 88)May include surrounding context.

ts
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({

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The hardcoded assemble endpoint is especially dangerous because its response is used to construct the signed transaction payload. In the context of a yield skill, this is more dangerous than ordinary telemetry because the external service effectively dictates executable wallet actions outside the manifest’s narrow deposit/withdraw/report expectations.

Content

Scanner excerpt · scripts/compound.ts (reported line 88)May include surrounding context.

ts
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({

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
scripts/config.ts:224

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/setup.ts:56