Skip to content

Prevent logging password as plain text in snapshot and indices collectors #1068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Otterpohl
Copy link

Problem

The elasticsearch_exporter inconsistently masks passwords in log output. While most log entries properly mask credentials with ***, some error messages expose plain text passwords.

Evidence

The logs below demonstrate the issue:

  • Properly masked: Most lines show elastic:***@localhost:9200
  • Plain text exposed: Lines 10, 12 show elastic:PlainTextPasswordGoesHere!@localhost:9200

Replication Steps

  1. Run elasticsearch_exporter, passing credentials however you please:
    go run main.go tls.go --es.uri https://elastic:PlainTextPasswordGoesHere\!@localhost:9200 \
      --log.format=logfmt --log.level=info --es.all --es.indices --es.indices_settings \
      --es.indices_mappings --no-es.aliases --es.shards --collector.snapshots \
      --es.timeout=30s --es.ssl-skip-verify --web.listen-address=:9108
  2. Ensure Elasticsearch is accessible on localhost:9200
  3. Visit /metrics to trigger collection
  4. Ensure Elasticsearch is now not accessible
  5. Visit /metrics to trigger collection (now with connection errors)
  6. Observe log output - password will be exposed in error messages in the indices and snapshot collectors

Impact

  • Security Risk: Credentials logged in plain text
  • Inconsistent Behavior: Some URLs are properly sanitized, others are not
  • Potential Compliance Issues: Violates security logging best practices

Expected Fix

All URL logging should consistently mask credentials, regardless of whether they appear in info, warning, or error messages.

go run main.go tls.go --es.uri https://elastic:PlainTextPasswordGoesHere\!@localhost:9200 --log.format=logfmt --log.level=info --es.all --es.indices --es.indices_settings --es.indices_mappings --no-es.aliases --es.shards --collector.snapshots --es.timeout=30s --es.ssl-skip-verify --web.listen-address=:9108 --web.telemetry-path=/metrics
time=2025-08-19T10:38:26.484+01:00 level=INFO source=clusterinfo.go:211 msg="triggering initial cluster info call"
time=2025-08-19T10:38:26.484+01:00 level=INFO source=clusterinfo.go:182 msg="providing consumers with updated cluster info label"
time=2025-08-19T10:38:26.962+01:00 level=INFO source=main.go:230 msg="started cluster info retriever" interval=5m0s
time=2025-08-19T10:38:26.963+01:00 level=INFO source=tls_config.go:347 msg="Listening on" address=[::]:9108
time=2025-08-19T10:38:26.963+01:00 level=INFO source=tls_config.go:350 msg="TLS is disabled." http2=false address=[::]:9108
time=2025-08-19T10:38:37.346+01:00 level=WARN source=indices_mappings.go:144 msg="failed to fetch and decode cluster mappings stats" err="failed to get from https://localhost:9200/_all/_mappings: Get \"https://elastic:***@localhost:9200/_all/_mappings\": dial tcp [::1]:9200: connect: connection refused"
time=2025-08-19T10:38:37.346+01:00 level=WARN source=indices_settings.go:172 msg="failed to fetch and decode cluster settings stats" err="failed to get from https://localhost:9200/_all/_settings: Get \"https://elastic:***@localhost:9200/_all/_settings\": dial tcp [::1]:9200: connect: connection refused"
time=2025-08-19T10:38:37.346+01:00 level=ERROR source=collector.go:188 msg="collector failed" name=cluster-info duration_seconds=0.001240542 err="Get \"https://elastic:***@localhost:9200\": dial tcp [::1]:9200: connect: connection refused"
time=2025-08-19T10:38:37.346+01:00 level=ERROR source=collector.go:188 msg="collector failed" name=snapshots duration_seconds=0.001345 err="failed to get https://elastic:PlainTextPasswordGoesHere!@localhost:9200/_snapshot: Get \"https://elastic:***@localhost:9200/_snapshot\": dial tcp [::1]:9200: connect: connection refused"
^^
time=2025-08-19T10:38:37.346+01:00 level=WARN source=cluster_health.go:254 msg="failed to fetch and decode cluster health" err="failed to get cluster health from https://localhost:9200/_cluster/health: Get \"https://elastic:***@localhost:9200/_cluster/health\": dial tcp [::1]:9200: connect: connection refused"
time=2025-08-19T10:38:37.346+01:00 level=WARN source=indices.go:639 msg="failed to fetch and decode index stats" err="failed to get https://elastic:PlainTextPasswordGoesHere!@localhost:9200/_all/_stats?ignore_unavailable=true&level=shards: Get \"https://elastic:***@localhost:9200/_all/_stats?ignore_unavailable=true&level=shards\": dial tcp [::1]:9200: connect: connection refused"
^^
time=2025-08-19T10:38:37.346+01:00 level=WARN source=shards.go:187 msg="failed to fetch and decode node shards stats" err="failed to get from https://localhost:9200/_cat/shards: Get \"https://elastic:***@localhost:9200/_cat/shards?format=json\": dial tcp [::1]:9200: connect: connection refused"
time=2025-08-19T10:38:37.346+01:00 level=WARN source=nodes.go:1901 msg="failed to fetch and decode node stats" err="failed to get cluster health from https://localhost:9200/_nodes/stats: Get \"https://elastic:***@localhost:9200/_nodes/stats\": dial tcp [::1]:9200: connect: connection refused"

… in indices and snapshot collectors

Signed-off-by: Tristan Otterpohl <tristan.otterpohl@forter.com>
@Otterpohl Otterpohl force-pushed the plain-text-password-logging branch from 8c7e2f9 to 8d12122 Compare August 19, 2025 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant