feat: governance trading blacklist (compliance / incident response) (#308) #786
No reviewers
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic!786
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cursor/gitlab-issue-workflow-7e7d"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements GitLab #308: a governance-controlled trading blacklist on the factory (wallets, CW20 tokens, pairs). Tier 255 fee-discount blacklist is unchanged and does not stop trading.
MR fix (
f895768): Mergedmain(resolvedSwapPage.tsximport conflict — keptuseTradingBlacklist, dropped removedMevPostureNotice); fixed pre-commit (cargo fmt, clippy on pair blacklist guards,#[cfg(test)]onblacklist_tests).BlacklistWallet/Token/Pair+ unban msgs;BlacklistCheckquery; storage maps + eventsblacklist_tests.rsmatrix (wallet/token/pair, router, unban, auth)useTradingBlacklist, banners + disabled CTAs on Trade/Swap/Pool; SwapPage probes all route hops (local BFS, native, indexer-solved multihop)GET /api/v1/compliance/blacklist-check(LCD proxy)Acceptance checklist
cd smartcontracts && cargo test -p cl8y-dex-tests blacklist_non_governance_cannot_blacklist_walletwallet_blacklist_blocks_swap_lp_limits_and_unban_restoresrouter_multihop_rejects_blacklisted_walletuseTradingBlacklisthooknpm test -- --run SwapPagedocs/security-model.md+ ADR 0003cargo test -p cl8y-dex-tests --lib(370 tests)make lint-frontendcd indexer && cargo checkcd indexer && cargo test --lib(113 tests)git merge origin/main(SwapPage conflict resolved)Third-party verification
After deploy: governance
BlacklistWalleton test wallet → confirm swap rejected on LCD;UnblacklistWallet→ swap succeeds.Follow-ups
Closes #308
mentioned in issue #308
changed the description
changed the description
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
9d8c9962c5. Configure here.Swap page skips token blacklist
High Severity
SwapPagecallsuseTradingBlacklistwith atokensproperty that the hook does not accept, sofromTokenandtoTokenare never passed intogetTradingBlacklistCheck. Under strict TypeScript this failstsc -b; if it compiled, the Swap UI would only honor wallet-level blocks, not token or pair blacklist signals that Trade and Pool already probe.Reviewed by Cursor Bugbot for commit
9d8c9962c5. Configure here.Security review (automated)
Commit reviewed:
9d8c9962c514484de2bfea10532dd68a86728dcbScope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router guards (incl. fail-open for legacy factory), dAppuseTradingBlacklistUX gates, indexerGET /api/v1/compliance/blacklist-check, tests and docs.Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and LCD/API abuse. No exploitable medium+ issues identified on this diff.
ensure_governanceon allBlacklist*/Unblacklist*executes; addresses validated; pair must be registeredtraderincluded on CW20 swap hooks; router probes wallet + route tokens/pairsBlacklistCheckinternal_err(generic 500 body)Note (below medium):
blacklist-checkaccepts unbounded comma-separatedtokens/pairs(one LCD call, O(n) factory loop). Consider caps orlcd_heavythrottling if abuse becomes noisy — availability hardening only, not authz/funds impact.added 1 commit
96229f04- fix: pass token0/token1 to useTradingBlacklist on Swap pageCompare with previous version
resolved all threads
changed the description
Security review (automated)
Commit reviewed:
96229f0429885ef1e89a727a4ff95346e456a5deScope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router guards (incl. fail-open for legacy factory), dAppuseTradingBlacklistUX gates, indexerGET /api/v1/compliance/blacklist-check, tests and docs. Re-reviewed after SwapPage token-probe fix (96229f04).Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and LCD/API abuse. No exploitable medium+ issues identified on this diff.
ensure_governanceon allBlacklist*/Unblacklist*executes; addresses validated; pair blacklist requiresPAIR_ADDR_REGISTEREDReceivecheckstoken_senderand optionaltrader; router probes wallet + route tokens/pairsBlacklistChecktoken0/token1correctlyfactory_addressonly (no SSRF); LCD errors mapped viainternal_err(generic 500 body)9d8c9962review (0 findings) still applies; no new attack paths in96229f04fix commitNote (below medium):
blacklist-checkaccepts unbounded comma-separatedtokens/pairs(one LCD call, O(n) factory loop) and sits on the standard API rate limit rather thanlcd_heavy. Consider input caps orlcd_heavythrottling if abuse becomes noisy — availability hardening only, not authz/funds impact.Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
96229f0429. Configure here.Swap omits pair blacklist probe
Medium Severity
The Swap page’s
useTradingBlacklistcall only sends the connected wallet and the two swap tokens toBlacklistCheck, not the direct pool address or multihop pair list. When governance blacklists a pool but leaves its CW20s off the token list, the factory reportsblocked: falseand the swap button stays enabled until the transaction fails on-chain.Additional Locations (1)
frontend-dapp/src/hooks/useTradingBlacklist.ts#L15-L34Reviewed by Cursor Bugbot for commit
96229f0429. Configure here.changed this line in version 3 of the diff
changed this line in version 3 of the diff
added 1 commit
eeda468f- fix(frontend): include swap route pairs in trading blacklist probeCompare with previous version
resolved all threads
changed the description
Stale Security Review comment
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
eeda468f17. Configure here.Swap page incomplete blacklist probe
Medium Severity
The swap page’s
useTradingBlacklistcall only sends the selectedfromToken/toTokenand pair addresses derived from the local BFSrouteornativeRouteInfo. It ignores hop tokens and pools on indexer-solved multihop paths, so a blacklisted intermediate CW20 or pair can leave the swap CTA enabled while the router rejects the tx on-chain.Reviewed by Cursor Bugbot for commit
eeda468f17. Configure here.Security review (automated)
Commit reviewed:
eeda468f170cec3b9baf20fd5a6ec0b5051614dfScope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router guards (incl. fail-open for legacy factory), dAppuseTradingBlacklistUX gates (incl. SwapPage multihop pair probe ineeda468f), indexerGET /api/v1/compliance/blacklist-check, tests and docs.Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and LCD/API abuse. No exploitable medium+ issues identified on this diff.
ensure_governanceon allBlacklist*/Unblacklist*executes; addresses validated; pair blacklist requiresPAIR_ADDR_REGISTEREDReceivecheckstoken_senderand optionaltrader; router probes wallet + route tokens/pairsBlacklistCheckeeda468fcloses pair-only Swap UX gap without weakening chain checksinternal_errPrior Bugbot threads on SwapPage token/pair probe gaps are UX completeness issues; on-chain enforcement remains intact — not rated medium+ for this security review.
changed this line in version 4 of the diff
added 1 commit
ccbb211a- fix(swap): include indexer route ops in blacklist probeCompare with previous version
changed the description
resolved all threads
Security review (automated)
Commit reviewed:
ccbb211a8e8a4199cfb93759a6aa1b17675f2ef6Scope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router guards (incl. fail-open for legacy factory), dAppuseTradingBlacklistUX gates (incl. SwapPage multihop/indexer route probe inccbb211), indexerGET /api/v1/compliance/blacklist-check, tests and docs.Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and unsafe deserialization.
ensure_governancegates allBlacklist*/Unblacklist*executes;BlacklistCheckis read-only withaddr_validateon inputs. Pair guards cover swap/LP/limits (incl. optionaltrader); router probes wallet + hop tokens/pairs. Fail-open when factory lacksBlacklistCheckis a deployment-compat behavior, not an attacker-controlled bypass once factory 1.5.0 is live.blacklist-checkproxies only the configuredFACTORY_ADDRESS(no caller-controlled upstream URL). LCD failures map to genericinternal_errbodies (no URL/path leakage). Endpoint is on the standard rate-limited router (single LCD query per request).dangerouslySetInnerHTML). Prior SwapPage probe gaps (token/pair/indexer-hop coverage) were fixed in96229f0,eeda468, andccbb211; remaining UI gaps would not bypass on-chain enforcement.No medium, high, or critical vulnerabilities with a plausible exploit path were identified on this diff.
added 39 commits
mainf8957689- Merge origin/main into cursor/gitlab-issue-workflow-7e7dCompare with previous version
changed the description
changed the description
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.
Reviewed by Cursor Bugbot for commit
f8957689f7. Configure here.Blacklist hook fails open
Medium Severity
useTradingBlacklistsetsblockedonly when cached data hasblocked === true. While the factory query is loading, or after it errors,blockedstays false and pages treat trading as allowed. Compliance UX can briefly or persistently show enabled CTAs for wallets or routes that are actually blacklisted until a successful refetch.Additional Locations (1)
frontend-dapp/src/pages/SwapPage.tsx#L728-L731Reviewed by Cursor Bugbot for commit
f8957689f7. Configure here.Blacklist shown as pair paused
Low Severity
LimitOrderMyPlacementsPanelreceivesisPairPaused={isTradeBlocked}, which combines pause and trading blacklist. Claim actions show “Unavailable (pair paused)” when the user is blocked by governance blacklist, not because the pool is paused, which misstates the restriction despite the separate blacklist banner above.Reviewed by Cursor Bugbot for commit
f8957689f7. Configure here.changed this line in version 6 of the diff
changed this line in version 6 of the diff
added 1 commit
b162fb0e- fix(frontend): fail-closed trading blacklist and correct claim copyCompare with previous version
changed the description
resolved all threads
Security review (automated)
Commit reviewed:
b162fb0e2f7717bb915fa164caae47ab6705dac6Scope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router guards (incl. documented fail-open for legacy factory), dAppuseTradingBlacklistUX gates (incl. SwapPage multihop probes, fail-closed pending/error inb162fb0), indexerGET /api/v1/compliance/blacklist-check, tests and docs. Re-reviewed after merge withmainand post-Bugbot fixes (96229f04,eeda468f,ccbb211a,b162fb0).Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and LCD/API abuse. No exploitable medium+ issues identified on this diff.
ensure_governanceon allBlacklist*/Unblacklist*executes; addresses validated; pair blacklist requiresPAIR_ADDR_REGISTEREDReceivecheckstoken_senderand optionaltrader; router probes wallet + route tokens/pairs; router always setstrader = senderon multihopBlacklistCheckb162fb0fail-closes while probe pending/erroredfactory_addressonly (no user-controlled contract target / SSRF); LCD errors mapped viainternal_err(generic 500 body)96229f04/eeda468f/ccbb211a; on-chain enforcement was intact throughout — UX-onlyNote (below medium):
blacklist-checkaccepts unbounded comma-separatedtokens/pairs(one LCD call, O(n) factory loop) and sits on the standard API rate limit rather thanlcd_heavy. Consider input caps orlcd_heavythrottling if abuse becomes noisy — availability hardening only, not authz/funds impact.Security review (automated)
Commit reviewed:
b162fb0e2f7717bb915fa164caae47ab6705dac6Scope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router enforcement (incl. fail-open when factory lacks query), dAppuseTradingBlacklistfail-closed UX (b162fb0), SwapPage multihop/indexer route probes, indexerGET /api/v1/compliance/blacklist-check, tests and docs.Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and unsafe deserialization.
Blacklist*/Unblacklist*executes callensure_governance;BlacklistCheckvalidates addresses before map lookups. Pairgate_trading_blacklistcovers swap (CW20 sender + optionaltrader), provide liquidity, and limit cancel/claim/update; router checks the CW20senderand enumerates hop tokens/pairs. Fail-open on missing factory query is intentional for unmigrated factories and does not grant non-governance list mutation.blacklist-checkproxies a single wasm smart query to configuredfactory_addressonly (no caller-controlled contract target). LCD failures useinternal_err(generic 500 body). Global rate limiting applies.useTradingBlacklisttreats pending/error as blocked (b162fb0); addresses are filtered toterra1prefixes before query. SwapPage derives tokens and pair addresses from local/native/indexer-solved routes. UI messages are static strings (no HTML injection). Claim CTAs useclaimsDisabledseparately from pair pause.Security review: no medium+ findings on this diff.
Prior Bugbot threads (fail-open hook, incomplete Swap probes) are addressed in
b162fb0and earlier commits on this branch; not re-reported.Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
b162fb0e2f. Configure here.Query errors block trading incorrectly
Medium Severity
useTradingBlacklistsetsblockedwhen the factoryBlacklistCheckquery is pending or errored, not only whendata.blockedis true. Swap, pool, trade, and expired-limit claim CTAs then show “Trading restricted” and disable actions even for users who are not blacklisted, including during LCD outages or transient query failures.Reviewed by Cursor Bugbot for commit
b162fb0e2f. Configure here.added 1 commit
878937a6- fix: only block trading when blacklist query returns blocked trueCompare with previous version
changed the description
resolved all threads
mentioned in commit
a46a9ccb77Security review (automated)
Commit reviewed:
878937a6b4eda86f98b5249dab2adfda6d6175dfScope: Governance trading blacklist (#308) — factory
Blacklist*/BlacklistCheck, pair/router on-chain guards (incl. documented fail-open when factory lacks query), dAppuseTradingBlacklistUX gates (re-reviewed after878937afail-open-on-pending/error fix), indexerGET /api/v1/compliance/blacklist-check, integration tests, docs.Outcome:
FINDINGS: 0medium+Inline threads: none
Summary
Reviewed added/modified paths for authz bypass, injection, SSRF/XSS, secret leakage, and unsafe deserialization. Traced attacker-controlled inputs (query params, CW20 hook
trader, multihop route tokens/pairs) to enforcement sinks.On-chain: Factory blacklist mutations are gated by
ensure_governance.BlacklistCheckonly evaluates caller-supplied addresses (no full-list enumeration). Pair guards run before swap, LP, limit place/cancel/claim/update, and check bothcw20_msg.senderand optionaltrader. Router multihop collects hop tokens/pairs and checkssender. Fail-open when the factory query is missing is documented for pre-1.5.0 factories; on upgraded deployments the query succeeds and blocks apply.Indexer:
/api/v1/compliance/blacklist-checkproxies a single LCD smart-query to the configured factory address (no user-controlled contract target → no SSRF). Params are serialized into the query body; global API rate limiting applies.dApp:
useTradingBlacklistblocks CTAs only whendata.blocked === true(878937a). Pending/error states no longer deny service to non-blacklisted users; on-chain enforcement remains authoritative, so this is a UX availability choice, not a trading bypass.Prior Bugbot threads (SwapPage probe gaps, fail-closed pending state) were addressed in earlier commits; the latest diff does not reintroduce exploitable paths.
Security review: no medium+ findings on this diff.