v0.8.17 — third-round audit closeout (5 follow-up items on v0.8.16) + migration hatch
Third-round audit closeout. A follow-up Codex CLI + Claude
Code review of v0.8.16 caught 5 residual items (2 MED + 3 LOW).
No CRIT / HIGH after the prior two cycles. This is the version
to target for the Reddit launch — three full multi-agent audit
cycles have closed every CRIT / HIGH / MED finding from the
pre-release review.
Published to crates.io as s4-server@0.8.17, s4-codec@0.8.17,
s4-config@0.8.17, s4-codec-py@0.8.17. Install via
cargo install s4-server (CPU build).
What's new since v0.8.16
Fixed (#160-#162)
- #160 G-1 — F-5 presigned-URL 501 is now unconditional.
The v0.8.16 check ran AFTERlet gate = gate?;, so
deployments without--sigv4a-credentialshad
?X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256URLs silently fall
through to the SigV4 path (which doesn't understand SigV4a
query auth either). The presigned-detect call now runs
before the gate guard, so every deployment emits the
deterministic 501. - #161 G-2 — reserved-name guard extended to 8 adjacent
per-object endpoints:get_object_acl,put_object_acl,
get_object_attributes,get_object_tagging,
put_object_tagging,delete_object_tagging,
restore_object, andupload_part_copy(both source +
destination). The v0.8.16 F-13 fix only covered GET / HEAD /
DELETE — a curious client could still
GetObjectAcl(<key>.s4index)or
PutObjectAcl(<key>.s4index, public-read)to bypass the
read-reject via the backend's public-URL path. New shared
helperS4Service::check_not_reserved_key(...)+
ReservedKeyModeenum so every site uses the same code; the
three pre-existing F-13 sites + the M-1 PUT / Copy /
CreateMultipart sites refactor through the same helper. - #162 G-3 —
post_magic_entropy_highshort-sample guard
is now reachable. The v0.8.16 F-12 check inside the helper
defaulted tofalsefor<= 48-byte samples but the upstream
MIN_SAMPLE_BYTES = 128short-circuit inpick_from_sample
filtered every such sample before it could reach F-12. The
magic-byte arm now runs above the MIN_SAMPLE_BYTES gate, so
a 40-byteBZh:loglog:user log actually hits the post-magic
entropy check and gets routed to the default codec
(compressed) rather than passed through uncompressed. Closes
the v0.8.15 M-7 motivation that v0.8.16 F-12 thought it had
closed.
Added (#163-#164)
- #163 G-4 —
--allow-legacy-reserved-key-readsCLI flag.
Migration escape hatch for operators upgrading from
pre-v0.8.15 deployments that may carry legitimate user-owned
objects whose key ends in.s4index. When set, the
reserved-name guard does NOT block GET / HEAD / DELETE on
.s4indexkeys; writes (PUT / Copy / Create-Multipart /
tagging-write / ACL-write) stay blocked regardless of the
flag so an attacker can't inject into the namespace. Default
falsematches v0.8.16 behaviour; boot-time info-log is
loud when the flag is on so the operator notices the
migration window is open. - #164 G-5 —
docs/orphan-sidecar-recovery.mdoperator
recipe for sweeping the orphan<key>.s4indexartifacts
that v0.8.15 H-g left on versioning-Enabled buckets. v0.8.16
#151 F-7 stopped emitting new orphans by skipping the
sidecar block on versioned multipart Complete; this recipe
handles the one-time cleanup of pre-F-7 leftovers. A future
release may ship as4 admin sweep-orphan-sidecars
subcommand that automates the same loop.
Upgrade notes
--allow-legacy-reserved-key-readsis the only new
operator-visible knob since v0.8.16. The cumulative audit
surface area still totals three opt-ins:
--trust-x-forwarded-for(v0.8.11 CRIT-4),
--prefer-columnar-gpu(v0.8.13 #125), and this v0.8.17
migration hatch.- No behavioural breaks since v0.8.16. The G-2 reserved-name
guard extension closes a leak that wasn't reachable via the
aws s3 cphappy path anyway.
Tests
438 lib + 45 integration tests green under
RUSTFLAGS=\"-D warnings\"; cargo clippy --workspace --all-targets clean; cargo fmt --all --check clean; MinIO
E2E job (cargo test --workspace --release -- --ignored --test-threads=1) green on CI.
Full per-issue notes: CHANGELOG.md.
Recovery recipe for v0.8.15 orphan sidecars:
docs/orphan-sidecar-recovery.md.