sec: leftover wrap/window/CMM admin — LCD attest + playbook close-out (AC-02) #697

Open
opened 2026-08-28 09:24:25 +00:00 by PlasticDigits · 3 comments
PlasticDigits commented 2026-08-28 09:24:25 +00:00 (Migrated from gitlab.com)

Gate

P1 ops / Chain K. Internal audit INTERNAL_GROK46_1787908099 AC-02. The accept queue stays on #526 (and #525, ustr-cmm#15, ust1-window#30). Do not reopen those tickets or move propose/schema work here.

This issue is the security close-out: LCD attestation that leftover wrap / window / CMM / minter powers are no longer on an EOA, plus in-repo REGISTRY + pause-playbook truth so operators do not pause with the wrong key.

Current codebase / chain state

#526 tracks columbus-5 powers not yet on DEX 2-of-3 terra1zlmv2xydxcusurtr6rl78wsvytdc6mfex6hep7.

Already on the 2-of-3 (per #526 + later runbook notes): factory, router, fee-discount, faucet, gem pair wasm admins, several token minters, UST1/cUSTC + UST1/USTR pair wasm, wrap-mapper app governance and (as of 2026-08-26 notes) mapper/treasury wasm admin. CMM treasury AcceptGovernanceTransfer was queued.

Still called out as EOA / wrap-stack cl8y2_admin terra1xsecn4… in current docs:

  • ust1-window + oracle config.governance (docs/runbooks/ust1-wrap-production-ops.md O6)
  • Possibly remaining ustr-cmm minters (USTR / cUSTC / cLUNC primary + wasm, vFDUSD wasm) — confirm live, do not trust the issue table alone
  • Bridge admin (cl8y-bridge-monorepo#135)

In-repo surfaces that consume those contracts as if they were honest:

  • Indexer wrap-fee ingest, hub USD, UST1 window fee rollups (UST1_WINDOW_ADDRESS)
  • dApp /ust1, wrap/unwrap quotes
  • scripts/rebalance-mint-ust1-lp.sh peg gate (indexer USTC/USD)
  • Pause playbooks that still say “who signs”

A leftover EOA can change unwrap fees, mint wrappers, or move the window oracle. This repo will display and route through those prints.

Why the new implementation is needed

#526 is a queue. It does not define LCD attestation, attack tests, or a fail-closed “docs match chain” gate. Without that, REGISTRY O6 and pause runbooks drift (already partially stale vs 2026-08-25/26 accepts). Operators can pause with the wrong key or miss that window/oracle is still an EOA.

Constraints / guardrails

  1. Do not move product minters off window/mapper/swap/bridge in this ticket. #526 already: keep product minters; add DEX as extra minter on cLUNC before moving that primary.
  2. Do not publish key material, passphrases, or signer PII. LCD admin/governance addresses only.
  3. Do not change wrap-mapper / window wasm in this repo (out of tree). Accepts happen in sister repos.
  4. Do not conflate pair TWAP with window effective_swap.
  5. In-repo edits are docs + verify script + playbook signer lines only, unless a code path still hardcodes cl8y2_admin.
  6. Close this issue only when LCD probes for the leftover list are recorded or each remaining EOA is explicitly accepted as residual with an owner and revisit date.

Relevant files

Path Role
#526 Accept queue (source of truth for “what is left”)
deployments/mainnet-ust1-wrap/REGISTRY.md O6 governance split
docs/runbooks/ust1-wrap-production-ops.md Pause who-signs; O6 table
docs/runbooks/wrap-mapper-pause.md Mapper signer (update if wasm admin moved)
docs/runbooks/key-custody.md Roster
docs/runbooks/emergency-commands.md Who can pause
docs/security-model.md Wasm admin / treasury trust
scripts/verify-issue-503.sh / wrap health probes Pattern for LCD config queries
Sister: ustr-cmm#15, ust1-window#30, cl8y-bridge-monorepo#135 Out-of-repo accepts
  1. Write scripts/qa/verify-issue-<N>.sh (or extend the #526 verify path) that, against columbus-5 LCD:
    • Queries wrap-mapper / treasury / window / oracle config.governance (and wasm ContractInfo.admin where the LCD supports it).
    • Prints a table: address, role, expected terra1zlmv2… vs leftover terra1xsecn4… vs other.
    • Exit 1 if a row that docs claim is 2-of-3 is still EOA. Exit 0 with RESIDUAL= lines for accepted leftovers (window/oracle until ust1-window#30).
  2. Update REGISTRY O6 + pause playbooks to match that table (no stale “wasm admin still EOA” if LCD says otherwise).
  3. On each leftover EOA: link the sister accept issue and the next date. Do not invent Telegram handles or new keys.
  4. Optional (nice): indexer/dApp copy on /ust1 when window governance is not the 2-of-3 — only if a single LCD probe already exists; do not add a new trust root.

Acceptance criteria

  • Live LCD table posted on this issue (UTC date + LCD URL) for mapper, treasury, window, oracle, and any minter #526 still lists.
  • REGISTRY O6 and pause playbooks match that table (no contradictory “who signs”).
  • make verify-issue-<N> re-runs the probe (fail-closed when COLUMBUS5_LCD / mainnet mode set; skip-with-message on Cloud Agent without LCD is OK if documented).
  • Every remaining EOA row has a sister issue link + owner. No silent leftovers.
  • #526 comment: “security close-out #<this> attests …” — do not close #526 from here unless the queue is empty.
  • No secrets in git or in this issue.

Test plan — happy / bad path

Path Expect
Probe vs current columbus-5 Table prints; exit 0 iff docs-expected rows match
Docs say 2-of-3, LCD says EOA Script exit 1
Docs say residual EOA, LCD says EOA Exit 0 + RESIDUAL line
LocalTerra / no LCD Skip or use fixture; do not fake mainnet green
Pause playbook dry-read Signer address equals LCD config.governance for that contract

Test plan — attack / abuse vectors

Vector Expect
Leftover EOA changes unwrap fee_unwrap_bps Users see new rate; this ticket does not stop that — it makes the key visible so #526 can finish. Record as residual until accept.
Leftover EOA migrates wrap-mapper wasm Same; wasm admin must appear on the table
Leftover EOA moves window effective_swap /ust1 + rebalance script follow it (Chain K). Residual until window accept.
Docs claim 2-of-3 while EOA still admin verify script fails (this is the bug this ticket catches)
Attacker social-engineers pause using old EOA Playbook lists the live signer so operators do not send txs to a retired key
Script logs mnemonic / keyring pass Forbidden; LCD queries only

Verification criteria

  1. Issue comment with LCD table (addresses + roles + expected vs live).
  2. make verify-issue-<N> documented; green on a host with columbus-5 LCD or explicit skip.
  3. rg cl8y2_admin / terra1xsecn4 in runbooks only appears on rows marked residual.
  4. Audit AC-02 noted as “attested; residuals listed” — full close when #526 queue is empty.
## Gate **P1 ops / Chain K.** Internal audit `INTERNAL_GROK46_1787908099` **AC-02**. The **accept queue stays on** [#526](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/526) (and [#525](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/525), ustr-cmm#15, ust1-window#30). **Do not reopen those tickets or move propose/schema work here.** This issue is the **security close-out**: LCD attestation that leftover wrap / window / CMM / minter powers are no longer on an EOA, plus in-repo REGISTRY + pause-playbook truth so operators do not pause with the wrong key. ## Current codebase / chain state #526 tracks columbus-5 powers not yet on DEX 2-of-3 `terra1zlmv2xydxcusurtr6rl78wsvytdc6mfex6hep7`. Already on the 2-of-3 (per #526 + later runbook notes): factory, router, fee-discount, faucet, gem pair wasm admins, several token minters, UST1/cUSTC + UST1/USTR pair wasm, wrap-mapper **app** governance and (as of 2026-08-26 notes) mapper/treasury **wasm admin**. CMM treasury `AcceptGovernanceTransfer` was queued. **Still called out as EOA / wrap-stack `cl8y2_admin` `terra1xsecn4…` in current docs:** - ust1-window + oracle `config.governance` (`docs/runbooks/ust1-wrap-production-ops.md` **O6**) - Possibly remaining ustr-cmm minters (USTR / cUSTC / cLUNC primary + wasm, vFDUSD wasm) — confirm live, do not trust the issue table alone - Bridge admin (cl8y-bridge-monorepo#135) In-repo surfaces that **consume** those contracts as if they were honest: - Indexer wrap-fee ingest, hub USD, UST1 window fee rollups (`UST1_WINDOW_ADDRESS`) - dApp `/ust1`, wrap/unwrap quotes - `scripts/rebalance-mint-ust1-lp.sh` peg gate (indexer USTC/USD) - Pause playbooks that still say “who signs” A leftover EOA can change unwrap fees, mint wrappers, or move the window oracle. This repo will **display and route through** those prints. ## Why the new implementation is needed #526 is a queue. It does not define LCD attestation, attack tests, or a fail-closed “docs match chain” gate. Without that, REGISTRY **O6** and pause runbooks drift (already partially stale vs 2026-08-25/26 accepts). Operators can pause with the wrong key or miss that window/oracle is still an EOA. ## Constraints / guardrails 1. **Do not** move product minters off window/mapper/swap/bridge in this ticket. #526 already: keep product minters; add DEX as **extra** minter on cLUNC before moving that primary. 2. **Do not** publish key material, passphrases, or signer PII. LCD admin/governance addresses only. 3. **Do not** change wrap-mapper / window wasm in this repo (out of tree). Accepts happen in sister repos. 4. **Do not** conflate pair TWAP with window `effective_swap`. 5. In-repo edits are **docs + verify script + playbook signer lines** only, unless a code path still hardcodes `cl8y2_admin`. 6. Close this issue only when LCD probes for the leftover list are recorded **or** each remaining EOA is explicitly accepted as residual with an owner and revisit date. ## Relevant files | Path | Role | |------|------| | [#526](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/526) | Accept queue (source of truth for “what is left”) | | `deployments/mainnet-ust1-wrap/REGISTRY.md` | **O6** governance split | | `docs/runbooks/ust1-wrap-production-ops.md` | Pause who-signs; O6 table | | `docs/runbooks/wrap-mapper-pause.md` | Mapper signer (update if wasm admin moved) | | `docs/runbooks/key-custody.md` | Roster | | `docs/runbooks/emergency-commands.md` | Who can pause | | `docs/security-model.md` | Wasm admin / treasury trust | | `scripts/verify-issue-503.sh` / wrap health probes | Pattern for LCD config queries | | Sister: ustr-cmm#15, ust1-window#30, cl8y-bridge-monorepo#135 | Out-of-repo accepts | ## Recommended direction 1. Write `scripts/qa/verify-issue-<N>.sh` (or extend the #526 verify path) that, against columbus-5 LCD: - Queries wrap-mapper / treasury / window / oracle `config.governance` (and wasm `ContractInfo.admin` where the LCD supports it). - Prints a table: address, role, expected `terra1zlmv2…` vs leftover `terra1xsecn4…` vs other. - Exit **1** if a row that docs claim is 2-of-3 is still EOA. Exit **0** with `RESIDUAL=` lines for accepted leftovers (window/oracle until ust1-window#30). 2. Update REGISTRY O6 + pause playbooks to match that table (no stale “wasm admin still EOA” if LCD says otherwise). 3. On each leftover EOA: link the sister accept issue and the next date. Do not invent Telegram handles or new keys. 4. Optional (nice): indexer/dApp copy on `/ust1` when window governance is not the 2-of-3 — **only** if a single LCD probe already exists; do not add a new trust root. ## Acceptance criteria - [ ] Live LCD table posted on this issue (UTC date + LCD URL) for mapper, treasury, window, oracle, and any minter #526 still lists. - [ ] REGISTRY O6 and pause playbooks match that table (no contradictory “who signs”). - [ ] `make verify-issue-<N>` re-runs the probe (fail-closed when `COLUMBUS5_LCD` / mainnet mode set; skip-with-message on Cloud Agent without LCD is OK if documented). - [ ] Every remaining EOA row has a sister issue link + owner. No silent leftovers. - [ ] #526 comment: “security close-out #&lt;this&gt; attests …” — do not close #526 from here unless the queue is empty. - [ ] No secrets in git or in this issue. ## Test plan — happy / bad path | Path | Expect | |------|--------| | Probe vs current columbus-5 | Table prints; exit 0 iff docs-expected rows match | | Docs say 2-of-3, LCD says EOA | Script exit 1 | | Docs say residual EOA, LCD says EOA | Exit 0 + `RESIDUAL` line | | LocalTerra / no LCD | Skip or use fixture; do not fake mainnet green | | Pause playbook dry-read | Signer address equals LCD `config.governance` for that contract | ## Test plan — attack / abuse vectors | Vector | Expect | |--------|--------| | Leftover EOA changes unwrap `fee_unwrap_bps` | Users see new rate; this ticket does not stop that — it **makes the key visible** so #526 can finish. Record as residual until accept. | | Leftover EOA migrates wrap-mapper wasm | Same; wasm admin must appear on the table | | Leftover EOA moves window `effective_swap` | `/ust1` + rebalance script follow it (Chain K). Residual until window accept. | | Docs claim 2-of-3 while EOA still admin | verify script fails (this is the bug this ticket catches) | | Attacker social-engineers pause using old EOA | Playbook lists the live signer so operators do not send txs to a retired key | | Script logs mnemonic / keyring pass | Forbidden; LCD queries only | ## Verification criteria 1. Issue comment with LCD table (addresses + roles + expected vs live). 2. `make verify-issue-<N>` documented; green on a host with columbus-5 LCD or explicit skip. 3. `rg cl8y2_admin` / `terra1xsecn4` in runbooks only appears on rows marked residual. 4. Audit AC-02 noted as “attested; residuals listed” — full close when #526 queue is empty.
PlasticDigits commented 2026-08-28 09:24:26 +00:00 (Migrated from gitlab.com)

marked as related to #526

marked as related to #526
PlasticDigits commented 2026-08-28 09:24:27 +00:00 (Migrated from gitlab.com)

marked as related to #525

marked as related to #525

Read-only columbus-5 LCD attestation

Queried https://terra-classic-lcd.publicnode.com at 2026-09-24 09:38:26 UTC, height 30540960, with VERIFY697_MAINNET=1 make verify-issue-697: PASS=4, RESIDUAL=13, FAIL=0. No signing or transaction broadcast was performed.

Contract / address Control queried Expected / documented status Live LCD Tracker
wrap-mapper terra1xuuuhpmyd5t29ry7mydg7ra2q2phrwhx7j28nx7x9sjw6zznkumsz0nmd2 config.governance + Wasm admin DEX 2-of-3 terra1zlmv2xydxcusurtr6rl78wsvytdc6mfex6hep7 DEX 2-of-3 DEX #526
CMM treasury terra16j5u6ey7a84g40sr3gd94nzg5w5fm45046k9s2347qhfpwm5fr6sem3lr2 config.governance + Wasm admin DEX 2-of-3 DEX 2-of-3 DEX #526
ust1-window terra1zxwpzpzpleatqn39r00grau4yt29sld8pw78s7ktvjafnj5nsaxq0h3rh2 config.governance + Wasm admin Documented residual: wrap-stack EOA terra1xsecn4snv94ezcez0z3vq8an9j4h4kxxcydp8l Same EOA ust1-window#30, DEX #526
ust1-oracle terra1fmht0t6svq3n24zx03nkfja0m40zhfyyxkdcvlrkl6u7gfe6aagq4gch8n config.governance + Wasm admin Documented residual: wrap-stack EOA Same EOA ust1-window#30, DEX #526
UST1 terra1f0eqgy9w7e5e7up97vjudqwx38tesf8ylx75x2lv3nwm0clry0pqmgfy72 CW20 minter + Wasm admin Documented residual: wrap-stack EOA Same EOA ust1-window#30, DEX #526
cLUNC terra1437qslye72t7qmmahn4t5chz50r8a62g45phwkquwpyu2l62u6ksqssgdg CW20 minter + Wasm admin Documented residual: wrap-stack EOA Same EOA ustr-cmm#15, DEX #526
cUSTC terra1nap4dxh9tv35v0ynd9m4k6zt6c0dq6weszc4j5m564kjls56hu7qcr56ch CW20 minter + Wasm admin Documented residual: wrap-stack EOA Same EOA ustr-cmm#15, DEX #526
USTR terra1vy3kc0swag2rhn7jz6n72jp0l2ns0p6r6ez5grxq5uhj2rvs97fqfsetxv CW20 minter + Wasm admin Documented residual: wrap-stack EOA Same EOA ustr-cmm#15, DEX #526
vFDUSD terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3 Wasm admin Documented residual: wrap-stack EOA Same EOA ustr-cmm#15, DEX #526

The USTC→USTR swap admin and bridge admin are outside this repo's registry/probe; #526 tracks ustr-cmm#15 and cl8y-bridge-monorepo#135, respectively.

#697 remains open. The documented EOA residuals still need either completed transfers or explicit disposition with a named owner and UTC revisit date. DEX #526 and #697 have no assignee; no newer DEX issue replacing this verification was found. Keep #526 open for its accept queue.

## Read-only columbus-5 LCD attestation Queried `https://terra-classic-lcd.publicnode.com` at **2026-09-24 09:38:26 UTC**, height **30540960**, with `VERIFY697_MAINNET=1 make verify-issue-697`: **PASS=4, RESIDUAL=13, FAIL=0**. No signing or transaction broadcast was performed. | Contract / address | Control queried | Expected / documented status | Live LCD | Tracker | |---|---|---|---|---| | wrap-mapper `terra1xuuuhpmyd5t29ry7mydg7ra2q2phrwhx7j28nx7x9sjw6zznkumsz0nmd2` | `config.governance` + Wasm admin | DEX 2-of-3 `terra1zlmv2xydxcusurtr6rl78wsvytdc6mfex6hep7` | DEX 2-of-3 | [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | CMM treasury `terra16j5u6ey7a84g40sr3gd94nzg5w5fm45046k9s2347qhfpwm5fr6sem3lr2` | `config.governance` + Wasm admin | DEX 2-of-3 | DEX 2-of-3 | [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | ust1-window `terra1zxwpzpzpleatqn39r00grau4yt29sld8pw78s7ktvjafnj5nsaxq0h3rh2` | `config.governance` + Wasm admin | Documented residual: wrap-stack EOA `terra1xsecn4snv94ezcez0z3vq8an9j4h4kxxcydp8l` | Same EOA | [ust1-window#30](https://gitlab.com/PlasticDigits/ust1-window/-/work_items/30), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | ust1-oracle `terra1fmht0t6svq3n24zx03nkfja0m40zhfyyxkdcvlrkl6u7gfe6aagq4gch8n` | `config.governance` + Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ust1-window#30](https://gitlab.com/PlasticDigits/ust1-window/-/work_items/30), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | UST1 `terra1f0eqgy9w7e5e7up97vjudqwx38tesf8ylx75x2lv3nwm0clry0pqmgfy72` | CW20 minter + Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ust1-window#30](https://gitlab.com/PlasticDigits/ust1-window/-/work_items/30), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | cLUNC `terra1437qslye72t7qmmahn4t5chz50r8a62g45phwkquwpyu2l62u6ksqssgdg` | CW20 minter + Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ustr-cmm#15](https://gitlab.com/PlasticDigits2/ustr-cmm/-/work_items/15), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | cUSTC `terra1nap4dxh9tv35v0ynd9m4k6zt6c0dq6weszc4j5m564kjls56hu7qcr56ch` | CW20 minter + Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ustr-cmm#15](https://gitlab.com/PlasticDigits2/ustr-cmm/-/work_items/15), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | USTR `terra1vy3kc0swag2rhn7jz6n72jp0l2ns0p6r6ez5grxq5uhj2rvs97fqfsetxv` | CW20 minter + Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ustr-cmm#15](https://gitlab.com/PlasticDigits2/ustr-cmm/-/work_items/15), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | | vFDUSD `terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3` | Wasm admin | Documented residual: wrap-stack EOA | Same EOA | [ustr-cmm#15](https://gitlab.com/PlasticDigits2/ustr-cmm/-/work_items/15), [DEX #526](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/526) | The USTC→USTR swap admin and bridge admin are outside this repo's registry/probe; #526 tracks [ustr-cmm#15](https://gitlab.com/PlasticDigits2/ustr-cmm/-/work_items/15) and [cl8y-bridge-monorepo#135](https://gitlab.com/PlasticDigits/cl8y-bridge-monorepo/-/work_items/135), respectively. **#697 remains open.** The documented EOA residuals still need either completed transfers or explicit disposition with a named owner and UTC revisit date. DEX #526 and #697 have no assignee; no newer DEX issue replacing this verification was found. Keep #526 open for its accept queue.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#697
No description provided.