Security: no post-deploy script cross-checks frontend and indexer env addresses against on-chain contract config [SEC-H04] #442

Closed
opened 2026-06-30 10:16:57 +00:00 by totdking · 11 comments
totdking commented 2026-06-30 10:16:57 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-30 10:18:43 +00:00 (Migrated from gitlab.com)

Summary

scripts/deploy-dex-local.sh writes frontend-dapp/.env.local and indexer/.env from the just-deployed contract addresses, so they match at the moment of writing for LocalTerra. However, no script performs a subsequent comparison of all address fields in the env files (FACTORY_ADDRESS, ROUTER_ADDRESS, FEE_DISCOUNT_ADDRESS, and their VITE_ counterparts) against what the on-chain contracts report as their own config. scripts/qa/verify-deploy.sh reads FACTORY_ADDRESS from the env and uses it to query the chain, but only does schema probes and does not cross-check ROUTER, FEE_DISCOUNT, or any VITE_ address variable against chain state. For staging and mainnet, env files are configured manually, so drift between env files and on-chain addresses is not detected.


What Was Checked

  • scripts/deploy-dex-local.sh lines 938-998: writes frontend-dapp/.env.local and indexer/.env from deployed addresses at write time. Confirmed these variables are written: VITE_FACTORY_ADDRESS, VITE_ROUTER_ADDRESS, VITE_FEE_DISCOUNT_ADDRESS, FACTORY_ADDRESS, ROUTER_ADDRESS.
  • scripts/qa/verify-deploy.sh lines 75-165: reads FACTORY_ADDRESS from indexer/.env or frontend-dapp/.env.local; uses it to query the factory; runs pair schema probes. Does not compare ROUTER_ADDRESS or FEE_DISCOUNT_ADDRESS or any VITE_ var against on-chain state.
  • docs/deployment-guide.md lines 114-160: post-deployment checklist is entirely manual terrad query commands. No script compares env to chain output.
  • No script in scripts/qa/ or scripts/ performs a systematic env-to-chain address comparison.

Expected (per checklist)

A post-deploy script reads all address fields from both env files (frontend-dapp/.env.local and indexer/.env), queries the on-chain config for each address (factory get_config for governance/treasury, router config for factory, fee-discount config for governance), and asserts that the addresses match what is reported by the chain.


Actual

No such comparison script exists. For LocalTerra the env files are written by the deploy script and match by construction. For staging and mainnet, env files are maintained manually and address drift is undetected unless the operator runs manual queries.


Evidence

  • scripts/qa/verify-deploy.sh in full: uses FACTORY from env to query chain but only does schema probes; does not compare ROUTER or FEE_DISCOUNT addresses against on-chain values
  • scripts/deploy-dex-local.sh lines 938-998: writes env files but no post-write verification step queries chain to confirm values match

Suggested Fix

Add a scripts/qa/verify-env-addresses.sh that: (1) reads FACTORY_ADDRESS, ROUTER_ADDRESS, FEE_DISCOUNT_ADDRESS from both env files and asserts they match each other; (2) queries factory get_config and asserts the on-chain factory address equals FACTORY_ADDRESS; (3) queries router config and asserts its factory field equals the env FACTORY_ADDRESS; (4) queries fee-discount config and asserts its governance field is non-empty. Wire this into make verify-deploy and add a step to docs/runbooks/launch-checklist.md Phase 4 requiring it before go/no-go sign-off.


Verification Checklist

  • A script reads all address fields from both env files and compares them against on-chain queries
  • Script exits nonzero on any mismatch between env file and chain state
  • docs/runbooks/launch-checklist.md Phase 4 requires this comparison before go/no-go sign-off

Labels

security, pre-launch

Cc: @PlasticDigits

### Summary `scripts/deploy-dex-local.sh` writes `frontend-dapp/.env.local` and `indexer/.env` from the just-deployed contract addresses, so they match at the moment of writing for LocalTerra. However, no script performs a subsequent comparison of all address fields in the env files (FACTORY_ADDRESS, ROUTER_ADDRESS, FEE_DISCOUNT_ADDRESS, and their VITE\_ counterparts) against what the on-chain contracts report as their own config. `scripts/qa/verify-deploy.sh` reads FACTORY_ADDRESS from the env and uses it to query the chain, but only does schema probes and does not cross-check ROUTER, FEE_DISCOUNT, or any VITE\_ address variable against chain state. For staging and mainnet, env files are configured manually, so drift between env files and on-chain addresses is not detected. --- ### What Was Checked - `scripts/deploy-dex-local.sh` lines 938-998: writes `frontend-dapp/.env.local` and `indexer/.env` from deployed addresses at write time. Confirmed these variables are written: `VITE_FACTORY_ADDRESS`, `VITE_ROUTER_ADDRESS`, `VITE_FEE_DISCOUNT_ADDRESS`, `FACTORY_ADDRESS`, `ROUTER_ADDRESS`. - `scripts/qa/verify-deploy.sh` lines 75-165: reads FACTORY_ADDRESS from indexer/.env or frontend-dapp/.env.local; uses it to query the factory; runs pair schema probes. Does not compare ROUTER_ADDRESS or FEE_DISCOUNT_ADDRESS or any VITE\_ var against on-chain state. - `docs/deployment-guide.md` lines 114-160: post-deployment checklist is entirely manual terrad query commands. No script compares env to chain output. - No script in `scripts/qa/` or `scripts/` performs a systematic env-to-chain address comparison. --- ### Expected (per checklist) A post-deploy script reads all address fields from both env files (frontend-dapp/.env.local and indexer/.env), queries the on-chain config for each address (factory get_config for governance/treasury, router config for factory, fee-discount config for governance), and asserts that the addresses match what is reported by the chain. --- ### Actual No such comparison script exists. For LocalTerra the env files are written by the deploy script and match by construction. For staging and mainnet, env files are maintained manually and address drift is undetected unless the operator runs manual queries. --- ### Evidence - `scripts/qa/verify-deploy.sh` in full: uses FACTORY from env to query chain but only does schema probes; does not compare ROUTER or FEE_DISCOUNT addresses against on-chain values - `scripts/deploy-dex-local.sh` lines 938-998: writes env files but no post-write verification step queries chain to confirm values match --- ### Suggested Fix Add a `scripts/qa/verify-env-addresses.sh` that: (1) reads FACTORY_ADDRESS, ROUTER_ADDRESS, FEE_DISCOUNT_ADDRESS from both env files and asserts they match each other; (2) queries factory `get_config` and asserts the on-chain factory address equals FACTORY_ADDRESS; (3) queries router `config` and asserts its factory field equals the env FACTORY_ADDRESS; (4) queries fee-discount config and asserts its governance field is non-empty. Wire this into `make verify-deploy` and add a step to `docs/runbooks/launch-checklist.md` Phase 4 requiring it before go/no-go sign-off. --- ### Verification Checklist - [ ] A script reads all address fields from both env files and compares them against on-chain queries - [ ] Script exits nonzero on any mismatch between env file and chain state - [ ] `docs/runbooks/launch-checklist.md` Phase 4 requires this comparison before go/no-go sign-off --- ### Labels `security`, `pre-launch` Cc: @PlasticDigits
totdking commented 2026-06-30 10:24:12 +00:00 (Migrated from gitlab.com)

mentioned in issue #381

mentioned in issue #381
PlasticDigits commented 2026-06-30 11:18:16 +00:00 (Migrated from gitlab.com)

mentioned in commit 8f5db8bccf

mentioned in commit 8f5db8bccf450bf2ab864076b5e6e6ccf3e8a3f3
PlasticDigits commented 2026-06-30 11:18:35 +00:00 (Migrated from gitlab.com)

mentioned in merge request !977

mentioned in merge request !977
Brouie commented 2026-06-30 11:24:01 +00:00 (Migrated from gitlab.com)

Went through the SEC-H04 env/chain address cross-check (8f5db8bc, !977) — verified the script against the current deploy, including the drift-detection path.

make verify-issue-442 → 7/7 PASS, with the live qa-verify-env-addresses at 14 checks / 0 failures. It does what the issue asked:

  • [1/4] env parity — indexer .env FACTORY/ROUTER/FEE_DISCOUNT each a valid terra1 addr and equal to the frontend VITE_* counterparts
  • [2/4] factory config query at FACTORY_ADDRESS resolves (governance/treasury valid) — proves the env factory is a live contract
  • [3/4] router.config.factory on chain == env FACTORY_ADDRESS
  • [4/4] fee-discount config at FEE_DISCOUNT_ADDRESS
  • wired into qa-verify-deploy (verify-deploy.sh) and gated in launch-checklist Phase 4

Checked the failure path too, not just the happy one: pointed both env files' FACTORY at a real-but-non-factory address (so env parity still passes) and the on-chain cross-check caught the drift two ways — the factory config query failed, and router.config.factory (the real factory) didn't match the tampered env value → RESULT FAIL, exit nonzero. So it genuinely cross-checks env against chain, which is the whole point of SEC-H04.

cannot_be_merged right now is just the Makefile .PHONY/target-list rebase (the same line every SEC-H MR appends to; branch base is behind current main) — verify-deploy.sh and the docs merge clean. Good to merge / good to close from my side once it's rebased.

@PlasticDigits

Went through the SEC-H04 env/chain address cross-check (8f5db8bc, !977) — verified the script against the current deploy, including the drift-detection path. `make verify-issue-442` → 7/7 PASS, with the live `qa-verify-env-addresses` at 14 checks / 0 failures. It does what the issue asked: - [1/4] env parity — indexer .env FACTORY/ROUTER/FEE_DISCOUNT each a valid terra1 addr and equal to the frontend VITE_* counterparts - [2/4] factory config query at FACTORY_ADDRESS resolves (governance/treasury valid) — proves the env factory is a live contract - [3/4] router.config.factory on chain == env FACTORY_ADDRESS - [4/4] fee-discount config at FEE_DISCOUNT_ADDRESS - wired into qa-verify-deploy (verify-deploy.sh) and gated in launch-checklist Phase 4 Checked the failure path too, not just the happy one: pointed both env files' FACTORY at a real-but-non-factory address (so env parity still passes) and the on-chain cross-check caught the drift two ways — the factory config query failed, and router.config.factory (the real factory) didn't match the tampered env value → RESULT FAIL, exit nonzero. So it genuinely cross-checks env against chain, which is the whole point of SEC-H04. cannot_be_merged right now is just the Makefile .PHONY/target-list rebase (the same line every SEC-H MR appends to; branch base is behind current main) — verify-deploy.sh and the docs merge clean. Good to merge / good to close from my side once it's rebased. @PlasticDigits
PlasticDigits commented 2026-06-30 11:40:41 +00:00 (Migrated from gitlab.com)

mentioned in commit 96f0f8514e

mentioned in commit 96f0f8514ea2d8a623db4b8ac6f2f07431a1a6e6
PlasticDigits commented 2026-06-30 11:53:32 +00:00 (Migrated from gitlab.com)

Verification — SEC-H04 env/chain address cross-check (MR !977 / #442)

Verified at 8f5db8bc on fresh LocalTerra deploy (make setup-cloud-localterra --fresh --skip-build).

Acceptance criteria (#442)

Criterion Result How verified
Script reads all address fields from both env files and compares against on-chain queries PASS make qa-verify-env-addresses — 14 checks / 0 failures: env parity (FACTORY, ROUTER, FEE_DISCOUNT), factory config, router config.factory, fee-discount config.governance
Script exits nonzero on env/chain mismatch PASS Tampered VITE_FACTORY_ADDRESS to router addr via VERIFY_ENV_FRONTEND_FILE=… → FACTORY (indexer == frontend) FAIL, exit 1
launch-checklist.md Phase 4 requires comparison before go/no-go PASS grep verify-env-addresses docs/runbooks/launch-checklist.md; make check-deploy-env-addresses-docs

Verification checklist

Item Result Command / output
make verify-issue-442 (full runner) PASS 7/7 (6 static + live LocalTerra)
make test-qa-verify-env-addresses PASS fixture LCD decode + env read helper
make qa-verify-deploy wires env check after Q1 PASS schema/stamp OK, then env cross-check PASS
Agent skill + qa-invariants Q4 PASS skills/AGENTS_DEPLOY_ENV_ADDRESSES_VERIFY.md, docs/qa-invariants.md
Live deploy env parity PASS indexer .env == frontend-dapp/.env.local for all three addresses

Notes

  • First deploy attempt on stale chain state failed at treasury funding (insufficient test1 uluna after partial deploy); --fresh reset resolved it — same class of bot-swarm / stale-volume issue called out in other e2e-tx runbooks.
  • Implementation already merged via !977.

Good to close #442 from QA.

## Verification — SEC-H04 env/chain address cross-check (MR !977 / #442) Verified at `8f5db8bc` on fresh LocalTerra deploy (`make setup-cloud-localterra --fresh --skip-build`). ### Acceptance criteria (#442) | Criterion | Result | How verified | |-----------|--------|--------------| | Script reads all address fields from both env files and compares against on-chain queries | **PASS** | `make qa-verify-env-addresses` — 14 checks / 0 failures: env parity (FACTORY, ROUTER, FEE_DISCOUNT), factory `config`, router `config.factory`, fee-discount `config.governance` | | Script exits nonzero on env/chain mismatch | **PASS** | Tampered `VITE_FACTORY_ADDRESS` to router addr via `VERIFY_ENV_FRONTEND_FILE=…` → `FACTORY (indexer == frontend)` FAIL, exit 1 | | `launch-checklist.md` Phase 4 requires comparison before go/no-go | **PASS** | `grep verify-env-addresses docs/runbooks/launch-checklist.md`; `make check-deploy-env-addresses-docs` | ### Verification checklist | Item | Result | Command / output | |------|--------|------------------| | `make verify-issue-442` (full runner) | **PASS** | 7/7 (6 static + live LocalTerra) | | `make test-qa-verify-env-addresses` | **PASS** | fixture LCD decode + env read helper | | `make qa-verify-deploy` wires env check after Q1 | **PASS** | schema/stamp OK, then env cross-check PASS | | Agent skill + qa-invariants Q4 | **PASS** | `skills/AGENTS_DEPLOY_ENV_ADDRESSES_VERIFY.md`, `docs/qa-invariants.md` | | Live deploy env parity | **PASS** | indexer `.env` == `frontend-dapp/.env.local` for all three addresses | ### Notes - First deploy attempt on stale chain state failed at treasury funding (insufficient `test1` uluna after partial deploy); **`--fresh`** reset resolved it — same class of bot-swarm / stale-volume issue called out in other `e2e-tx` runbooks. - Implementation already merged via [!977](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/259). Good to close #442 from QA.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-30 11:53:34 +00:00
PlasticDigits commented 2026-06-30 11:59:45 +00:00 (Migrated from gitlab.com)

Verification complete — SEC-H04 / #442

Verified on main @ 96f0f851 after fresh LocalTerra deploy (./scripts/setup-cloud-agent-localterra.sh --fresh --skip-build).

Acceptance criteria

Criterion Result How verified
Script reads all address fields from both env files and compares them against on-chain queries PASS make qa-verify-env-addresses — 14 checks / 0 failures: [1/4] env parity (FACTORY, ROUTER, FEE_DISCOUNT indexer ↔ frontend VITE_*); [2/4] factory config at FACTORY_ADDRESS; [3/4] router config.factory == env FACTORY; [4/4] fee-discount config.governance
Script exits nonzero on any mismatch between env file and chain state PASS Tampered both env files' FACTORY to router address (real contract, not factory); env parity still passed but on-chain cross-check failed 3 ways → RESULT: FAIL, exit 1
docs/runbooks/launch-checklist.md Phase 4 requires this before go/no-go PASS Phase 4 checklist item references verify-env-addresses.sh / make qa-verify-env-addresses; doc invariant make check-deploy-env-addresses-docs OK

Regression suite

make verify-issue-442 → 7/7 PASS (doc invariant, script present, agent skill, launch runbook wiring, verify-deploy.sh integration, unit tests, live LocalTerra).

Wiring confirmed

  • scripts/qa/verify-env-addresses.sh — SEC-H04 cross-check implementation
  • scripts/qa/verify-deploy.sh — invokes env address check after schema/stamp probes
  • skills/AGENTS_DEPLOY_ENV_ADDRESSES_VERIFY.md — agent playbook present

No repo changes required; implementation from !977 is complete and verified.

## Verification complete — SEC-H04 / #442 Verified on `main` @ `96f0f851` after fresh LocalTerra deploy (`./scripts/setup-cloud-agent-localterra.sh --fresh --skip-build`). ### Acceptance criteria | Criterion | Result | How verified | |-----------|--------|--------------| | Script reads all address fields from both env files and compares them against on-chain queries | **PASS** | `make qa-verify-env-addresses` — 14 checks / 0 failures: [1/4] env parity (FACTORY, ROUTER, FEE_DISCOUNT indexer ↔ frontend VITE_*); [2/4] factory `config` at FACTORY_ADDRESS; [3/4] router `config.factory` == env FACTORY; [4/4] fee-discount `config.governance` | | Script exits nonzero on any mismatch between env file and chain state | **PASS** | Tampered both env files' FACTORY to router address (real contract, not factory); env parity still passed but on-chain cross-check failed 3 ways → `RESULT: FAIL`, exit 1 | | `docs/runbooks/launch-checklist.md` Phase 4 requires this before go/no-go | **PASS** | Phase 4 checklist item references `verify-env-addresses.sh` / `make qa-verify-env-addresses`; doc invariant `make check-deploy-env-addresses-docs` OK | ### Regression suite `make verify-issue-442` → **7/7 PASS** (doc invariant, script present, agent skill, launch runbook wiring, `verify-deploy.sh` integration, unit tests, live LocalTerra). ### Wiring confirmed - `scripts/qa/verify-env-addresses.sh` — SEC-H04 cross-check implementation - `scripts/qa/verify-deploy.sh` — invokes env address check after schema/stamp probes - `skills/AGENTS_DEPLOY_ENV_ADDRESSES_VERIFY.md` — agent playbook present No repo changes required; implementation from !977 is complete and verified.
totdking commented 2026-06-30 15:21:57 +00:00 (Migrated from gitlab.com)

mentioned in issue #446

mentioned in issue #446
totdking commented 2026-06-30 16:11:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #451

mentioned in issue #451
PlasticDigits commented 2026-07-12 07:14:42 +00:00 (Migrated from gitlab.com)

mentioned in issue #477

mentioned in issue #477
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#442
No description provided.