Files
nick-doc/09 - Audits/Threat Model - Amanat Escrow Platform.md
Siavash Sameni 4cf5c49274 docs(audit): align documentation with post-remediation backend reality
- Update data model enums to match backend models
- Update API reference auth requirements
- Add dispute module references and warning blocks
- Add 2026-05-24 audit remediation callout to Overview
- Generate task breakdowns and audit artifacts
- Add doc alignment report (.taskmaster/reports/)
2026-05-24 11:16:29 +04:00

48 KiB

title, tags, created, status, reviewers
title tags created status reviewers
Threat Model - Amanat Escrow Platform
audit
security
threat-model
escrow
payments
2026-05-24 living
backend
security
product

Threat Model - Amanat Escrow Platform

This document is the canonical threat model for the Amanat (Amn) financial escrow marketplace. All security specifications, authorization matrices, and hardening plans reference this document. It is a living document and must be updated when the attack surface changes.

Cross-references


1. System Description

1.1 What is Amanat

Amanat is a financial escrow marketplace where buyers and sellers transact in cryptocurrency (USDT, USDC on BSC and Ethereum). The platform holds buyer funds in a custodial escrow wallet during order fulfillment and releases or refunds them based on delivery outcome or dispute resolution. It is not a simple CRUD marketplace; it is a financial platform with custody obligations.

1.2 Technology stack

Layer Technology
Frontend Next.js (React), MUI, wagmi/Web3, Socket.IO client
Backend Express 5, TypeScript, Mongoose, Socket.IO
Database MongoDB (primary), Redis (caching, lockout, rate-limit)
Payments - hosted SHKeeper self-hosted gateway at pay.amn.gg
Payments - direct Web3/wagmi wallet transfer to custodial escrow address
Blockchain BSC mainnet (chain ID 56), Ethereum; USDT/USDC BEP-20/ERC-20
Realtime Socket.IO 4.8 with client-driven room joins
Email Nodemailer via SMTP
AI OpenAI API for content generation, analysis, translation
Infrastructure Docker Compose on single host, Nginx reverse proxy, CloudFlare upstream
Deployment Watchtower auto-pull on latest tag (no staging gate)

1.3 Key data flows

Pay-in to escrow (SHKeeper path): Buyer selects offer -> Backend creates Payment intent -> SHKeeper allocates deposit address -> Buyer sends crypto -> SHKeeper webhook confirms -> Backend sets escrowState=funded -> Cascade: offer accepted, request status advanced, chat created.

Pay-in to escrow (Web3 path): Buyer connects wallet -> Backend records pending Payment -> Buyer signs on-chain transfer to escrow wallet -> Backend verifies eth_getTransactionReceipt -> Sets escrowState=funded -> Same cascade.

Escrow hold: Funds sit at custodial BSC wallet. Payment.escrowState=funded. No on-chain action occurs. Admin dashboard shows all funded escrows.

Release to seller: Buyer confirms delivery (or auto-release timer) -> Admin initiates payout via SHKeeper Payouts API or manual wallet signing -> On-chain transfer to seller wallet -> escrowState=released.

Refund to buyer: Dispute resolved with refund action, or pre-shipment cancellation -> Admin builds refund tx payload -> Admin signs and broadcasts -> escrowState=refunded.

Dispute flow: Buyer or seller opens dispute -> Three-way chat created (buyer, seller, admin) -> Admin assigned -> Evidence gathered -> Admin resolves (release/refund/partial/reject) -> Financial side-effect dispatched manually.

Webhook flow (SHKeeper): SHKeeper POSTs to /api/payment/shkeeper/webhook with HMAC-SHA256 signature -> Backend verifies raw-body signature -> Deduplicates by (providerPaymentId, status) tuple -> PaymentCoordinator serializes state update -> Cascade to offer/request/chat/notification.


2. Protected Assets

Asset Class Examples Sensitivity Storage
User credentials bcrypt-hashed passwords, email Critical MongoDB users
User sessions JWT access (7d), refresh (30d) Critical localStorage (browser), MongoDB user.refreshTokens[]
Admin credentials and sessions Same as user but with role: admin Critical Same as user
Payment records and funds state Payment.status, escrowState, amounts, tx hashes Critical MongoDB payments
Escrow wallet private key Key controlling ESCROW_WALLET_ADDRESS Critical Platform operator custody (not in code)
Wallet addresses Buyer wallet, seller payout wallet, escrow wallet High MongoDB users.profile.walletAddress, Payment.blockchain
Webhook secrets SHKEEPER_WEBHOOK_SECRET Critical Env var
API keys SHKEEPER_API_KEY, OPENAI_API_KEY, JWT_SECRET Critical Env var
User personal data Email, name, phone, addresses High MongoDB users
Transaction history All Payment, PurchaseRequest, Dispute records High MongoDB
Private messages/chat Chat messages, dispute evidence High MongoDB chats
Realtime event streams Socket.IO room broadcasts, notifications Medium In-process / Socket.IO
Provider integration configs SHKeeper endpoint, callback URLs, CORS origin High Env var, hardcoded
AI usage and budgets OpenAI call volume per user Medium No tracked storage currently
Upload files Avatars, product images, dispute evidence Medium Host filesystem uploads/
Notification preferences Per-user notification settings Low MongoDB users
Blog content Posts, categories Low MongoDB blogposts

3. Actors

Actor Access Level Motivation Risk Profile
Buyer Authenticated (role: buyer). Can create requests, pay, confirm delivery, open disputes, rate. Complete purchase, get refund if unsatisfied, dispute bad service. May attempt to bypass payment or confirm without delivery. Medium. Motivated to fraud payment or delivery confirmation.
Seller Authenticated (role: seller). Can create offers, templates, shop settings, receive payouts. Receive payment for goods/services. May attempt to mark unshipped items as delivered or inflate prices post-acceptance. Medium. Motivated to receive funds without delivery.
Admin Authenticated (role: admin). Full access to user management, dispute resolution, manual payouts, payment dashboard. Platform operations. Single point of trust for fund release. High. If compromised, can release all escrowed funds.
Support staff Authenticated (role: support). Read-only access, password resets, escalation. Customer support operations. Low-Medium. Limited destructive capability but can read sensitive data.
Unauthenticated attacker No auth. Can reach public endpoints, Socket.IO handshake (rejected without JWT), webhook route (requires HMAC). Financial gain, data theft, service disruption, cost abuse. High. Broad attack surface including unauthenticated endpoints.
Compromised user Valid JWT for a buyer/seller account. Attacker uses stolen session to redirect payouts, open fraudulent disputes, exfiltrate data. High. Hard to distinguish from legitimate activity.
Compromised admin Valid JWT with admin role. Full platform compromise: release escrows, manipulate payments, exfiltrate all user data. Critical. Single compromised admin session can drain the escrow wallet.
Malicious payment provider / webhook sender Can POST to webhook endpoint. Inject false payment confirmations to trigger release. High. If webhook verification is flawed, funds are at risk.
Malicious blockchain actor Can submit any tx hash for verification. Submit a tx hash for an unrelated successful transfer (wrong recipient/amount) and get it accepted as payment. High. Current Web3 verification is incomplete.
Insider threat Legitimate access to infrastructure, code, or admin tools. Fund manipulation, data exfiltration, backdoor insertion. Critical. Trust boundary cannot be fully technical.
Supply-chain attacker Can compromise npm packages used by the project. Remote code execution, credential theft, payment flow manipulation. High. Real 2026 precedent with Axios, TanStack compromises.

4. Trust Boundaries

4.1 Diagram

flowchart TB
    subgraph Internet["INTERNET (Untrusted)"]
        Browser["Browser / Next.js"]
        MobileApp["Telegram Mini App"]
        Attacker["Attacker"]
    end

    subgraph Edge["EDGE (Semi-Trusted)"]
        CF["CloudFlare / Nginx"]
    end

    subgraph Backend["BACKEND (Trusted - single Docker host)"]
        API["Express API\n:5001"]
        SocketIO["Socket.IO Server"]
        Uploads["/uploads filesystem"]
    end

    subgraph Data["DATA LAYER (Trusted)"]
        Mongo[("MongoDB\n:27017")]
        Redis[("Redis\n:6379")]
    end

    subgraph External["EXTERNAL SERVICES (Semi-Trusted)"]
        SHK["SHKeeper\npay.amn.gg"]
        BSC["BSC/Eth RPC\nbsc-dataseed"]
        SMTP["SMTP / Email"]
        OpenAI["OpenAI API"]
    end

    Browser -- "HTTPS / REST\nJWT in Authorization" --> CF
    Browser -- "WSS / Socket.IO\nJWT in handshake" --> CF
    MobileApp -- "HTTPS" --> CF
    Attacker -.-> CF

    CF -- "HTTP proxy" --> API
    CF -- "WS proxy" --> SocketIO

    API -- "Mongoose queries" --> Mongo
    API -- "Cache / lockout / rate-limit" --> Redis
    API -- "File read" --> Uploads
    SocketIO -- "Room membership" --> Redis

    API -- "POST /api/v1/payment_request\nX-Shkeeper-Api-Key" --> SHK
    SHK -- "POST /api/payment/shkeeper/webhook\nHMAC-SHA256" --> API
    API -- "eth_getTransactionReceipt" --> BSC
    API -- "Nodemailer send" --> SMTP
    API -- "GPT calls" --> OpenAI

4.2 Boundary descriptions

Boundary Crossing Protocol Trust Assumption Current Gap
Browser <-> Backend API HTTPS, JWT in Authorization header, CORS allow-list Browser is untrusted; JWT proves identity Tokens stored in localStorage (XSS-exposed); 7-day access token lifetime
Browser <-> Socket.IO WSS, JWT in handshake auth.token Socket is untrusted until JWT verified Room joins are client-driven with userId argument; server-side verification may be incomplete (socketService.ts citation needed)
Backend <-> MongoDB Mongoose on localhost:27017 (no TLS in dev) Database is trusted; network is trusted (single host) No TLS, no auth on MongoDB connection in default config
Backend <-> Redis Redis client on localhost:6379 Redis is trusted; used for cache and lockout No TLS; password optional (REDIS_PASSWORD)
Backend <-> SHKeeper HTTPS, X-Shkeeper-Api-Key header outbound; HMAC-SHA256 inbound SHKeeper is semi-trusted (self-hosted, operator controls) Webhook returns 202 on all errors; no dead-letter queue; signature bypass in dev mode
Backend <-> Blockchain RPC HTTPS JSON-RPC to bsc-dataseed.binance.org RPC is semi-trusted (public endpoint, rate-limited) Only receipt.status checked, not Transfer event recipient/amount; public RPC subject to throttling
Backend <-> Email (SMTP) SMTP with credentials SMTP provider is trusted Verification codes logged in plaintext to stdout in all environments
Backend <-> OpenAI HTTPS, OPENAI_API_KEY OpenAI is trusted for data handling No authentication required on AI endpoints; no per-user budget tracking
Admin UI <-> Backend Same as Browser <-> Backend but with role: admin JWT Admin is highly trusted No step-up auth for payouts; admin role not verified on all admin routes
Mini App / Telegram <-> Backend HTTPS, Telegram WebApp initData Telegram identity is semi-trusted Deep-link parameter tampering surface; initData validation must be strict

5. Threat Catalog

T01 -- Fake Payment Proof Submission

Field Value
STRIDE Spoofing
Affected assets Payment records, escrow funds
Actors Buyer, malicious blockchain actor
Description In the Web3 payment path, the backend accepts a transactionHash and verifies it via eth_getTransactionReceipt. The current BSCTransactionVerifier checks only receipt.status === '0x1' (transaction succeeded). It does not decode the ERC-20 Transfer event to verify that to matches ESCROW_WALLET_ADDRESS or that value matches the expected payment amount. A buyer can submit the hash of any successful USDT transfer (e.g., a 0.01 USDT transfer to their own wallet) and the system marks the payment as completed with escrowState=funded.
Current state Vulnerable
Required mitigation Decode Transfer(address,address,uint256) event from receipt.logs. Assert to == ESCROW_WALLET_ADDRESS and value >= expectedAmount (with decimal adjustment). Reject if mismatch. Reference: Payment Flow - DePay & Web3, decentralizedPaymentService.ts.

T02 -- Webhook Replay Attack

Field Value
STRIDE Spoofing / Tampering
Affected assets Payment records, escrow funds
Actors Malicious webhook sender, man-in-the-middle
Description SHKeeper webhooks are verified using HMAC-SHA256 of the raw body against SHKEEPER_WEBHOOK_SECRET. However: (a) in development mode, signature verification is bypassed entirely; (b) the handler deduplicates by comparing (metadata.shkeeperStatus, balance_fiat, paid) within a 10-second window, but a replay outside that window with identical payload could be processed again; (c) there is no nonce, timestamp, or delivery-ID check from SHKeeper. An attacker who captures a valid webhook payload can replay it to mark a different payment as paid.
Current state Partially mitigated
Required mitigation Implement webhook delivery-ID tracking (store delivery_id or (external_id, status) as idempotency key). Reject webhooks older than a configurable window. Never bypass signature verification in any non-local environment. Add dead-letter storage for failed webhooks. Reference: Payment Flow - SHKeeper, shkeeperWebhook.ts.

T03 -- Arbitrary Socket.IO Room Join

Field Value
STRIDE Information disclosure / Elevation of privilege
Affected assets Realtime event streams, private notifications, chat messages
Actors Compromised user, unauthenticated attacker (with stolen JWT)
Description Socket.IO room joins are client-driven. The client emits events like join-user-room {userId}, join-seller-room {sellerId}, join-chat-room {chatId}. The documentation explicitly warns that userId arguments "are NOT trusted blindly" but notes the authorization check in socketService.ts "needs verification." If the server does not verify socket.data.user.id === userId before joining, any authenticated user can subscribe to any other user's private notifications (user-{otherUserId}), seller events (seller-{otherSellerId}), or chat rooms (chat-{otherChatId}).
Current state Vulnerable (verification status uncertain)
Required mitigation Remove client-driven join-*-room events. After JWT handshake, the server should automatically join the socket to user-{decoded.id}. For role rooms (seller-*, buyer-*), derive membership from decoded.role. For chat rooms, verify that decoded.id is in chat.participants. Reference: Real-time Layer, socketService.ts.

T04 -- Stolen Token Reuse

Field Value
STRIDE Spoofing / Elevation of privilege
Affected assets User sessions, admin sessions, all user-owned data
Actors Compromised user, compromised admin
Description Access tokens are JWTs stored in localStorage with a 7-day expiry. If an XSS vulnerability exists (or a compromised npm dependency injects a script), the attacker exfiltrates both accessToken and refreshToken from localStorage. The refresh token rotation mechanism detects reuse (if the same refresh token is presented twice, all sessions are invalidated), but the attacker can use the access token for up to 7 days without triggering rotation. For admin accounts, a stolen token gives full platform control including manual payout signing.
Current state Partially mitigated (rotation exists, but storage and lifetime are weak)
Required mitigation (1) Move refresh tokens to httpOnly secure cookies. (2) Reduce access token lifetime to 15-60 minutes. (3) Keep only the access token in memory (not localStorage). (4) Implement CSRF protection if cookies are used. Reference: Security Architecture section 11, Authentication Flow.

T05 -- Double Payout / Double Release

Field Value
STRIDE Tampering / Repudiation
Affected assets Payment records, escrow funds
Actors Compromised admin, race condition (concurrent requests)
Description The payout flow (shkeeperPayoutService.createPayoutTask) has idempotency: it checks for an existing outgoing Payment with the same (purchaseRequestId, sellerOfferId, sellerId, provider, direction:'out') in pending/processing/completed status. However: (a) the manual admin payout path (admin-wallet-payout.tsx) signs on-chain directly and then calls confirmAdminTx, with no corresponding idempotency guard; (b) the PaymentCoordinator serializes updates for a single payment, but two concurrent payout requests for different payments against the same escrow balance are not guarded; (c) escrowState is a mutable field, not derived from an immutable ledger. An admin (or attacker with admin credentials) could trigger two payouts for the same underlying funds.
Current state Partially mitigated
Required mitigation (1) Introduce an immutable funds ledger (FundsAccount, LedgerEntry) so that releasable balance is derived, not stored. (2) Add a distributed lock (Redis) around payout creation for a given escrow. (3) Require admin step-up authentication or two-person approval for payouts above a threshold. Reference: Escrow Flow, Payout Flow, Backend Stack Security and Refactor Assessment - 2026-05-24 Phase 2.

T06 -- Dispute Bypass (Release During Active Dispute)

Field Value
STRIDE Tampering
Affected assets Escrow funds, dispute records
Actors Compromised admin, buyer (if auto-release fires)
Description Opening a dispute does not change Payment.escrowState away from funded. The Dispute Flow explicitly documents this: "Today, opening a dispute does not flip Payment.escrowState away from funded. An admin could theoretically still release the escrow before resolving the dispute." The Dispute API claims dispute creation "pauses any in-flight payout," but the implementation does not enforce this in the PaymentCoordinator or PayoutService. A release or refund can proceed while a dispute is active.
Current state Vulnerable
Required mitigation (1) Add a disputed escrow state or a disputeHold flag on Payment that blocks all release/refund operations. (2) Enforce this in PaymentCoordinator and shkeeperPayoutService as a precondition. (3) Auto-set this flag in DisputeService.createDispute. (4) Clear only when dispute is resolved. Reference: Dispute Flow, Escrow Flow, Platform Logical Audit - 2026-05-24 Finding 1.

T07 -- Email / Registration Abuse

Field Value
STRIDE Denial of service / Spoofing
Affected assets Email service, user accounts
Actors Unauthenticated attacker
Description The registration endpoint (POST /api/auth/register) triggers an email dispatch for every request. The resend endpoint (POST /api/auth/resend-verification) does the same. Rate limiting is disabled globally. An attacker can submit thousands of registration requests with random or victim email addresses, causing: (a) SMTP cost explosion; (b) email service reputation damage (spam complaints); (c) TempVerification collection bloat in MongoDB. Additionally, the 6-digit verification code is logged to stdout in all environments, leaking it to anyone with log access.
Current state Vulnerable
Required mitigation (1) Enable rate limiting on /api/auth/register and /api/auth/resend-verification (e.g., 5 requests per 15 minutes per IP, 3 per email). (2) Remove console.log of verification codes in production. (3) Add CAPTCHA or proof-of-work for registration. (4) Add TTL index on TempVerification collection for auto-cleanup. Reference: Registration Flow, Security Architecture section 9.

T08 -- AI Cost Abuse (Unauthenticated / Over-Budget Usage)

Field Value
STRIDE Denial of service (financial)
Affected assets AI usage budgets, OPENAI_API_KEY cost
Actors Unauthenticated attacker, compromised user
Description All AI endpoints (/api/ai/generate, /api/ai/analyze, /api/ai/translate, /api/ai/assist) currently have no authentication or caller identity verification, as documented in the Platform Logical Audit. Any client can call these endpoints and incur OpenAI API costs. Even if authentication is added, there is no per-user budget tracking, daily limit, or cost attribution.
Current state Vulnerable
Required mitigation (1) Require Bearer JWT on all AI routes. (2) Implement per-user daily/monthly token budgets stored in MongoDB or Redis. (3) Rate-limit AI endpoints separately (e.g., 20 requests per hour per user). (4) Alert on abnormal cost spikes. Reference: Platform Logical Audit - 2026-05-24 Finding 3.

T09 -- Admin Privilege Escalation

Field Value
STRIDE Elevation of privilege
Affected assets All platform assets
Actors Compromised user, insider
Description Admin role is stored as a string field role: 'admin' on the User document. If any route or service fails to enforce roleGuard('admin'), an ordinary user can access admin-only endpoints. The audit identifies that "admin-sensitive routes need explicit role enforcement, not just authentication." The admin bootstrap seed creates an admin with known credentials; if these are not rotated before launch, anyone who knows the seed email/password gains admin access. Additionally, there is no step-up authentication for high-risk admin operations (payouts, role changes, user deletion).
Current state Partially mitigated (roleGuard exists but may not be applied consistently)
Required mitigation (1) Audit every admin route for roleGuard('admin') enforcement. (2) Rotate all seed admin credentials before launch. (3) Implement step-up authentication (re-authentication or 2FA) for payouts, role changes, and user suspension. (4) Add audit logging for all admin actions. Reference: Security Architecture section 3, Backend Architecture section 4.

T10 -- Passkey / WebAuthn Bypass

Field Value
STRIDE Spoofing
Affected assets User credentials, sessions
Actors Unauthenticated attacker, compromised user
Description The passkey implementation has three critical flaws: (a) The publicKey field is stored as the literal string 'simulated-public-key' rather than the actual COSE public key from the attestation object. A malicious client can register any credential ID under any user account. (b) Challenges are stored in an in-process Map, not Redis, breaking in multi-instance deployments. (c) Passkey-issued refresh tokens are not appended to user.refreshTokens[], so the standard refresh endpoint rejects them, and the token reuse detection mechanism does not apply.
Current state Vulnerable (passkeys are stubbed and non-functional for security)
Required mitigation (1) Replace stub attestation with @simplewebauthn/server. Store real COSE public keys. (2) Move challenge storage to Redis with TTL. (3) Persist passkey-issued refresh tokens in user.refreshTokens[]. (4) Enforce monotonic counter to detect cloned authenticators. (5) Consider disabling passkey feature entirely until production-ready. Reference: Passkey (WebAuthn) Flow, Platform Logical Audit - 2026-05-24 Finding 2.

T11 -- Web3 Payment with Wrong Recipient / Token / Amount

Field Value
STRIDE Spoofing
Affected assets Payment records, escrow funds
Actors Buyer, malicious blockchain actor
Description Closely related to T01 but distinct in scope. The POST /api/payment/decentralized/save and POST /api/payment/decentralized/update endpoints are unauthenticated (per the audit findings). This means any client can create or modify decentralized payment records in the database without any on-chain verification. Combined with the incomplete BSCTransactionVerifier, an attacker can: (a) save a fake payment with arbitrary status; (b) update confirmations to make it appear verified; (c) trigger the cascade that accepts an offer and advances the purchase request.
Current state Vulnerable
Required mitigation (1) Add authentication to all /api/payment/decentralized/* endpoints. (2) Add ownership verification (the authenticated user must be the buyer of the referenced purchase request). (3) Harden BSCTransactionVerifier per T01. (4) Remove test endpoints from production builds. Reference: Platform Logical Audit - 2026-05-24 Finding 3, Payment Flow - DePay & Web3.

T12 -- Rate Limit Bypass

Field Value
STRIDE Denial of service
Affected assets All endpoints, email service, AI budget, database
Actors Unauthenticated attacker
Description express-rate-limit is explicitly disabled in the Express application (app.ts:227). The documentation describes recommended limits but they are not active. Without rate limiting, every endpoint is exposed to abuse: brute-force login attempts, registration email spam, AI cost explosion, payment endpoint flooding, and chat/message spam. Redis-based counters are wired but not enforced.
Current state Vulnerable
Required mitigation (1) Enable rate limiting globally with tiered limits: auth paths (5-10 req/5 min/IP), payment paths (20 req/15 min/user), AI paths (20 req/hr/user), chat/messaging (30 req/min/user), file upload (10 req/hr/user), global default (100 req/15 min/IP). (2) Store counters in Redis. (3) Return 429 Too Many Requests with Retry-After header. Reference: Security Architecture section 9, Backend Architecture section 3.

T13 -- XSS Leading to Token Theft

Field Value
STRIDE Tampering / Information disclosure
Affected assets User sessions, admin sessions
Actors Unauthenticated attacker (via stored XSS), compromised user (via reflected XSS)
Description Access tokens and refresh tokens are stored in localStorage. Any XSS vulnerability -- whether from a stored payload in chat messages, product descriptions, blog posts, dispute evidence, or user profile fields -- allows an attacker to read both tokens via localStorage.getItem(). Helmet CSP is in place but configured permissively for Web3 popup compatibility (COEP: unsafe-none, COOP: same-origin-allow-popups). React auto-escapes output, but dangerouslySetInnerHTML may be used in blog or description rendering. File uploads (dispute evidence, chat attachments) are served from /uploads without authentication, and a malicious SVG or HTML file could execute scripts in the context of the application.
Current state Partially mitigated (CSP, React escaping, MIME validation exist)
Required mitigation (1) Move tokens out of localStorage per T04. (2) Tighten CSP; evaluate whether unsafe-none COEP is necessary. (3) Audit all uses of dangerouslySetInnerHTML. (4) Serve uploads with Content-Disposition: attachment and X-Content-Type-Options: nosniff. (5) Add virus scanning (ClamAV) for uploaded files. Reference: Security Architecture section 11, section 7.

T14 -- npm Supply-Chain Compromise

Field Value
STRIDE Tampering / Elevation of privilege / Information disclosure
Affected assets All backend and frontend code, secrets, user data
Actors Supply-chain attacker
Description Both frontend and backend depend heavily on npm packages. The 2026 ecosystem has documented real compromises: Axios npm supply-chain compromise (March 2026, used in this project), TanStack npm compromise (May 2026, @tanstack/react-query used in this project), Express security releases including Multer issues (February 2026, multer: ^2.0.2 specified). A compromised dependency can exfiltrate JWT_SECRET, SHKEEPER_WEBHOOK_SECRET, OPENAI_API_KEY, or inject malicious code into payment flows. The backend currently has no lockfile pinning verification, no npm provenance checking, and no dependency audit CI step.
Current state Partially mitigated (some packages may be updated)
Required mitigation (1) Pin all dependencies with lockfile; verify lockfile integrity in CI. (2) Enable npm provenance/signature verification where available. (3) Run npm audit / yarn audit in CI; fail on high/critical CVEs. (4) Review and update multer to >= 2.1.0. (5) Implement a secure build and supply-chain policy (see Backend Stack Security and Refactor Assessment - 2026-05-24 doc 10). (6) Consider extracting security-critical backend code to Go/Kotlin with smaller dependency footprint. Reference: Backend Stack Security and Refactor Assessment - 2026-05-24 supply-chain section.

T15 -- CSRF on State-Changing Endpoints

Field Value
STRIDE Cross-site request forgery
Affected assets User account settings, payment actions, admin operations
Actors Unauthenticated attacker (via victim browser)
Description The current architecture uses JWT in the Authorization header (not cookies), which provides inherent CSRF protection because browsers do not automatically attach Authorization headers on cross-origin requests. However, if the planned migration to httpOnly cookies for refresh tokens (recommended in T04) is implemented without CSRF tokens, the refresh endpoint becomes vulnerable to CSRF. Additionally, if any endpoint accidentally reads tokens from cookies or query parameters, CSRF becomes possible.
Current state Mitigated (JWT in Authorization header)
Required mitigation When migrating to httpOnly cookies: (1) Implement CSRF token (double-submit cookie or synchronizer token). (2) Apply SameSite=Strict or SameSite=Lax on cookies. (3) Verify Origin header on state-changing requests. (4) Ensure CORS is not overly permissive. Reference: Security Architecture section 4.
Field Value
STRIDE Tampering / Spoofing
Affected assets User identity, referral attribution
Actors Unauthenticated attacker
Description The Telegram Mini App surface accepts initData from the Telegram WebApp SDK. If the backend does not cryptographically verify initData using the Telegram Bot token, an attacker can forge the user identity, impersonate other Telegram users, or tamper with referral parameters in deep links (/r/:code redirect at app.ts:274-278). The referral code is passed as a query parameter and is not validated against a signed token.
Current state Partially mitigated (verification status depends on implementation)
Required mitigation (1) Verify Telegram initData signature using HMAC-SHA256 with the Bot token on every Mini App request. (2) Validate referral codes server-side before applying. (3) Do not trust client-supplied userId from Telegram context without signature verification.

T17 -- Payment Provider Outage / Chain RPC Outage

Field Value
STRIDE Denial of service
Affected assets Payment processing, escrow operations, user experience
Actors Infrastructure failure (non-malicious)
Description The platform depends on two external systems for financial operations: (a) SHKeeper gateway at pay.amn.gg for pay-in address allocation and payout execution; (b) BSC/Ethereum RPC (bsc-dataseed.binance.org) for transaction verification. If SHKeeper is down, new pay-in intents cannot be created (the code falls back to a demo URL in this case). If the RPC is down, Web3 payment verification cannot complete. The circuit breaker (shkeeperFetch in shkeeperHealthCheck.ts) trips after repeated failures, but the fallback is a demo URL, not a graceful degradation. Public BSC RPC endpoints are rate-limited. There is no dedicated RPC provider.
Current state Partially mitigated (circuit breaker and wallet monitor exist as fallbacks)
Required mitigation (1) Use a dedicated RPC provider (Ankr, QuickNode, Alchemy) with SLA guarantees. (2) Implement retry with exponential backoff for verification. (3) When SHKeeper is down, return a clear error to the buyer instead of a demo URL. (4) Store pending verifications for reconciliation when service resumes. (5) Document operational runbooks for provider outage. Reference: Payment Flow - SHKeeper, Payment Flow - DePay & Web3.

T18 -- Insider Fund Manipulation

Field Value
STRIDE Tampering / Repudiation
Affected assets Escrow funds, payment records
Actors Insider threat (admin, operator, developer)
Description The escrow wallet is a single custodial BSC address controlled by the platform operator. The private key has unrestricted access to all in-flight escrowed funds. Admin users can initiate manual payouts via the admin-wallet-payout.tsx UI by connecting their wallet and signing transfers directly. There is no multi-signature requirement, no dual-approval for large payouts, no immutable audit ledger, and no automated anomaly detection on payout patterns. A single insider with access to the escrow private key or an admin session can drain all escrowed funds.
Current state Vulnerable
Required mitigation (1) Move escrow wallet to a multi-sig solution (e.g., Gnosis Safe) requiring at least 2-of-3 signatures for any transfer. (2) Implement two-person approval for payouts above a configurable threshold. (3) Build an immutable funds ledger so every debit/credit is append-only and auditable. (4) Implement real-time alerting on unusual payout patterns. (5) Store one key in HSM. (6) Separate admin UI access from wallet signing capability. Reference: Escrow Flow custodial risk warning, Payout Flow, Backend Stack Security and Refactor Assessment - 2026-05-24 Phase 2.

T19 -- Seller Price Manipulation After Offer Acceptance

Field Value
STRIDE Tampering
Affected assets Payment amounts, escrow funds
Actors Seller
Description The Negotiation Flow documents that "updateOffer does not enforce status... Current code allows the price change, which is dangerous post-payment." A seller can modify the offer price after the buyer has already paid, potentially inflating the amount or changing terms. The escrow holds the original amount, but the displayed/agreed amount could be tampered with.
Current state Vulnerable
Required mitigation (1) Reject updateOffer if status !== 'pending'. (2) Snapshot offer amount at payment creation time in the Payment document. (3) Use the Payment-embedded amount for all downstream operations, not the live offer. Reference: Platform Logical Audit - 2026-05-24 Finding 18.

T20 -- Delivery Confirmation Brute Force

Field Value
STRIDE Spoofing
Affected assets Escrow release trigger
Actors Buyer
Description The delivery confirmation code is a 6-digit number (Math.floor(100000 + Math.random()*900000)) with 900,000 possible combinations. There is no rate limiting on verification attempts. The "manual fast-track" allows the buyer to confirm delivery at any time, even before the seller has shipped. A buyer could brute-force the confirmation code to trigger release without actually receiving the item.
Current state Vulnerable
Required mitigation (1) Add Redis-backed rate limiting on delivery code verification (e.g., 5 attempts per 15 minutes per request). (2) Increase code entropy (alphanumeric, longer). (3) Restrict fast-track confirmation to status: 'delivery' only. (4) Add time-based invalidation. Reference: Platform Logical Audit - 2026-05-24 Finding 8.

T21 -- Unauthenticated Data Exfiltration

Field Value
STRIDE Information disclosure
Affected assets User personal data, payment history, notifications
Actors Unauthenticated attacker
Description Multiple endpoints accept a userId parameter without authentication or ownership verification: GET /api/payment/decentralized/history/:userId returns any user's payment history; the legacy notification router accepts ?userId= query parameter allowing notification read/modify for any user. The payment history endpoint exposes transaction hashes, amounts, counterparties, and wallet addresses.
Current state Vulnerable
Required mitigation (1) Add Bearer JWT authentication to all data-access endpoints. (2) Enforce ownership: the authenticated user's ID must match the requested userId (or require admin role). (3) Audit all parameterized routes for missing auth middleware. Reference: Platform Logical Audit - 2026-05-24 Finding 3.

T22 -- Verification Code Leakage via Logs

Field Value
STRIDE Information disclosure
Affected assets User credentials
Actors Insider threat, log viewer
Description The registration and password reset controllers log the generated 6-digit verification code to stdout via console.log in all environments, including production. Anyone with access to application logs (CloudWatch, Sentry breadcrumbs, docker logs) can read these codes and take over unverified accounts or reset passwords.
Current state Vulnerable
Required mitigation (1) Guard all verification code logging behind if (NODE_ENV !== 'production'). (2) Implement a log redaction formatter that strips sensitive fields. (3) Audit all console.log and logger calls for sensitive data. Reference: Registration Flow warning.

T23 -- Payment State Machine Inconsistency

Field Value
STRIDE Tampering / Repudiation
Affected assets Payment records, escrow state
Actors Race conditions, software bugs
Description The platform has multiple overlapping state machines for the same entities. Payment has both status and escrowState that must remain consistent. The Dispute entity has three mutually incompatible status/action enum sets across the Data Model, API Reference, and Flow documents. The PurchaseRequest has different status enums across three documents. Ghost states exist (confirmed, partial, finalized, archived) that no automated flow sets. This inconsistency creates opportunities for state confusion where a payment appears in one state from one code path and a different state from another.
Current state Vulnerable
Required mitigation (1) Create a single canonical enum set for each entity, documented in one place. (2) Enforce valid transitions in a centralized state machine service. (3) Reject invalid transitions at the service layer, not just the controller. (4) Remove ghost states or document the transitions that set them. Reference: Platform Logical Audit - 2026-05-24 Findings 5, 9, 20, 21.

6. Risk Summary Matrix

ID Threat Risk Level Current State Mitigation Owner Reference
T01 Fake payment proof (Web3) Critical Vulnerable Backend / Payment Task 2 subtask: Web3 verification hardening
T02 Webhook replay attack High Partially mitigated Backend / Payment Task 2 subtask: Webhook security spec
T03 Arbitrary Socket.IO room join High Vulnerable Backend / Realtime Task 2 subtask: Realtime authorization spec
T04 Stolen token reuse Critical Partially mitigated Backend / Auth Task 2 subtask: Session architecture
T05 Double payout / double release Critical Partially mitigated Backend / Payment Task 2 subtask: Funds ledger specification
T06 Dispute bypass (release during dispute) Critical Vulnerable Backend / Payment Task 2 subtask: Escrow state machine
T07 Email / registration abuse Medium Vulnerable Backend / Auth Task 2 subtask: Rate limiting
T08 AI cost abuse High Vulnerable Backend / AI Task 2 subtask: Rate limiting + auth
T09 Admin privilege escalation High Partially mitigated Backend / Auth Task 2 subtask: Authorization matrix
T10 Passkey / WebAuthn bypass High Vulnerable Backend / Auth Task 2 subtask: Disable or fix passkeys
T11 Web3 payment with wrong data (unauthenticated endpoints) Critical Vulnerable Backend / Payment Task 2 subtask: Auth on all financial endpoints
T12 Rate limit bypass High Vulnerable Backend / Infrastructure Task 2 subtask: Rate limiting
T13 XSS leading to token theft High Partially mitigated Frontend / Backend Task 2 subtask: Session architecture
T14 npm supply-chain compromise High Partially mitigated DevOps / Backend Task 2 subtask: Supply-chain policy
T15 CSRF on state-changing endpoints Low Mitigated Backend / Auth Monitor when cookie migration occurs
T16 Deep-link / parameter tampering (Telegram) Medium Partially mitigated Backend / Telegram Task 2 subtask: Telegram initData verification
T17 Payment provider / RPC outage Medium Partially mitigated DevOps / Backend Task 2 subtask: Operational runbooks
T18 Insider fund manipulation Critical Vulnerable Security / Operations Task 2 subtask: Multi-sig wallet + ledger
T19 Seller price manipulation post-acceptance Medium Vulnerable Backend / Marketplace Task 2 subtask: Offer status enforcement
T20 Delivery confirmation brute force Medium Vulnerable Backend / Marketplace Task 2 subtask: Rate limiting + code entropy
T21 Unauthenticated data exfiltration High Vulnerable Backend / All Task 2 subtask: Auth on all data endpoints
T22 Verification code leakage via logs Medium Vulnerable Backend / Auth Immediate: remove log statements
T23 Payment state machine inconsistency High Vulnerable Backend / Payment Task 2 subtask: Canonical state machine

Risk distribution

Risk Level Count Threat IDs
Critical 6 T01, T04, T05, T06, T11, T18
High 10 T02, T03, T08, T09, T10, T12, T13, T14, T21, T23
Medium 6 T07, T16, T17, T19, T20, T22
Low 1 T15
Total 23

7. Assumptions and Constraints

7.1 In scope

  • The Express 5 backend API server and all routes documented in Backend Architecture.
  • The Socket.IO realtime layer as documented in Real-time Layer.
  • The SHKeeper payment integration (pay-in webhook, payout API).
  • The Web3/direct-wallet payment path (on-chain verification).
  • The escrow state machine and fund custody model.
  • The dispute lifecycle and its interaction with escrow.
  • Authentication flows (email/password, Google OAuth, passkey/WebAuthn).
  • Admin operations surface (dashboard, manual payouts, user management).
  • Frontend token storage and session management.
  • Infrastructure: single Docker host, CloudFlare/Nginx proxy, Watchtower deployment.
  • npm supply chain for both frontend and backend.
  • Telegram Mini App integration surface.

7.2 Out of scope (for this iteration)

  • Physical security of hosting infrastructure.
  • Social engineering attacks against platform operators (addressed partially by insider threat mitigations).
  • Cryptographic weaknesses in blockchain protocols (BSC, Ethereum assumed secure).
  • SHKeeper application internals (assumed to be a trusted component operated by the platform).
  • Third-party email provider security (SMTP provider assumed secure).
  • Client-side malware on user devices.
  • Regulatory compliance (KYC/AML requirements not covered here).
  • DNS hijacking (mitigated by CloudFlare proxy assumption).

7.3 Assumptions

  1. Hosting is a single Docker host behind CloudFlare with Nginx. Internal service-to-service communication (MongoDB, Redis) is on localhost without TLS. This is acceptable for a single-host deployment but must be revisited if the architecture scales to multiple nodes.

  2. CloudFlare provides DDoS mitigation and TLS termination. The threat model assumes HTTPS is enforced externally and the Nginx-to-Express hop is HTTP on localhost.

  3. SHKeeper is self-hosted and under platform control. The webhook secret is shared only between the backend and the SHKeeper instance. If SHKeeper is compromised, webhook integrity is lost.

  4. MongoDB and Redis are not exposed to the internet. They are bound to localhost on the Docker host. If this assumption is violated (e.g., misconfigured Docker network), the entire data layer is exposed.

  5. The escrow wallet private key is stored securely by the platform operator. The threat model assumes the key is not in the codebase or env files. If this assumption is wrong, the exposure is total.

  6. Admin accounts are created via bootstrap seed and manually. There is no self-service admin creation flow. The seed admin credentials must be rotated before any public launch.

  7. The frontend is a Next.js application served from the same origin or a CORS-allowlisted origin. Cross-origin access is restricted by the CORS configuration. This assumption must hold for CSRF protection via Authorization header to be effective.

7.4 Constraints

  1. Single-host deployment limits defense-in-depth. Network segmentation between services is not possible on a single host.

  2. No background job queue. All async work is inline with request handlers or uses setTimeout/setInterval. This limits the ability to implement reliable retry, reconciliation, and scheduled operations.

  3. No external penetration testing has been performed. All findings are based on code review and documentation analysis.

  4. Documentation and implementation may diverge. Several findings in the Platform Logical Audit - 2026-05-24 show that documentation describes security controls that may not be implemented in code. This threat model is based on documented behavior and known gaps; the actual attack surface may be larger.

  5. The platform is in pre-launch state. Many security controls are documented as recommended but not yet implemented. This threat model reflects the current state, not the target state.


Appendix A -- STRIDE Category Reference

Category Description
S -- Spoofing Pretending to be another user or system
T -- Tampering Modifying data or code
R -- Repudiation Denying having performed an action
I -- Information disclosure Exposing data to unauthorized parties
D -- Denial of service Making a system unavailable
E -- Elevation of privilege Gaining access beyond authorized level

Appendix B -- Threat-to-Mitigation Traceability

The following remediation documents (from the recommended documentation set in Backend Stack Security and Refactor Assessment - 2026-05-24) address specific threats:

Remediation Document Threats Addressed
Funds Ledger Specification T05, T18, T23
Escrow State Machine T06, T19, T23
Authorization Matrix T09, T21
Webhook Security Spec T02
Session and Auth Architecture T04, T10, T13, T22
Realtime Authorization Spec T03
Payment Provider Adapter Spec T01, T11, T17
Secure Build and Supply-Chain Policy T14
Operational Runbooks T17

This document was created on 2026-05-24 based on cross-referencing the platform audit documents, architecture documentation, and flow specifications. It must be reviewed and updated when: new payment providers are added, the escrow model changes, new authentication methods are introduced, the infrastructure topology changes, or significant new features are shipped.