Skip to content

Security hardening: tenant isolation, slippage protection, sliding-window rate limiting, withdrawal allowlist#535

Merged
Smartdevs17 merged 1 commit into
Smartdevs17:mainfrom
Akanimoh12:security/multi-feature-hardening
Jun 26, 2026
Merged

Security hardening: tenant isolation, slippage protection, sliding-window rate limiting, withdrawal allowlist#535
Smartdevs17 merged 1 commit into
Smartdevs17:mainfrom
Akanimoh12:security/multi-feature-hardening

Conversation

@Akanimoh12

Copy link
Copy Markdown
Contributor

Summary

Four independent security hardening features, implemented together:

  • Cross-tenant data isolation enforcement — a Prisma client extension (backend/src/security/tenant-isolation/guard.ts) binds an AsyncLocalStorage-scoped tenant context and throws CrossTenantAccessError if any query against a tenant-scoped model targets a different tenant, or omits a tenant filter on bulk operations, while a tenant context is active. A companion static scanner (scan.ts) walks routes/, services/, and repositories/ with the TypeScript AST and flags Prisma calls on tenant-scoped models with no tenantId in their where clause — it already surfaces a real gap in sandbox-db.ts (getAccountById/getAccountByWalletAddress query by raw id with no tenant filter). Both the scan and a runtime test suite run in a new CI workflow (.github/workflows/tenant-isolation.yml) gated on changes to routes/services/repositories/schema.
  • Smart contract slippage protection with simulated executionbackend/src/services/slippage-protection.ts simulates expected swap output from a quoted price and recent price history, scores sandwich-attack risk (front-run price spikes, sub-second tick bursts, oversized trades relative to pool liquidity, quote/market divergence), and computes a hard minAmountOut floor. contracts/evm/contracts/SlippageGuard.sol enforces that same floor on-chain — executeGuardedSettlement reverts if realized output falls below minAmountOut or the quote has expired, independent of what the off-chain simulation predicted, and clamps any requested tolerance to a 5% hard cap.
  • Sliding-window rate limiting per endpointbackend/src/middleware/sliding-window-rate-limit.ts adds a true sliding-window-log limiter (Redis sorted-set backed, with in-memory fallback) layered on top of the existing token-bucket limiter. Replaces fixed-window boundary bursting with smooth enforcement, adds per-endpoint configs (withdrawals, auth, invoice get tighter windows than the global default), graduated warning → throttle → block penalties, and IP+User-Agent fingerprinting for anonymous clients so they can't evade limits by dropping headers.
  • Wallet withdrawal allowlistbackend/src/services/withdrawal-allowlist.ts and backend/src/routes/withdrawals.ts let each wallet configure an allowlist of withdrawal destinations. Withdrawals to allowlisted addresses can auto-approve; withdrawals to anywhere else require reaching a configurable multi-signature approval threshold from an authorized approver set. Every withdrawal, regardless of destination, is checked against hourly/daily amount and hourly count velocity limits before it's allowed to proceed.

Test plan

  • cd backend && npm install && npm run db:generate
  • npm run tenant-isolation:scan — static scan reports the existing sandbox-db.ts finding, exits non-zero only on high-severity violations
  • npm test — covers sliding-window rate limiting, tenant isolation guard + scanner, withdrawal allowlist lifecycle, and slippage simulation
  • cd contracts/evm && npm install && npm test — covers SlippageGuard.sol (tolerance clamping, slippage floor enforcement, quote expiry, zero-amount guard)
  • Manually exercise POST /api/v1/swap/simulate and POST /api/v1/withdrawals/:walletId/requests against a running backend

Closes #522
Closes #521
Closes #520
Closes #519

…ow rate limiting, withdrawal allowlist

Implements four security hardening features:

- Cross-tenant data isolation: a Prisma client extension enforces tenant
  boundaries at query time (throws on cross-tenant access instead of
  silently leaking), backed by a static AST scanner that flags queries on
  tenant-scoped models missing a tenantId filter, plus a CI workflow that
  runs both on every PR touching routes/services/repositories/schema.
- Slippage protection: a pre-execution swap simulation service estimates
  expected output, detects sandwich-attack price signatures, and computes
  a hard minAmountOut floor; a new SlippageGuard.sol contract enforces that
  floor on-chain regardless of what the off-chain simulation predicted.
- Sliding-window rate limiting: a true sliding-window-log limiter with
  per-endpoint configuration and graduated warning/throttle/block penalties,
  layered on top of the existing token-bucket limiter.
- Withdrawal allowlist: per-wallet allowlisted withdrawal addresses, with
  multi-signature approval required for non-allowlisted destinations and
  hourly/daily velocity checks on withdrawal amount and count.

Closes Smartdevs17#522, Smartdevs17#521, Smartdevs17#520, Smartdevs17#519
@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

@Akanimoh12 is attempting to deploy a commit to the smartdevs17's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 26, 2026

Copy link
Copy Markdown

@Akanimoh12 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Smartdevs17 Smartdevs17 merged commit 1f0a353 into Smartdevs17:main Jun 26, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants