docs: SEC-I01 LLM attacker prompt pack [SEC-I01] #446

Closed
opened 2026-06-30 15:15:53 +00:00 by totdking · 9 comments
totdking commented 2026-06-30 15:15:53 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-30 15:21:57 +00:00 (Migrated from gitlab.com)

Summary

LLM attacker prompt pack created and saved at help/sec-i-prompt-pack.md. The pack models all 10 historical exploit themes from the checklist preamble against this repo's specific code, generates exploit hypotheses, and triages each result.

What Was Done

Built 17 exploit hypotheses (H01-H17) derived from all 10 historical exploit themes in the checklist preamble, plus two novel hypotheses from direct codebase review (H16, H17). Each hypothesis includes a verbatim adversarial prompt parameterized with actual file paths and line numbers, the generated exploit scenario, and a triage verdict.

Full prompt pack artifact: help/sec-i-prompt-pack.md


Covered (6)

  • H02: LP share inflation via first-depositor manipulation -- MINIMUM_LIQUIDITY burn of 1,000 tokens on first deposit prevents the attack (pair/src/contract.rs lines 1614-1622). Same defense as Uniswap v2 and Astroport.
  • H03: Repeated add/remove profit extraction (Osmosis-style loop) -- Floor division rounds down shares issued and down on withdrawal. Rounding direction goes against the attacker on both legs.
  • H06: Governance key replay or spoofed factory message -- Standard admin key compromise scenario. Documented in docs/security-model.md and docs/operator-secrets.md. Governance intended as multisig for production.
  • H11: Concurrent limit-book depth walks fan out unbounded LCD queries -- limit-book uses cursor pagination not depth parameter. 10 RPS per-IP on LCD-heavy routes bounds fanout.
  • H13: Fake pair contract emits wasm events to inject synthetic volume -- Factory provenance check in pair_discovery.rs (lines 157-199) confirms factory maps asset tuple to the exact emitting pair address. Clone pairs cannot pass.
  • H17: Limit order partial fill followed by cancel returns full original escrow -- Orderbook fill updates order.remaining atomically before cancel is reachable. checked_sub on PENDING_ESCROW prevents over-withdrawal.

Not Applicable (2)

  • H01: IBC hooks reentrancy via submessage reply chain -- No IBC receive, ack, or timeout handlers exist in any contract. Reserves committed to storage before hooks dispatch. CosmWasm message model prevents mid-execution callbacks.
  • H12: SQL injection via sort or interval query parameters -- All sort values validated against Rust enum. All interval values validated against VALID_INTERVALS array. All remaining inputs use SQLx QueryBuilder push_bind() parameterized binding. No user input reaches raw SQL.

Risk Accepted (4)

  • H04: Sandwich via large reserve shift before multihop settlement -- Standard AMM sandwich. max_spread enforced per hop (pair/src/contract.rs lines 824-878). min_return enforced globally by router. Limit book reduces surface. No private mempool on Terra Classic. Accepted for small-TVL launch.
  • H08: Expert Mode persistence in localStorage enables high-slippage swaps -- Requires explicit confirmation phrase with visible warning. Standard DEX design pattern. Social engineering vector applies to all DEXes with this feature. Not a code defect.
  • H10: IPv6 /64 rotation bypasses per-IP rate limit on LCD-heavy routes -- Indexer defaults to IPv4-only (api/mod.rs Domain::IPV4). IPv6 only when API_IPV6_ENABLED=1 is explicitly set. Acceptable for small-TVL launch with IPv4 default.
  • H16: Blacklist UI gate bypassed via 15-second React Query stale cache -- On-chain contract enforces blacklist at execution time regardless of UI state. User loses gas only, not funds. Acceptable for small TVL.

Real Gap (4, feed into SEC-I02)

  • H05: Fee-on-transfer CW20 drains limit order escrow -- Maker fee deducted from declared amount at placement time (limit_placement.rs lines 183-287). Pair records declared_amount - maker_fee in PENDING_ESCROW but receives declared_amount - cw20_fee in real balance. Shortfall = cw20 fee-on-transfer amount per order. Not documented as explicit constraint on whitelist code ID candidates.
  • H07: Signing modal shows symbol only -- malicious indexer substitutes pair contract -- SwapPreSubmitSummary.tsx (lines 48, 70) shows token symbols only, no pair contract address. Frontend validates token_in and token_out only (SwapPage.tsx line ~531). Malicious VITE_INDEXER_URL can substitute pair contracts. Impact bounded by min_return but skim within slippage tolerance is possible.
  • H09: Route intermediate tokens not cross-validated between display and submitted operations -- swapRouteDisplay.ts deriveSwapSubmitRouteSource (lines 115-131) uses indexer operations for both display and submission without cross-validating intermediate token addresses. Malicious indexer can display one route and submit another. Impact bounded by min_return.
  • H14: Empty FACTORY_ADDRESS skips factory provenance check in non-prod RUN_MODE -- pair_discovery.rs (lines 163-168) logs warning and returns Ok(()) when FACTORY_ADDRESS is empty. RUN_MODE=prod requires non-empty but non-prod deployments have no guard. No CI check for staging.

Partially Covered (1)

  • H15: Stale env address causes frontend to call wrong factory or router on mainnet -- No funds lost (transactions revert), but frontend is broken and blacklist state is stale. Partially covered by existing issue #442 (env-to-chain address comparison gap). Fully addressed if #442 is resolved with a VITE_* cross-check script.

Artifact

help/sec-i-prompt-pack.md

Verification Checklist

  • All 10 historical exploit themes addressed (T1-T10)
  • Each prompt parameterized with actual file paths and line numbers
  • Each hypothesis has a triage verdict
  • Real Gap items mapped to required follow-up actions for SEC-I02

Labels

security, pre-launch ~"block:log_only"

Cc : @PlasticDigits

### Summary LLM attacker prompt pack created and saved at `help/sec-i-prompt-pack.md`. The pack models all 10 historical exploit themes from the checklist preamble against this repo's specific code, generates exploit hypotheses, and triages each result. ### What Was Done Built 17 exploit hypotheses (H01-H17) derived from all 10 historical exploit themes in the checklist preamble, plus two novel hypotheses from direct codebase review (H16, H17). Each hypothesis includes a verbatim adversarial prompt parameterized with actual file paths and line numbers, the generated exploit scenario, and a triage verdict. Full prompt pack artifact: `help/sec-i-prompt-pack.md` --- ### Covered (6) - H02: LP share inflation via first-depositor manipulation -- MINIMUM_LIQUIDITY burn of 1,000 tokens on first deposit prevents the attack (pair/src/contract.rs lines 1614-1622). Same defense as Uniswap v2 and Astroport. - H03: Repeated add/remove profit extraction (Osmosis-style loop) -- Floor division rounds down shares issued and down on withdrawal. Rounding direction goes against the attacker on both legs. - H06: Governance key replay or spoofed factory message -- Standard admin key compromise scenario. Documented in docs/security-model.md and docs/operator-secrets.md. Governance intended as multisig for production. - H11: Concurrent limit-book depth walks fan out unbounded LCD queries -- limit-book uses cursor pagination not depth parameter. 10 RPS per-IP on LCD-heavy routes bounds fanout. - H13: Fake pair contract emits wasm events to inject synthetic volume -- Factory provenance check in pair_discovery.rs (lines 157-199) confirms factory maps asset tuple to the exact emitting pair address. Clone pairs cannot pass. - H17: Limit order partial fill followed by cancel returns full original escrow -- Orderbook fill updates order.remaining atomically before cancel is reachable. checked_sub on PENDING_ESCROW prevents over-withdrawal. --- ### Not Applicable (2) - H01: IBC hooks reentrancy via submessage reply chain -- No IBC receive, ack, or timeout handlers exist in any contract. Reserves committed to storage before hooks dispatch. CosmWasm message model prevents mid-execution callbacks. - H12: SQL injection via sort or interval query parameters -- All sort values validated against Rust enum. All interval values validated against VALID_INTERVALS array. All remaining inputs use SQLx QueryBuilder push_bind() parameterized binding. No user input reaches raw SQL. --- ### Risk Accepted (4) - H04: Sandwich via large reserve shift before multihop settlement -- Standard AMM sandwich. max_spread enforced per hop (pair/src/contract.rs lines 824-878). min_return enforced globally by router. Limit book reduces surface. No private mempool on Terra Classic. Accepted for small-TVL launch. - H08: Expert Mode persistence in localStorage enables high-slippage swaps -- Requires explicit confirmation phrase with visible warning. Standard DEX design pattern. Social engineering vector applies to all DEXes with this feature. Not a code defect. - H10: IPv6 /64 rotation bypasses per-IP rate limit on LCD-heavy routes -- Indexer defaults to IPv4-only (api/mod.rs Domain::IPV4). IPv6 only when API_IPV6_ENABLED=1 is explicitly set. Acceptable for small-TVL launch with IPv4 default. - H16: Blacklist UI gate bypassed via 15-second React Query stale cache -- On-chain contract enforces blacklist at execution time regardless of UI state. User loses gas only, not funds. Acceptable for small TVL. --- ### Real Gap (4, feed into SEC-I02) - H05: Fee-on-transfer CW20 drains limit order escrow -- Maker fee deducted from declared amount at placement time (limit_placement.rs lines 183-287). Pair records declared_amount - maker_fee in PENDING_ESCROW but receives declared_amount - cw20_fee in real balance. Shortfall = cw20 fee-on-transfer amount per order. Not documented as explicit constraint on whitelist code ID candidates. - H07: Signing modal shows symbol only -- malicious indexer substitutes pair contract -- SwapPreSubmitSummary.tsx (lines 48, 70) shows token symbols only, no pair contract address. Frontend validates token_in and token_out only (SwapPage.tsx line \~531). Malicious VITE_INDEXER_URL can substitute pair contracts. Impact bounded by min_return but skim within slippage tolerance is possible. - H09: Route intermediate tokens not cross-validated between display and submitted operations -- swapRouteDisplay.ts deriveSwapSubmitRouteSource (lines 115-131) uses indexer operations for both display and submission without cross-validating intermediate token addresses. Malicious indexer can display one route and submit another. Impact bounded by min_return. - H14: Empty FACTORY_ADDRESS skips factory provenance check in non-prod RUN_MODE -- pair_discovery.rs (lines 163-168) logs warning and returns Ok(()) when FACTORY_ADDRESS is empty. RUN_MODE=prod requires non-empty but non-prod deployments have no guard. No CI check for staging. --- ### Partially Covered (1) - H15: Stale env address causes frontend to call wrong factory or router on mainnet -- No funds lost (transactions revert), but frontend is broken and blacklist state is stale. Partially covered by existing issue #442 (env-to-chain address comparison gap). Fully addressed if #442 is resolved with a VITE\_\* cross-check script. ### Artifact `help/sec-i-prompt-pack.md` ### Verification Checklist - [x] All 10 historical exploit themes addressed (T1-T10) - [x] Each prompt parameterized with actual file paths and line numbers - [x] Each hypothesis has a triage verdict - [x] Real Gap items mapped to required follow-up actions for SEC-I02 ### Labels `security`, `pre-launch` ~"block:log_only" Cc : @PlasticDigits
totdking commented 2026-06-30 18:37:54 +00:00 (Migrated from gitlab.com)

mentioned in issue #381

mentioned in issue #381
PlasticDigits commented 2026-06-30 22:10:08 +00:00 (Migrated from gitlab.com)

@totdking please make an mr to the docs folder including the help/sec-i-prompt-pack.md

@totdking please make an mr to the docs folder including the help/sec-i-prompt-pack.md
totdking commented 2026-07-01 18:04:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #472

mentioned in issue #472
totdking commented 2026-07-01 18:45:59 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1006

mentioned in merge request !1006
totdking commented 2026-07-02 16:13:11 +00:00 (Migrated from gitlab.com)

mentioned in commit 9ff4ea7b60

mentioned in commit 9ff4ea7b6091af242260e3566c86b126f590411c
totdking commented 2026-07-02 16:14:08 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1007

mentioned in merge request !1007
totdking commented 2026-07-02 16:17:06 +00:00 (Migrated from gitlab.com)

MR made in !1007

When merged, this issue will be closed on my end @PlasticDigits

MR made in !1007 When merged, this issue will be closed on my end @PlasticDigits
PlasticDigits commented 2026-07-03 07:54:08 +00:00 (Migrated from gitlab.com)

mentioned in commit 4b74383025

mentioned in commit 4b7438302565d441a3edb53cb7b8831250760aaa
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-07-03 07:54:08 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#446
No description provided.