fix: harden CORS and replication request trust - #101
Merged
Conversation
Keep pre-authentication CORS lookups resident-only so attacker-controlled path segments cannot trigger metadata I/O or grow the metadata cache. Preserve fail-closed behavior for startup, load failures, invalid metadata, and the internal namespace. Centralize replication request trust after authentication, distinguish general replication from replica-only privileges, and gate SSE-C ciphertext handling, source metadata, object-lock bypasses, event suppression, delete semantics, and replica status on the appropriate permission. Add least-privilege, multipart, PostPolicy, CORS amplification, and compatibility regressions. Signed-off-by: Feng Ruohang <rh@vonng.com>
Count only valid live CORS states in per-site summaries. Treat baselines and tombstones as absent, and diagnose malformed payloads or missing source timestamps.\n\nRefs: #77 Signed-off-by: Feng Ruohang <rh@vonng.com>
Evaluate ReplicateObject or ReplicateDelete before returning the no-op validation response, so underprivileged target credentials fail during replication setup instead of at runtime. Signed-off-by: Feng Ruohang <rh@vonng.com>
Evaluate PutObject and ReplicateObject permissions with immutable per-entry request snapshots during concurrent Snowball extraction. Preserve the first API error without sharing mutable handler state, and cover prefix-scoped trust under the race detector. Signed-off-by: Feng Ruohang <rh@vonng.com>
Place synthetic permission-check objects under each enabled rule's effective prefix, so least-privilege target policies are validated against the namespace they will actually replicate. Signed-off-by: Feng Ruohang <rh@vonng.com>
Snapshot per-entry requests after applying bucket encryption defaults but before streaming trailers are consumed. Keep authorization failures fatal while retaining Snowball ignore-errors behavior for object-lock failures. Signed-off-by: Feng Ruohang <rh@vonng.com>
This was referenced Sep 1, 2026
Accept the new CORS test routes, resident getter, and replication header literals in the rebrand guard. Apply gofumpt, context-first helper ordering, and spelling fixes required by CI. Signed-off-by: Feng Ruohang <rh@vonng.com>
Member
Author
|
Final acceptance update:
No merge, tag, package, image, deployment, or production verification has been performed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution Licensing (no CLA, inbound=outbound, DCO required)
This project does not use a CLA; contributions are accepted inbound=outbound.
Every commit in this PR carries a DCO
Signed-off-bytrailer.Description
Motivation and Context
The old CORS middleware could turn arbitrary valid-looking bucket path segments into pre-authentication metadata reads and persistent cache entries. Separately, client-controlled replication headers acquired internal meaning in SSE-C reads, source ETag/MTime preservation, object lock, checksums, events, and deletes before one receiver-wide trust decision existed.
The status loop then counted malformed or timestamp-less CORS payloads as configured, and replication setup probes returned before checking the permissions required at runtime. Adversarial review also found that the first trust implementation mutated shared request authorization state across concurrent Snowball entries; this PR closes that race and the related prefix-authorization bypass.
Refs #77 for the CORS status-accounting portion.
How to test this PR?
Passed locally on macOS/arm64 with Go 1.27.0:
-race;-race;go build ./...;go vet ./cmd ./internal/bucket/object/lock/;go test ./cmd -count=1(final run: 131.426s).A real local TLS two-site run of the core trust commit also passed SSE-C single PUT, 12 MiB multipart, SSE-C CopyObject, and delete-marker replication with matching hashes, ETags, sizes, version IDs, and key MD5s.
Claude Code Fable 5 reviewed the design and implementation; Claude Code Opus 5 performed repeated adversarial acceptance reviews. Final verdict: GO, no P0/P1/P2 findings.
Compatibility impact
rule.Prefix(). Empty-prefix behavior and the documentedbucket/*policy remain unchanged.Types of changes
Checklist:
git commit -s) per the DCO938603458make verifierspassespgsty/silo.pgsty.com