Skip to content

DNS check: [DNS_ANSWER] is not a placeholder and undefined placeholders aren't caught at config validation #1779

Description

@jrimmer

Description

The type: dns check exposes only [DNS_RCODE] as a condition placeholder, so there is no way to assert that a DNS query actually returned records (as opposed to NOERROR with zero answers / NODATA).

Worse, referencing an undefined placeholder (e.g. [DNS_ANSWER].length > 0) is silently accepted at config-validation time and then silently evaluates to false (measured value 0) on every run — no error, no warning. This is very hard to debug because the config looks valid and [DNS_RCODE] == NOERROR in the same conditions list succeeds, so the endpoint is red for a reason that isn't obvious.

Steps to Reproduce

  1. Configure a DNS check against a resolver that returns real A records:
    endpoints:
      - name: dns-forward
        url: "10.1.0.2"
        interval: 1m
        dns:
          query-name: google.com
          query-type: A
        conditions:
          - "[DNS_RCODE] == NOERROR"
          - "[DNS_ANSWER].length > 0"
  2. Start Gatus. Config validation passes — the endpoint is counted (Validated N endpoints) with no panic and no invalid condition error.
  3. Observe the endpoint result. [DNS_RCODE] == NOERRORsuccess=true. [DNS_ANSWER].length > 0success=false (measured value 0) on every check, even though the query returns real A records.

Expected Behavior

Either:

  • A placeholder that exposes the DNS answer and/or answer count, so a user can write has([DNS_ANSWER]), len([DNS_ANSWER]) > 0, etc.; or
  • At minimum, config validation should fail fast with a clear invalid condition error when a condition references an undefined placeholder, instead of silently producing a condition that always fails (or, worse, spuriously passes for forms like [DNS_ANSWER] != '').

Actual Behavior

[DNS_ANSWER] is not a recognized placeholder — config/endpoint/placeholder.go defines only DNSRCodePlaceholder = "[DNS_RCODE]". ResolvePlaceholder falls through to return originalPlaceholder, nil for unknown placeholders (to support literal string comparisons), so the condition's left-hand side becomes the literal string [DNS_ANSWER], which numeric comparisons treat as 00 > 0 is false. No validation error is raised at startup.

Environment

  • Gatus version: v5.36.0 (built from source)
  • OS: Linux
  • Resolver under test: Technitium DNS (though any resolver returning answers reproduces it)

Additional Context

  • The resolver does return answers: dig +short @10.1.0.2 google.com A → IPv4 addresses.
  • Source reference: config/endpoint/placeholder.go — only [DNS_RCODE] is defined for DNS checks; there is no [DNS_ANSWER], [DNS_RESULT], or answer-count placeholder. Unknown placeholders are returned verbatim (line ~189: "Return the original placeholder if we can't resolve it... allows for literal string comparisons"), which silently breaks numeric/len/has conditions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions