SEC-F13: automated guard for indexer log secret leakage (#433) #962

Merged
PlasticDigits merged 2 commits from issue-433-indexer-log-secrets into main 2026-06-30 02:15:13 +00:00
PlasticDigits commented 2026-06-29 15:58:42 +00:00 (Migrated from gitlab.com)

Summary

GitLab #433 (SEC-F13): the indexer already avoided logging DATABASE_URL and other secrets at startup, but nothing in CI or tests enforced that invariant. This MR adds:

  • indexer/src/startup.rs — extracted safe startup INFO logging (run_mode, LCD URLs, factory, rate limits only)
  • scripts/lint-indexer-log-secrets.sh + make lint-indexer-log-secrets — ripgrep guard for secret field names inside tracing:: macro arguments
  • Unit tests (startup::tests) — capture tracing output with a dummy DATABASE_URL password and assert it never appears
  • CI — lint-indexer-log-secrets job in the security stage (default branch + indexer-touching MRs)
  • Docs — operator-secrets.md, indexer-invariants.md, testing.md, AGENTS_INDEXER_API_LCD_SECURITY.md

Acceptance checklist

Criterion Verification Result
Makefile/CI greps indexer source for secret-pattern log calls make lint-indexer-log-secrets PASS
Test captures startup log output; DATABASE_URL password absent cd indexer && cargo test --lib startup::tests PASS
Runbook documents procedure docs/operator-secrets.md § Logs + cross-links PASS
CI job on default branch / MR .gitlab-ci.yml lint-indexer-log-secrets PASS (pending pipeline)
Indexer binary still builds cd indexer && cargo build PASS

Third-party verification

make lint-indexer-log-secrets
cd indexer && cargo test --lib startup::tests
cd indexer && cargo build
rg 'tracing::' indexer/src/ | rg 'database_url|password|mnemonic|bearer|private_key'  # expect no matches

Confirm startup logs on a running indexer show RUN_MODE, LCD URLs, factory, and rate limits — not a postgres connection string.

Blockers

None.

## Summary GitLab #433 (SEC-F13): the indexer already avoided logging `DATABASE_URL` and other secrets at startup, but nothing in CI or tests enforced that invariant. This MR adds: - **`indexer/src/startup.rs`** — extracted safe startup INFO logging (`run_mode`, LCD URLs, factory, rate limits only) - **`scripts/lint-indexer-log-secrets.sh`** + **`make lint-indexer-log-secrets`** — ripgrep guard for secret field names inside `tracing::` macro arguments - **Unit tests** (`startup::tests`) — capture tracing output with a dummy DATABASE_URL password and assert it never appears - **CI** — `lint-indexer-log-secrets` job in the security stage (default branch + indexer-touching MRs) - **Docs** — `operator-secrets.md`, `indexer-invariants.md`, `testing.md`, `AGENTS_INDEXER_API_LCD_SECURITY.md` ## Acceptance checklist | Criterion | Verification | Result | |-----------|--------------|--------| | Makefile/CI greps indexer source for secret-pattern log calls | `make lint-indexer-log-secrets` | PASS | | Test captures startup log output; DATABASE_URL password absent | `cd indexer && cargo test --lib startup::tests` | PASS | | Runbook documents procedure | `docs/operator-secrets.md` § Logs + cross-links | PASS | | CI job on default branch / MR | `.gitlab-ci.yml` `lint-indexer-log-secrets` | PASS (pending pipeline) | | Indexer binary still builds | `cd indexer && cargo build` | PASS | ## Third-party verification ```bash make lint-indexer-log-secrets cd indexer && cargo test --lib startup::tests cd indexer && cargo build rg 'tracing::' indexer/src/ | rg 'database_url|password|mnemonic|bearer|private_key' # expect no matches ``` Confirm startup logs on a running indexer show `RUN_MODE`, LCD URLs, factory, and rate limits — not a postgres connection string. ## Blockers None.
PlasticDigits commented 2026-06-29 16:03:01 +00:00 (Migrated from gitlab.com)

Security review — MR !962

Commit reviewed: 9a9bf50de7cbb4be4ea0972013b21deba00bc397
Scope: SEC-F13 automated guard for indexer log secret leakage (#433) — indexer/src/startup.rs, scripts/lint-indexer-log-secrets.sh, CI job lint-indexer-log-secrets, unit tests, docs/Makefile wiring.

Method: Diff review; traced startup logging and config fields to sinks; verified lint coverage and bypass classes (multiline tracing:: args, {:?} on Config, non-tracing:: sinks); checked reorg_alert webhook paths; confirmed tracing-test is dev-only; ran make lint-indexer-log-secrets and cargo test --lib startup::tests.

Outcome: FINDINGS: 0 medium+

Summary: This MR is defensive hardening only. log_startup_config logs the same non-secret fields that main.rs previously emitted at INFO (run_mode, lcd_urls, factory_address, rate limits) and does not reference database_url, reorg_alert_webhook_url, or other secret-bearing Config fields. Unit tests capture tracing output with dummy credentials and assert absence. No new attacker-controlled input paths, authz changes, injection surfaces, or runtime secret exposure were introduced. The ripgrep guard is line-scoped (multiline macro args / whole-Config Debug would evade it) — noted as a control limitation, not rated medium+ because exploitation requires a merged code change and does not widen external attack surface beyond pre-MR behavior.

Prior threads: No prior security-review notes on this MR; nothing to re-report.

Inline findings: None.

## Security review — MR !962 **Commit reviewed:** `9a9bf50de7cbb4be4ea0972013b21deba00bc397` **Scope:** SEC-F13 automated guard for indexer log secret leakage (#433) — `indexer/src/startup.rs`, `scripts/lint-indexer-log-secrets.sh`, CI job `lint-indexer-log-secrets`, unit tests, docs/Makefile wiring. **Method:** Diff review; traced startup logging and config fields to sinks; verified lint coverage and bypass classes (multiline `tracing::` args, `{:?}` on `Config`, non-`tracing::` sinks); checked `reorg_alert` webhook paths; confirmed `tracing-test` is dev-only; ran `make lint-indexer-log-secrets` and `cargo test --lib startup::tests`. **Outcome:** `FINDINGS: 0` medium+ **Summary:** This MR is defensive hardening only. `log_startup_config` logs the same non-secret fields that `main.rs` previously emitted at INFO (`run_mode`, `lcd_urls`, `factory_address`, rate limits) and does not reference `database_url`, `reorg_alert_webhook_url`, or other secret-bearing `Config` fields. Unit tests capture tracing output with dummy credentials and assert absence. No new attacker-controlled input paths, authz changes, injection surfaces, or runtime secret exposure were introduced. The ripgrep guard is line-scoped (multiline macro args / whole-`Config` Debug would evade it) — noted as a control limitation, not rated medium+ because exploitation requires a merged code change and does not widen external attack surface beyond pre-MR behavior. **Prior threads:** No prior security-review notes on this MR; nothing to re-report. **Inline findings:** None.
PlasticDigits commented 2026-06-29 16:25:16 +00:00 (Migrated from gitlab.com)

added 5 commits

  • 9a9bf50d...de59858d - 4 commits from branch main
  • 5448d214 - Merge origin/main into issue-433-indexer-log-secrets

Compare with previous version

added 5 commits <ul><li>9a9bf50d...de59858d - 4 commits from branch <code>main</code></li><li>5448d214 - Merge origin/main into issue-433-indexer-log-secrets</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/244/diffs?diff_id=1876583690&start_sha=9a9bf50de7cbb4be4ea0972013b21deba00bc397)
PlasticDigits commented 2026-06-29 16:25:20 +00:00 (Migrated from gitlab.com)

Resolved merge conflict with main (single file: Makefile).

Conflict: both branches added SEC-F13 log-secret guards to the aggregate lint target — this MR adds lint-indexer-log-secrets (ripgrep + CI job + startup unit tests); main already merged lint-log-secrets (scripts/check_indexer_log_secrets.py).

Resolution: kept both targets in make lint so the ripgrep guard, Python AST guard, and startup tracing tests all run.

Sanity checks: make lint-indexer-log-secrets, make lint-log-secrets, cargo test --lib startup::tests — all pass.

Resolved merge conflict with `main` (single file: `Makefile`). **Conflict:** both branches added SEC-F13 log-secret guards to the aggregate `lint` target — this MR adds `lint-indexer-log-secrets` (ripgrep + CI job + startup unit tests); `main` already merged `lint-log-secrets` (`scripts/check_indexer_log_secrets.py`). **Resolution:** kept both targets in `make lint` so the ripgrep guard, Python AST guard, and startup tracing tests all run. Sanity checks: `make lint-indexer-log-secrets`, `make lint-log-secrets`, `cargo test --lib startup::tests` — all pass.
PlasticDigits commented 2026-06-29 16:28:31 +00:00 (Migrated from gitlab.com)

Security review — MR !962

Commit reviewed: 5448d214040cdad7f0a42fc859fce309f18e28df
Scope: SEC-F13 automated guard for indexer log secret leakage (#433) — indexer/src/startup.rs, scripts/lint-indexer-log-secrets.sh, CI job lint-indexer-log-secrets, unit tests (tracing-test), docs/Makefile wiring; post-merge with main also retains lint-log-secrets (scripts/check_indexer_log_secrets.py).

Method: Diff review on all 12 changed files; traced Config secret fields (database_url, reorg_alert_webhook_url) to startup logging sink; verified reorg_alert.rs webhook delivery does not log URL (unchanged); checked ripgrep guard vs Python AST guard bypass classes (multiline args, println!/dbg!, whole-Config {:?}); confirmed tracing-test is [dev-dependencies] only; ran make lint-indexer-log-secrets, make lint-log-secrets, and cargo test --lib startup::tests.

Outcome: FINDINGS: 0 medium+

Summary: This MR is defensive hardening only. log_startup_config emits the same non-secret INFO fields previously inlined in main.rs (run_mode, lcd_urls, factory_address, rate limits) and does not reference secret-bearing Config fields. Unit tests capture tracing output with dummy credentials and assert absence. No new attacker-controlled input paths, authn/authz changes, injection surfaces, SSRF/XSS/deserialization risks, or runtime secret exposure were introduced. The ripgrep CI guard is line-scoped and complements the existing Python AST checker on main (both pass locally); gaps such as multiline macro args or non-tracing:: sinks are control-limitation notes, not exploitable vulnerabilities in this diff because exploitation requires a future merged logging change and does not widen external attack surface beyond pre-MR behavior.

Prior threads: Re-reviewed prior security note on 9a9bf50; findings still do not apply after merge-conflict resolution with main (Makefile keeps both lint targets). No medium+ items to re-report.

Inline findings: None.

## Security review — MR !962 **Commit reviewed:** `5448d214040cdad7f0a42fc859fce309f18e28df` **Scope:** SEC-F13 automated guard for indexer log secret leakage (#433) — `indexer/src/startup.rs`, `scripts/lint-indexer-log-secrets.sh`, CI job `lint-indexer-log-secrets`, unit tests (`tracing-test`), docs/Makefile wiring; post-merge with `main` also retains `lint-log-secrets` (`scripts/check_indexer_log_secrets.py`). **Method:** Diff review on all 12 changed files; traced `Config` secret fields (`database_url`, `reorg_alert_webhook_url`) to startup logging sink; verified `reorg_alert.rs` webhook delivery does not log URL (unchanged); checked ripgrep guard vs Python AST guard bypass classes (multiline args, `println!`/`dbg!`, whole-`Config` `{:?}`); confirmed `tracing-test` is `[dev-dependencies]` only; ran `make lint-indexer-log-secrets`, `make lint-log-secrets`, and `cargo test --lib startup::tests`. **Outcome:** `FINDINGS: 0` medium+ **Summary:** This MR is defensive hardening only. `log_startup_config` emits the same non-secret INFO fields previously inlined in `main.rs` (`run_mode`, `lcd_urls`, `factory_address`, rate limits) and does not reference secret-bearing `Config` fields. Unit tests capture tracing output with dummy credentials and assert absence. No new attacker-controlled input paths, authn/authz changes, injection surfaces, SSRF/XSS/deserialization risks, or runtime secret exposure were introduced. The ripgrep CI guard is line-scoped and complements the existing Python AST checker on `main` (both pass locally); gaps such as multiline macro args or non-`tracing::` sinks are control-limitation notes, not exploitable vulnerabilities in this diff because exploitation requires a future merged logging change and does not widen external attack surface beyond pre-MR behavior. **Prior threads:** Re-reviewed prior security note on `9a9bf50`; findings still do not apply after merge-conflict resolution with `main` (Makefile keeps both lint targets). No medium+ items to re-report. **Inline findings:** None.
PlasticDigits commented 2026-06-30 02:15:14 +00:00 (Migrated from gitlab.com)

mentioned in commit 2a06048bc6

mentioned in commit 2a06048bc63903ada3ad17d492b737bac18b19d8
PlasticDigits (Migrated from gitlab.com) merged commit 2a06048bc6 into main 2026-06-30 02:15:14 +00:00
Sign in to join this conversation.
No reviewers
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!962
No description provided.