Skip to main content

Security Findings

Internal Document

This page tracks active security findings and fix recommendations. Review before deploying to production.


Open Findings​

The following issues were identified during the production security audit and have not yet been fully resolved.

HIGH — Analytics Endpoints Unauthenticated​

Risk: Anyone can scrape every user's wallet history and protocol stats.

Location:

  • src/app/api/analytics/user-history/route.ts:24-83
  • src/app/api/analytics/protocol-volume/route.ts:17-94
  • src/app/api/analytics/global-stats/route.ts:17-35

Issue: All three analytics endpoints skip authenticateRequest. They expose aggregated swap history and per-wallet protocol volume to unauthenticated callers.

Fix: Apply the same x-api-key gate and rate limiting used on the 1inch and LiFi routes, or move the aggregation behind server-side-only RPCs.


HIGH — 1inch Proxy Routes Unauthenticated​

Risk: Anonymous users can burn your 1inch API quota or spam limit-order endpoints under your key.

Location:

  • src/app/api/1inch/orderbook/limit/create/route.ts
  • src/app/api/1inch/orderbook/limit/submit/route.ts
  • src/app/api/1inch/charts/candle/route.ts
  • src/app/api/1inch/charts/line/route.ts
  • src/app/api/1inch/swap/classic/quote/route.ts
  • src/app/api/1inch/tokens/search/route.ts

Issue: These routes forward requests with ONEINCH_API_KEY but do not validate the caller. Logging-only cleanup was applied to chart routes; authentication was not added.

Fix: Enforce API key checks and per-IP throttling on all these routes, or proxy through an authenticated backend job.


MEDIUM — Faucet IP Spoofing​

Risk: Callers can bypass faucet rate limiting by spoofing x-forwarded-for.

Location: src/app/api/faucet/request/route.ts:61-70

Issue: The faucet rate limiter reads the client IP from x-forwarded-for and x-real-ip headers, which are user-controlled. An attacker can rotate fake IPs to bypass all rate limiting.

Fix: Use request.ip from the hosting platform or a trusted proxy header set by the load balancer. Reject user-controlled forwarded headers.


MEDIUM — In-Memory Rate Limiter Not Shared Across Instances​

Risk: Rate limits reset on every serverless worker cold start and are not coordinated across instances — effectively no rate limit in production.

Location: src/lib/rate-limit.ts:15-107

Issue: The rate limiter is process-local and uses setInterval for cleanup. In a serverless/edge environment, each worker instance maintains its own state. Multiple dangling intervals accumulate on long-lived workers.

Fix: Move rate limit state to a shared store (Redis/Upstash) or use the Prisma database as the source of truth for request counts.


MEDIUM — Auth Logging Leaks API Key​

Risk: A compromised log stream leaks the server's CLIENT_API_KEY and the caller's key value.

Location: src/lib/auth.ts:95-104

Issue: The authentication utility logs both the supplied x-api-key header and the configured CLIENT_API_KEY value on every authenticated request.

Fix: Strip key values from logs or wrap them in a debug flag. Redact before emitting.


LOW — BigInt Overflow in Wormhole and Balance Display​

Risk: Balances and fees silently misreport for positions over 2^53.

Location:

  • src/hooks/useTokenBalances.ts:96-107
  • src/plugins/wormhole/handlers.ts:191-208

Issue: Token balance formatting and Wormhole quote amounts cast bigint values to Number. JavaScript's Number cannot represent integers above 2^53 accurately. Large positions are silently truncated.

Fix: Replace Number(bigintValue) with formatUnits(bigintValue, decimals) from viem throughout these paths. Never cast token amounts to Number.


LOW — Unbounded Chart Cache Memory Leak​

Risk: Switching tokens or time ranges repeatedly leaks browser memory.

Location: src/components/charts/price-chart.tsx:105-158

Issue: PriceChart caches every request in an ever-growing Map with no eviction policy. Full API responses are also logged, flooding devtools.

Fix: Add an LRU eviction policy or size cap (e.g., max 50 entries). Remove the response logging.


LOW — Turbopack Forced in Production Build​

Risk: Silent optimization regressions vs. the stable compiler.

Location: package.json:6-13

Issue: The build script forces next build --turbopack, which is experimental for production bundles.

Fix: Use next build for production releases. Keep next dev --turbopack for development.


Resolved Findings​

FindingLocationResolutionDate
Unprotected API routes1inch/eth_rpc, lifi/routes, 1inch/gasauthenticateRequest + rate limiting added2025-10-24
Arbitrary RPC methods1inch/eth_rpc/route.ts14-method allowlist enforced; write methods return 4032025-10-24
Stale closure state dropscli.tsx (4+ setTabs calls)Rewritten with functional update form2025-10-24
Commands fail silently during plugin loadcli.tsxLoading state + command queue added2025-10-24
Production log leaks wallet data4 API routesLogging gated behind NODE_ENV === 'development'2025-10-24
Hardcoded chain mapsMultiple pluginsCentralized src/lib/chains.ts with 7 chains2025-10-24

Priority Order for Remaining Fixes​

  1. Analytics endpoints — HIGH (data exposure, no auth)
  2. 1inch proxy routes — HIGH (quota drain, no auth)
  3. In-memory rate limiter — MEDIUM (ineffective in serverless)
  4. Faucet IP spoofing — MEDIUM (bypass rate limiting)
  5. Auth logging — MEDIUM (key leakage in logs)
  6. BigInt overflow — LOW (silent precision loss)
  7. Chart cache — LOW (browser memory leak)
  8. Turbopack in production — LOW (build risk)