Skip to content

fleet-config: misspelled fleet.toml section/key is silently ignored — a typo'd [domains] disable loads Ok and the domain stays enabled #5460

Closed

Description

@dezren39

Summary

fleet-config (pkgs/fleet/crates/fleet-config/src/lib.rs, landed in step 1, #5429) parses fleet.toml with serde's default unknown-field handling: any misspelled section or key is silently ignored and the compiled-in default rules instead. That is exactly the failure mode the crate's own docs say must never happen:

"A missing file is not an error (defaults rule); a malformed file is a loud error, never a silent fallback, because a silently ignored disable would defeat the lever." (crate doc, lib.rs:13-15)

A typo is not a parse error under TOML/serde, so today it is a silent fallback.

Evidence (verified this run, laptop probe ~/git/fleet/probe-fleetconfig against the real crate as a path dependency, main be7dae6ca)

Config::load_from on three misspelled files:

  • [domain] (misspelled [domains]) with queue = false → Ok, domain_enabled("queue") == true — the operator's domain disable is silently lost; the domain the operator meant to kill via the §7 incident lever stays enabled.
  • [proxy] with idle_exit_sec = 60 and broker_soket = "/tmp/x.sock" → Ok, idle_exit_secs() == 3600 (default), broker_socket() == the default under $HOME — both overrides silently lost.
  • Unknown top-level key (domainz = 1) → Ok.

Control with correct spellings ([domains] queue = false, [proxy] idle_exit_secs = 60) resolves as intended (domain_enabled("queue") == false, idle == 60), so the loss is specifically the unknown-field handling, not the resolution logic.

Root cause: Config, ProxyConfig, and SecretsConfig (lib.rs:36-60) derive Deserialize with #[serde(default)] but no #[serde(deny_unknown_fields)], so unknown sections/keys deserialize without error.

Why it matters

The [domains] disable is the per-host incident lever for the fleet binary (design §7, epic #5412). An operator disabling a misbehaving domain during an incident, with one character wrong in the section name, gets a successful load, no warning, and a still-enabled domain — the worst possible outcome for a safety lever, and a direct contradiction of the crate's stated contract. The same silent loss applies to the broker socket and secrets token-file overrides, where a typo reroutes (or un-routes) broker traffic with no signal.

Acceptance criteria

  • Config, ProxyConfig, and SecretsConfig reject unknown fields (#[serde(deny_unknown_fields)] or equivalent), so a misspelled section or key in fleet.toml makes Config::load_from return ConfigError::Parse naming the offending field.
  • [domains] remains an open map: arbitrary domain names as keys still load (the deny applies to struct fields, not domain names).
  • Unit tests pin: misspelled section ([domain]), misspelled key (idle_exit_sec), and unknown top-level key all error; the existing tests (missing file → defaults, correct spellings resolve) still pass.
  • cargo test -p fleet-config green.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    on Nov 4, 2026
  2. developing-today commented on Nov 4, 2026

    @developing-today
    Contributor
  3. added
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    work/self-assignedAn agent grabbed this item directly, outside the queue
    app/fleetpkgs/fleet multicall binary + platform crates
    on Nov 4, 2026
  4. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: filed

    • Agent: new-issue-creator job (new-issue-creator-code-a)
    • Session / ID: cron new-issue-creator-code-a run 2026-11-04T13:05Z
    • Found via: filed this run
    • Task: Filed after verifying with a laptop probe (~/git/fleet/probe-fleetconfig, real crate as path dependency): misspelled [domain] section, misspelled proxy keys, and an unknown top-level key all load Ok with defaults silently substituted. Guarded self-solve this run (trivial: serde deny_unknown_fields on the three config structs + tests).
    • Expectation: effort xs; done = PR merged with cargo test -p fleet-config green on the laptop, unknown fields rejected as ConfigError::Parse, [domains] staying an open map.
    • Links: body evidence in the issue; branch creator-a/5460-fleet-config-deny-unknown to follow
  5. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: done

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

    app/fleetpkgs/fleet multicall binary + platform crateskind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:donetask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions