Skip to content

validate: the staleness probe must not make the file unreadable - #1272

Merged
MDA2AV merged 1 commit into
mainfrom
fix/static-probe-file-mode
Aug 22, 2026
Merged

validate: the staleness probe must not make the file unreadable#1272
MDA2AV merged 1 commit into
mainfrom
fix/static-probe-file-mode

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Aug 22, 2026

Copy link
Copy Markdown
Owner

The static staleness probe added in #1267 built its replacement file with mktemp, which creates it 0600. mv carries the source mode onto the destination, so after the replace the static file was 0600 owned by the invoking user.

Any container running as a non-root user then got EACCES reading it. The probe never saw bytes matching the replacement and failed the entry with:

hero.webp was replaced in the mounted static directory and the server still served the old bytes after 30s. Either a cache is holding the file contents and never revalidating, or the entry is serving a copy taken at image build rather than the directory the profile mounts

which is the opposite of what those entries were doing.

The bias is the wrong way round: every entry that passed the probe so far runs as root, so the bug penalised precisely the images following good practice.

Repro

phoenix-bandit runs as nobody (65534) and fails the probe on this alone. It reads the mounted directory correctly — replacing hero.webp by hand and requesting it back shows the new bytes within 1s over both HTTP/1.1 and h2. Under validate.sh it failed twice in a row.

Fix

Carry the mode of the file being replaced onto the replacement, so the server sees it exactly as it saw the original.

chmod --reference="$backup" "$probe"

phoenix-bandit: 69 passed / 1 failed → 70 passed / 0 failed.

🤖 Generated with Claude Code

The static staleness probe built its replacement with mktemp, which creates
the file 0600. mv carries the source mode onto the destination, so after the
replace the static file was mode 0600 owned by the invoking user. Any
container running as a non-root user then got EACCES reading it, the probe
saw bytes that never matched, and the entry was failed for "serving a copy
taken at image build" -- the exact opposite of what it was doing.

phoenix-bandit runs as nobody and failed on that alone; it passes 70/0 with
the mode carried over. Entries that happened to pass were all running as
root, so the bug penalised precisely the images following good practice.

Carry the mode of the file being replaced onto the replacement.
@MDA2AV
MDA2AV merged commit ed096b1 into main Aug 22, 2026
3 checks passed
MDA2AV added a commit that referenced this pull request Aug 22, 2026
plug-cowboy     a second Plug.Cowboy listener in front of the same router.
                Plug.Cowboy derives its ref from plug + scheme, so the two
                children do not collide.
phoenix-bandit  the endpoint's https: config already holds 8443 for the h2
                profiles and Phoenix binds one https listener per endpoint,
                so json-tls gets a second Bandit listener in front of the
                same endpoint plug -- the identical pipeline, not a copy.

Both guarded on the PEMs, which the harness only mounts for TLS profiles.

validate: plug-cowboy 37/0, phoenix-bandit 70/0 (the latter needs #1272,
which fixes a probe bug that fails any container running as non-root)
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