Back to skill

Security audit

Windfall Inference

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to provide the advertised inference gateway, but its included service code has serious review-worthy security issues around wallet-linked accounts, browser credential storage, payment/proxy trust, and server installation.

Review before installing or using with sensitive workloads. Treat Windfall as a third-party proxy that can see prompts and route them to OpenRouter; avoid production secrets or confidential prompts until the wallet-auth, dashboard XSS, localStorage credential, peer-proxy, dependency, and deployment-script issues are addressed.

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

T03 · Remote Payload Retrieval and Execution

Error
Location
deploy/setup.sh:10
Finding

Root-Level Execution of a Mutable Remote Installation Script

Content
View full analysis
/dev/null; then echo "Installing Node.js 22..." curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt-get install -y nodejs fi ``` ### Technical Analysis The setup script downloads content from a remote URL and passes it directly to Bash. The response is not pinned to a version, inspected, signature-verified, or checked against a known digest before execution. The surrounding commands install system packages and create directories under `/opt`, indicating that the script is intended to run with root privileges. Consequently, the remotely supplied script also executes with root authority. NodeSource is a recognizable package provider, and there is no evidence that its current script is malicious. However, the effective code executed by this project can change after the project itself has been reviewed. A compromise of the remote endpoint, upstream publication process, DNS resolution, or TLS trust chain would therefore become arbitrary root code execution. ### Attack Path 1. An administrator runs `deploy/setup.sh` with root privileges on a fresh server. 2. The script requests the current content of `https://deb.nodesource.com/setup_22.x`. 3. A compromised or unexpectedly modified response is streamed directly into Bash. 4. Bash executes the response without local review or integrity verification. 5. The remote payload gains root-level access to the host. ### Impact Assessment A successful supply-chain compromise could obtain complete control of the deployment server. The resulting privileges could include: - Reading application secrets and wallet private keys. - Replacing the inference service or its dependencies. - Modifying payment destinations or transaction logic. - Installing persistent service ...[truncated 156 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
public/dashboard.html:263
Finding

Stored Cross-Site Scripting Through Unsanitized API-Key Labels

Content
View full analysis
{ try { const { wallet_address, label } = req.body || {}; // Check onchain identity to determine free request tier const identity = await checkIdentity(wallet_address); const result = createApiKey( wallet_address, label, identity.tier, identity.freeRequests, ); ``` The label is stored without content validation or a length restriction: ```typescript export function createApiKey( walletAddress?: string, label?: string, identityTier?: string, freeRequests?: number, ): { key: string; info: ApiKeyInfo } { const db = getDb(); const key = generateKey(); const keyHash = hashKey(key); const keyPrefix = key.slice(0, 12) + '...'; const now = new Date().toISOString(); const tier = identityTier || 'anonymous'; const free = freeRequests ?? DEFAULT_FREE_REQUESTS; db.prepare(` INSERT INTO api_keys (key_prefix, key_hash, wallet_address, label, identity_tier, free_requests_remaining, created_at) VALUES (?, ?, ?, ?, ?, ?, ?) `).run(keyPrefix, keyHash, walletAddress?.toLowerCase() || null, label || null, tier, free, now); ``` It is later returned to the wallet dashboard and inserted into an HTML string: ```javascript // Show keys list for wallet auth if (authMode === 'wallet' && data.keys && data.keys.length > 0) { keysListSection.classList.remove('hidden'); keysList.innerHTML = data.keys.map(function(k) { return '
' + '
' + '
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/index.ts:371
Finding

Unauthenticated Wallet Impersonation During API-Key Creation

Content
View full analysis
{ try { const { wallet_address, label } = req.body || {}; // Check onchain identity to determine free request tier const identity = await checkIdentity(wallet_address); const result = createApiKey( wallet_address, label, identity.tier, identity.freeRequests, ); ``` ### Technical Analysis The endpoint trusts a wallet address supplied in an unauthenticated request. It uses that address both to determine the on-chain identity tier and to associate the generated key with the wallet. A blockchain address is public information and is not proof of wallet control. The endpoint does not require a fresh nonce, wallet signature, or existing authenticated wallet session before granting benefits tied to the address. Consequently, any caller can claim an address that has a Basename or ERC-8004 identity and receive the corresponding free-request tier. The same missing ownership verification lets attackers insert API-key records and labels into another wallet's dashboard. This also enables the stored-XSS delivery path described separately. ### Attack Path 1. The attacker identifies a public wallet with a privileged on-chain identity. 2. The attacker submits the address as `wallet_address` to `POST /api/keys`. 3. `checkIdentity` evaluates the victim's address rather than an authenticated caller identity. 4. The server generates a key with the victim's identity tier and free-request allowance. 5. The attacker receives and uses the newly generated key. 6. The created record also appears in the victim's wallet dashboard because it is associated with the victim's address. The configured rate limiter reduces request volume from a single perceived client ...[truncated 704 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
public/dashboard.html:336
Finding

Long-Lived API Keys and Wallet Bearer Sessions Stored in localStorage

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/routes/inference.ts:151
Finding

Unsigned Peer Payment-Verification Headers and Plaintext Inter-Node Proxying

Content
View full analysis
n.id === proxyNodeId && clientIp.includes(n.ip)); if (isProxied) { payment = { method: 'free_tier', walletAddress: walletAddress || 'proxied', amountUsd: 0 }; } ``` The source sends prompts and wallet metadata over plaintext HTTP: ```typescript try { const proxyHeaders: Record = { 'Content-Type': 'application/json', 'X-Proxied-From': config.nodeId, 'X-Payment-Verified': 'true', }; if (walletAddress) proxyHeaders['X-Wallet-Address'] = walletAddress; const proxyRes = await fetch(`http://${routing.nodeIp}:${config.port}/v1/chat/completions`, { method: 'POST', headers: proxyHeaders, body: JSON.stringify({ ...body, model, _payment_verified: true }), signal: AbortSignal.timeout(60000), }); const proxyData = await proxyRes.json(); return res.status(proxyRes.status).json(proxyData); } catch (proxyErr) { console.error(`[inference] Proxy to ${routing.nodeId} failed, falling back to local:`, proxyErr); } ``` ### Technical Analysis A request is considered paid when it carries two ordinary HTTP headers and appears to originate from an address whose string contains a configured peer IP. There is no request signature, shared-secret MAC, mutually authenticated TLS identity, timestamp, nonce, or replay protection. The application also sets Express `trust proxy` to one hop. Correctn ...[truncated 2067 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (118)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an LLM inference/routing service with pricing, model support, energy-aware routing, and onchain attestations. The supplied code does not implement inference, routing, model selection, API compatibility, blockchain attestations, or request handling. Instead, it is a client-side website UI script for nav/footer injection and status-dot updates. This is a materially different primary purpose, so the description does not accurately represent the code chunk's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a general-purpose inference platform: cheapest/greenest routing, 200+ models, OpenAI-compatible API, and onchain attestations. This code chunk does not implement such a service. Instead, it is a specific operational script for ACP protocol testing/graduation as a buyer. It requires an ACP wallet key, talks to hardcoded agent addresses, submits ten predefined prompts, pays for jobs, waits for negotiation/delivery phases, and evaluates the returned deliverables. While the prompts relate to energy/sustainability and the requirement includes mode='greenest', that is only a parameter in submitted job data, not evidence that this code itself performs spatial routing, model selection across 200+ models, or exposes an OpenAI-compatible interface. The actual primary purpose and capabilities are materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The core declared purpose is broadly represented: this route is indeed an OpenAI-compatible inference endpoint that performs spatial routing, factors in green/cheap modes, attaches energy-related metadata, supports multiple model selection, and queues onchain attestations on Base. However, the code also contains several substantial capabilities not disclosed in the description or permissions: it authenticates users via API keys or wallet sessions, checks and consumes free-tier quotas, requires and verifies payments (including onchain tx hashes and x402 protocol), settles billing, logs revenue, and caches responses. These are not merely incidental implementation details; billing/auth/payment handling is a major part of the endpoint’s behavior and materially expands what the skill does beyond simple routed inference. Therefore the description is incomplete enough to count as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description is about LLM inference routing and energy/cost-aware model selection, but this code chunk does not perform any routing, model selection, inference, OpenAI-compatible API handling, or onchain attestation logic. Instead, it provides backend account infrastructure for API keys, quotas, balances, and privacy maintenance. While such functionality could support an inference platform, it is a materially different behavior from the declared primary purpose and introduces undeclared capabilities around credential management, billing state, and database persistence.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code does not implement model routing, energy-aware provider selection, OpenAI-compatible inference handling, access to 200+ models, or onchain attestations. Instead, it is a caching subsystem that stores and serves prior LLM responses from a local SQLite database keyed by prompt/model/user scope. While caching could be a supporting optimization for an inference platform, this chunk’s actual behavior is materially different from the declared primary purpose and introduces undeclared data storage/cache management capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description emphasizes spatial routing for LLM inference based on cost and green energy, broad model availability, OpenAI compatibility, and onchain attestations. None of those core behaviors appear in this code chunk. Instead, the code performs heuristic engagement scoring and model recommendation using request metadata and message characteristics. While model selection and cost savings are tangentially related to routing, the primary purpose here is not geographic/energy-aware routing or inference serving; it is engagement classification and simple auto-model choice. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The code does not implement LLM inference routing, model selection, OpenAI-compatible serving, energy-aware routing, or onchain attestations. Instead, its primary purpose is payment processing: watching Base for ETH deposits and crediting internal API balances. This is a materially different function and introduces undeclared capabilities involving blockchain transaction monitoring, external price fetching, and database balance updates. Therefore the declared description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents an inference-routing platform focused on choosing the cheapest/greenest node and exposing 200+ models with OpenAI-compatible access and onchain attestations. This code chunk instead handles backend accounting/telemetry: it creates SQLite tables, tracks per-wallet free requests, logs request metadata, records revenue, and returns operational stats. While some fields like node_id, model, energy_price_kwh, carbon_intensity, and attestation_uid are consistent with the broader product domain, the actual behavior here is not routing inference requests or serving model APIs. These are materially different capabilities from the declared primary purpose and are undeclared persistence/analytics behaviors.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is about LLM inference routing and pricing/energy optimization, with mention of onchain attestations. The supplied code does not perform inference routing, model selection, OpenAI-compatible API handling, energy-aware routing, pricing logic, or attestation generation/verification. Instead, it checks whether a wallet has an ERC-8004 identity token or a .base.eth basename and maps that to request allowances. While this uses Base onchain data, that is only loosely related to the description’s mention of onchain attestations and is not an implementation of the stated primary purpose. Therefore the code chunk’s actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The code's primary behavior is an OpenRouter API wrapper/proxy for chat completions with basic model-based pricing classification and optional streaming. It does not implement the key advertised capabilities of spatial routing, green-energy-aware routing, cheapest-route selection, or onchain attestations. While using OpenRouter may be broadly compatible with multi-model access, this specific chunk does not demonstrate those distinctive claims. Therefore the declared description materially overstates and misrepresents what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description is about LLM inference routing and energy-aware model selection, but this code chunk does not perform any inference, routing, model selection, OpenAI-compatible API behavior, or attestation generation. Instead, it is a payment service focused on validating onchain ETH/USDC transfers on Base and checking wallet balances. While onchain payments could be part of a broader product, this specific code’s primary purpose is materially different from the declared skill description and introduces significant undeclared payment-processing behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The code chunk does not implement LLM inference routing, model selection, energy-aware routing, OpenAI-compatible inference, or onchain attestations. Its primary purpose is billing: selling prepaid API credits via Stripe and crediting balances to API keys after successful payment events. This is a materially different capability from the declared description, so the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about LLM inference routing and model access, but the supplied code does not perform inference routing, model selection, OpenAI-compatible request handling, green-energy optimization, or onchain attestation generation. Instead, it implements payment infrastructure: a blockchain watcher that monitors USDC deposits on Base and updates API key balances in a database. This is a materially different primary purpose and includes undeclared capabilities related to blockchain monitoring, payment processing, and database mutation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The supplied code does not implement or indicate any LLM inference, routing, API compatibility, energy-aware optimization, or blockchain attestation behavior. It is purely a frontend styling configuration for Tailwind CSS. This is a materially different primary purpose from the declared description, so it is a clear mismatch.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.18.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
97% confidence
Finding

The lockfile includes ws@8.18.0, which is flagged for uninitialized memory disclosure and memory-exhaustion DoS. In this skill's context, multiple packages rely on websocket functionality for blockchain/rpc/client communications, so if any server-side or long-lived websocket handling is exposed, an attacker could crash processes or potentially obtain unintended memory contents.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-cookie==3.0.1 — 1 advisory(ies): CVE-2026-46625 (JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attr)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/dashboard.html (reported line 25)May include surrounding context.

html
<main id="main-content" class="flex-1 px-6 py-24">
  <div class="max-w-2xl mx-auto">

    <!-- Auth Section (shown when not logged in) -->
    <div id="auth-section" class="text-center">
      <h1 class="font-serif text-2xl font-bold text-warm-900 mb-2">Dashboard</h1>
      <p class="text-warm-500 mb-8">View your usage, savings, and environmental impact.</p>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/imprint.html (reported line 23)May include surrounding context.

html
<main id="main-content" class="flex-1 px-6 py-24">
  <div class="max-w-3xl mx-auto">

    <!-- ═══════════════════════════════════════════ -->
    <!--  FRENCH VERSION (version légale)            -->
    <!-- ═══════════════════════════════════════════ -->

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/imprint.html (reported line 80)May include surrounding context.

html
<p class="mt-3">Conformément au Règlement Général sur la Protection des Données (RGPD) et à la loi Informatique et Libertés, vous disposez d'un droit d'accès, de rectification, de suppression et de portabilité de vos données. Pour exercer ces droits, contactez-nous à l'adresse indiquée ci-dessus.</p>
      </section>

      <!-- 5 — Propriété intellectuelle -->
      <section>
        <h2 class="font-serif text-xl font-semibold text-warm-900 mb-3">5. Propriété intellectuelle</h2>
        <p>L'ensemble des contenus présents sur ce site (textes, images, logiciels, marques, logos) est la propriété d'Ecofrontiers SARL, sauf mention contraire. Le logiciel et la marque Windfall sont la propriété d'Ecofrontiers SARL.</p>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/index.html (reported line 261)May include surrounding context.

html
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:bg-sage-600 focus:text-white focus:px-4 focus:py-2 focus:rounded focus:z-50">Skip to content</a>

<!-- Hero -->
<main id="main-content" class="hero-bg pt-32 pb-20 px-6">
  <div class="max-w-5xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-14 items-start">

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/index.html (reported line 281)May include surrounding context.

html
<!-- Right: terminal -->
    <div class="pt-2">
      <!-- Request: the 2-line switch -->
      <div class="terminal-chrome">
        <div class="terminal-bar">
          <span class="terminal-dot red"></span>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/index.html (reported line 520)May include surrounding context.

html
<p class="text-warm-500 text-center mb-10 max-w-xl mx-auto">Every request flows through four stages — from classification to verifiable proof.</p>

    <div class="grid grid-cols-1 md:grid-cols-2 gap-6 hiw-grid">
      <!-- Vertical connectors -->
      <span class="hiw-vline-left"></span>
      <span class="hiw-vline-right"></span>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/index.html (reported line 566)May include surrounding context.

html
</div>
</section>

<!-- Live Energy Routing -->
<section class="py-16 px-6">
  <div class="max-w-4xl mx-auto">
    <div class="text-center mb-10">

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/index.html (reported line 689)May include surrounding context.

html
</div>
</section>

<!-- Scripts -->
<script src="/assets/shared.js" defer></script>
<script>
// Live oracle

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · public/privacy.html (reported line 29)May include surrounding context.

html
<div class="prose-windfall space-y-8 text-warm-700 text-[15px] leading-relaxed">

      <!-- 1 -->
      <section>
        <h2 class="font-serif text-xl font-semibold text-warm-900 mb-3">1. Who we are</h2>
        <p>This privacy policy explains how <strong>Windfall</strong>, a product of <strong>Ecofrontiers SARL</strong>, collects, uses, and protects your data when you use the Windfall inference gateway at <a href="https://windfall.ecofrontiers.xyz" class="text-sage-600 hover:underline">windfall.ecofrontiers.xyz</a>.</p>

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/services/x402.ts:6