Skip to content

fix: fail closed for RWA geoblocking#7621

Draft
fairlighteth wants to merge 10 commits into
developfrom
deepsec/medium-05-rwa-geoblock-hardening
Draft

fix: fail closed for RWA geoblocking#7621
fairlighteth wants to merge 10 commits into
developfrom
deepsec/medium-05-rwa-geoblock-hardening

Conversation

@fairlighteth

@fairlighteth fairlighteth commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

What changed

  • Treat unresolved RWA feature flags, geolocation, and restricted-token metadata as pending or blocked instead of allowing trade confirmation.
  • Evaluate both sides of an RWA trade and apply the result consistently to swap, Yield, ETH-flow, token import, token-list visibility, and consent continuation.
  • Re-check RWA status when consent is confirmed, while preserving ETH-flow's wrapped-token and forced-price-confirmation continuation.
  • Keep the last known good restricted-token policy on refresh failures, refresh it when its TTL expires, and stop using mutable browser cache as the runtime policy source.
  • Preserve CoW Shed proxy verification state and block bridge trades when proxy setup is invalid.
  • Keep the widget token-list work split into fix: enforce widget token list restrictions #7834.

Why

  • Closes the DeepSec findings RWA checks fail open before restricted-token metadata is available, RWA trade confirmation can fail open while restriction metadata is unavailable, and RWA restricted-token checks fail open while lists load or partially fail.
  • Closes Only one side of a two-token RWA trade is evaluated, EthFlow swap continuation bypasses RWA consent gate, and Account-proxy verification failures are collapsed into an unblocked state.
  • Closes the URL-spoofing and failed-geo-lookup paths in Token-list geoblocking can be bypassed by spoofing widget mode or blocking geo lookup.
  • Partially addresses RWA/geoblock enforcement fails open when client flags or restricted-token data are unavailable and RWA list blocking fails open when geolocation or the feature flag is unavailable: unresolved and failed client states now fail closed, but a deliberately false or tampered client-side flag is not a trusted enforcement boundary.
  • A post-fix DeepSec run still reports RWA geoblock and consent enforcement depends on client-side feature flag state. Closing that remaining HIGH finding requires backend or orderbook enforcement.

QA Testing

Preview URL QA:

  • Swap branch preview: with the RWA geoblock flag enabled, connect a wallet and exercise an RWA trade through standard swap, Yield, and native-asset ETH-flow. Pending or restricted checks must not open confirmation; when consent is requested, accepting it must resume the same flow.

Developer verification:

  • Focused tests cover pending and failed geo checks, both-token evaluation, consent gating, invalid proxy setup, partial restricted-list failures, stale cache handling, cache expiry, and stale geo-response cancellation.
  • The targeted RWA/trade-validation and shared-token test suites pass, and the swap frontend typecheck passes.

Reviewer note:

  • Blocked-country and failed-network states are covered deterministically in tests. The preview behavior depends on the tester's LaunchDarkly and geolocation state.
  • This PR hardens the frontend but does not claim to make client-side RWA checks authoritative.

Preview URLs

Surface URL
swap-dev - branch preview URL https://swap-dev-git-deepsec-medium-05-rwa-geoblock-67bda2-cowswap-dev.vercel.app
explorer-dev - branch preview URL https://explorer-dev-git-deepsec-medium-05-rwa-geobl-4651fd-cowswap-dev.vercel.app
cowfi - branch preview URL https://cowfi-git-deepsec-medium-05-rwa-geoblock-hardening-cowswap.vercel.app
storybook - branch preview URL https://storybook-git-deepsec-medium-05-rwa-geoblock-9b1619-cowswap-dev.vercel.app
widget-configurator - branch preview URL https://widget-configurator-git-deepsec-medium-05-rw-379363-cowswap-dev.vercel.app

@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview Jul 9, 2026 5:43pm
explorer-dev Ready Ready Preview Jul 9, 2026 5:43pm
storybook Ready Ready Preview Jul 9, 2026 5:43pm
swap-dev Ready Ready Preview Jul 9, 2026 5:43pm
widget-configurator Ready Ready Preview Jul 9, 2026 5:43pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Jul 9, 2026 5:43pm
sdk-tools Ignored Ignored Preview Jul 9, 2026 5:43pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2348dbd2-88be-4197-9ef6-827eec457057

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch deepsec/medium-05-rwa-geoblock-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 6, 2026

Copy link
Copy Markdown

Deploying explorer-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 84e4a42
Status: ✅  Deploy successful!
Preview URL: https://d8da9364.explorer-dev-dxz.pages.dev
Branch Preview URL: https://deepsec-medium-05-rwa-geoblo.explorer-dev-dxz.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 6, 2026

Copy link
Copy Markdown

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 84e4a42
Status: ✅  Deploy successful!
Preview URL: https://508c4090.swap-dev-5u6.pages.dev
Branch Preview URL: https://deepsec-medium-05-rwa-geoblo.swap-dev-5u6.pages.dev

View logs

@fairlighteth

Copy link
Copy Markdown
Contributor Author
AI Review (Codex GPT-5, worked 2m): no new non-duplicate findings

Review completed. I found no new non-duplicate comments worth posting.

Review scope and related context

Related context checked:

  • libs/tokens/src/updaters/TokensListsUpdater/index.tsx: current code resets the token-list cache when curated-only mode relaxes, so the full default list set can refetch immediately.
  • apps/cowswap-frontend/src/modules/rwa/hooks/useRwaTokenStatus.ts: current code consistently keeps the RWA gate fail-closed while feature flags, geo, or restricted-token metadata are unresolved.
  • apps/cowswap-frontend/src/modules/trade/hooks/useConfirmTradeWithRwaCheck.ts and apps/cowswap-frontend/src/modules/ethFlow/containers/EthFlow/hooks/useEthFlowActions.ts: the current diff applies the same pending/restricted/consent handling to both standard trade confirmation and EthFlow continuation.
  • There are still no human review threads on this PR; only deploy/status comments are present, so there were no active threads to de-duplicate against.

@fairlighteth

Copy link
Copy Markdown
Contributor Author
⚠️ AI Review (Codex GPT-5, worked 4m): geo-check race can re-enable curated mode after the flag turns off

Finding: stale api.country.is responses can override a later isGeoBlockEnabled=false result

  • Location: libs/tokens/src/updaters/TokensListsUpdater/index.tsx:119
  • The effect now starts the geo fetch before the geoblock flag has necessarily resolved. If that request is still in flight when LaunchDarkly later resolves isGeoBlockEnabled to false, the next effect run correctly calls setCuratedListOnly(false) and returns, but the older promise still resolves and calls setCuratedListOnly(isUsUser) (or true in catch).
  • That leaves the app back in curated-only mode even though geoblocking is disabled, which contradicts the PR’s fail-closed contract and can silently narrow the default token-list set again.

Suggested fix

  • Guard the async callbacks with an effect-local cancellation/staleness flag so only the latest [chainId, isGeoBlockEnabled] run can update curated mode.
  • Add a targeted updater test that simulates undefined/true -> false while the geo request is pending and asserts the stale response cannot switch curated mode back on.
Review scope and related context

This is separate from the existing comments on the PR, which are currently only deploy/status comments plus an earlier AI no-findings summary. There are still no human review threads covering this race.

🤖 Prompt for AI agents
Verify this finding against current code. Fix only if still valid, keep the change minimal, and validate with targeted tests.

Context:
- libs/tokens/src/updaters/TokensListsUpdater/index.tsx
- The geo fetch starts before isGeoBlockEnabled is guaranteed to be resolved.
- A later effect run can set curated mode to false when the flag resolves false, but the older fetch callbacks still call setCuratedListOnly(...) afterward.
- Expected fix: ignore stale async results from earlier effect runs, and add a regression test for the pending-fetch -> flag-false transition.

@fairlighteth fairlighteth force-pushed the deepsec/medium-05-rwa-geoblock-hardening branch from 856978f to d20d9b1 Compare July 9, 2026 16:14
fairlighteth and others added 3 commits July 9, 2026 17:24
…ardening' into deepsec/medium-05-rwa-geoblock-hardening

# Conflicts:
#	apps/cowswap-frontend/src/locales/en-US.po
#	apps/cowswap-frontend/src/modules/rwa/hooks/useRwaTokenStatus.ts
#	apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.test.ts
#	apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts
#	libs/tokens/src/hooks/useRestrictedTokensCache.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant