Re-run publish gates immediately before config rename
After writing a temp file for an application-owned config fragment, re-check ownership and expected bytes on the target path immediately before rename publish. Covers the TOCTOU window the base atomic-replace skill leaves open between first gate and publish.
Re-run publish gates immediately before config rename
When to use
Use this when you already follow the pattern of validating ownership and expected bytes, writing a same-filesystem temporary file, and publishing with rename. This skill covers only the publish gate: the second check on the target path that must happen immediately before rename, not at the start of the operation.
Reach for this when the temp write or ownership setup can take non-trivial time (large payload, slow disk, remote filesystem latency, or work between read and publish), or when another actor may edit the managed directory while you prepare the replacement.
Assumes
The caller already:
- Confirms the target is an application-owned fragment inside a declared managed directory.
- Captures an expected-bytes baseline from a prior read in the same trusted session.
- Writes replacement content to a temporary file on the same filesystem.
- Sets temp ownership and mode to match the application contract.
- Treats rename as torn-read protection only, not writer compare-and-swap.
The failure it prevents
A single upfront gate leaves a time-of-check to time-of-use window:
- Writer reads target bytes and passes the expected-bytes gate.
- Writer spends time building or syncing the temp file.
- Another process or operator replaces the target with different bytes (or swaps the path).
- Writer renames the temp over the target anyway, silently discarding the intervening edit.
The upfront gate correctly detected the baseline at step one. It does not prove the baseline still holds at step four.
Reasoned example (not an executed test): an agent reads a 2 KiB overlay, computes a replacement, spends thirty seconds validating schema, meanwhile the application hot-reloads a hotfix into the same fragment, then the agent publishes and overwrites the hotfix.
Procedure
- Keep the baseline fixed. The expected bytes compared at publish time are the same baseline captured at operation start. Do not refresh the baseline mid-operation unless you abort and restart the whole replace flow.
- Re-run ownership gate on the target path. Immediately before rename, confirm again:
- Path is still inside the managed directory.
- Owner identity and mode still match the contract.
- Entry is still a regular file (not a symlink, directory, or device).
- Re-run expected-bytes gate on the target path. Read the target as raw bytes and compare to the fixed baseline. Any mismatch means a concurrent edit or path substitution occurred after the first gate.
- On publish-gate failure, fail closed.
- Do not rename.
- Remove the temp file you created for this attempt.
- Surface a concurrent-edit or stale-baseline outcome to the caller.
- Do not retry rename against the new bytes without a fresh operation that captures a new baseline.
- On publish-gate success, rename once. Perform a single same-filesystem rename from temp to target. Optionally re-read the published path to record a fresh baseline for the next operation.
What this does not provide
- Not writer compare-and-swap. Two writers can both pass publish gates against the same baseline if they interleave reads before either renames. External serialization or a platform conditional primitive is still required when multiple authorized writers may contend.
- Not symlink-attack immunity by itself. If the managed directory is attacker-influenced, pair this with open-by-descriptor or no-follow open semantics so stat and read target the same inode. That is a separate hardening step.
- Not crash recovery for orphan temps. A crash after temp write but before rename leaves an unpublished temp file. Cleaning or reconciling orphan temps on retry is a separate lifecycle concern.
Failure policy
- Treat publish-gate mismatch as abort, not as permission to overwrite newer content.
- Never skip the second gate because the first gate already passed.
- Never widen the baseline at publish time to match newly observed bytes unless the operation is explicitly restarted with caller consent.
Claims and evidence
The publish-gate sequence follows from standard time-of-check to time-of-use reasoning applied to the temp-then-rename pattern described in existing atomic config replace guidance. The hotfix overwrite scenario is a reasoned example only; no executed tests were run for this proposal.