fleet.leaders.<name>.cwd is never validated — a relative value is silently accepted #488

Open
opened 2026-09-12 00:50:03 +02:00 by ltms · 0 comments
Owner

Found while reviewing #487 (the fleetd #480 relative-handoverPath follow-up). Not fixed there, on purpose — it is a separate decision.

What was measured

Nothing in FleetConfig's validate* methods looks at Leader.cwd(). Measured by the worker on branch worker/480-relative-handover-path-906323-1:

grep -c '\.cwd()' fleetd/src/main/java/dev/ltms/fleet/config/FleetConfig.java
0

So an operator can write a relative cwd: under fleet.leaders.<name> and the daemon starts normally.

Why it matters

Two consumers read that value and neither can tell a relative one is wrong:

  1. LeadLauncher.java:311 passes it to herdr as the new lead pane's working directory. A relative value would be resolved by whatever process ends up interpreting it, which is not obviously the daemon.
  2. Since #487, LeadRollover.open() resolves a relative leadRollover.handoverPath against it. #487 already defends itself here — resolveHandoverPath now calls .toAbsolutePath() on both branches, so the result is guaranteed absolute even if cwd is relative — but that defence silently picks the daemon's own user.dir as the base, which is almost certainly not what an operator writing a relative cwd meant.

So today a relative cwd does not crash. It quietly means something different from what it looks like.

The decision to make

Either refuse a relative cwd at config load (the same way validateLeadRollover() refuses a present leadRollover: block with a blank handoverPath), or document that it resolves against the daemon's working directory and leave it. Refusing is probably right: cwd is an absolute-path concept everywhere else in this config, and a startup refusal is the cheapest possible place to find out.

This is small and self-contained. It is not urgent — no current config uses a relative cwd.

Related: #480, #487.

Found while reviewing #487 (the fleetd #480 relative-`handoverPath` follow-up). Not fixed there, on purpose — it is a separate decision. ## What was measured Nothing in `FleetConfig`'s `validate*` methods looks at `Leader.cwd()`. Measured by the worker on branch `worker/480-relative-handover-path-906323-1`: ``` grep -c '\.cwd()' fleetd/src/main/java/dev/ltms/fleet/config/FleetConfig.java 0 ``` So an operator can write a relative `cwd:` under `fleet.leaders.<name>` and the daemon starts normally. ## Why it matters Two consumers read that value and neither can tell a relative one is wrong: 1. `LeadLauncher.java:311` passes it to herdr as the new lead pane's working directory. A relative value would be resolved by whatever process ends up interpreting it, which is not obviously the daemon. 2. Since #487, `LeadRollover.open()` resolves a relative `leadRollover.handoverPath` against it. #487 already defends itself here — `resolveHandoverPath` now calls `.toAbsolutePath()` on both branches, so the result is guaranteed absolute even if `cwd` is relative — but that defence silently picks the daemon's own `user.dir` as the base, which is almost certainly not what an operator writing a relative `cwd` meant. So today a relative `cwd` does not crash. It quietly means something different from what it looks like. ## The decision to make Either refuse a relative `cwd` at config load (the same way `validateLeadRollover()` refuses a present `leadRollover:` block with a blank `handoverPath`), or document that it resolves against the daemon's working directory and leave it. Refusing is probably right: `cwd` is an absolute-path concept everywhere else in this config, and a startup refusal is the cheapest possible place to find out. This is small and self-contained. It is not urgent — no current config uses a relative `cwd`. Related: #480, #487.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: fleet/fleetd#488