Security: /metrics may be publicly exposed when METRICS_BIND matches API or 0.0.0.0 #125
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#125
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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
indexer/src/api/mod.rsline 399If
METRICS_BINDis set to0.0.0.0or the same as the public API bind address, the/metricsendpoint is publicly accessible, leaking operational metrics (DB query counts, request rates, error rates). Default is env-dependent.Recommended fix
Always bind metrics on
127.0.0.1(localhost only) and proxy behind authenticated reverse proxy.mentioned in commit
3b65750681Implemented on
main(please verify)Summary: Prometheus
GET /metricsis no longer mounted on the public API Axum router. It is served only on a dedicated TCP listener parsed fromMETRICS_BIND(host:port, or legacy non-:value →127.0.0.1:METRICS_PORT, default port 9095).DEPLOY_ENV(defaults: production whenRUN_MODE=prod, else dev) rejects0.0.0.0and::on that metrics address; setDEPLOY_ENV=qa(orstaging) for non-prod hosts that need an all-interfaces bind.Docs / crosslinks:
docs/operator-secrets.md,docs/indexer-invariants.md,docs/environment-matrix.md, runbook + incident template,docs/README.md,skills/AGENTS_LOCALNET_TRADING_SWARM.md.Verification checklist
RUN_MODE=prod, defaultDEPLOY_ENV):METRICS_BIND=0.0.0.0:9095→ process exits with config error;127.0.0.1:9095→ OK.DEPLOY_ENV=qawithRUN_MODE=prod:0.0.0.0:9095allowed.curlto API base URL/metricsreturns 404; scrape succeeds only againstMETRICS_BIND./cc @brouie — please confirm in your environment. Leaving issue open per process.
verified on main. ran
cargo test --lib config→ 10/10 pass, 0 failed. covers all the cases from your checklist:production_rejects_inaddr_any_metrics_bind,production_rejects_ipv6_unspecified_metrics_bind(prod + :: also rejected),production_accepts_loopback_metrics_bind,prod_run_mode_with_deploy_env_qa_allows_inaddr_any,dev_allows_inaddr_any_metrics_bind,metrics_legacy_flag_binds_loopback. on the routing side, src/api/mod.rs is clean —build_metrics_router()at line 411 only mounts /metrics on the dedicated listener (line 410 doc comment is explicit), and lines 437-448 spin metrics up on its owntokio::net::TcpListener::bind(metrics_sa)separate from the API listener viatokio::try_join!. so curl to api base /metrics returning 404 is architecturally guaranteed — it's not on that router at all. line 438tracing::info!("Prometheus metrics listening on {}")covers the logging item. all 4 checklist items pass at source + unit level, didn't see a need to spin up the binary 4x with env permutations since the config gate the unit tests cover is the same gate the runtime hits.mentioned in issue #200