Skip to content

Silo 20260903 Released

The complete release since 20260806: authenticated replication semantics, per-bucket CORS, serialized bucket metadata, AWS-aligned authorization and checksums, safer SSE-C copies, Go 1.27.1, and the final 20260903 mcli and SILO component line.
The complete release since 20260806: authenticated replication semantics, per-bucket CORS, serialized bucket metadata, AWS-aligned authorization and checksums, safer SSE-C copies, Go 1.27.1, and the final 20260903 mcli and SILO component line.

Released: 2026-09-03 · Version: RELEASE.2026-09-03T00-00-00Z · Previous release: RELEASE.2026-08-06T00-00-00Z

SILO 20260903 is the security and correctness release following the first fully rebranded Silo release. Its main theme is not a new delivery surface but a tighter set of server invariants: client headers do not create replication authority, browser origins cannot trigger bucket-metadata I/O before authentication, concurrent bucket-configuration writers cannot silently overwrite one another, and authorization and checksum behavior more closely match AWS S3.

This note deliberately uses 20260806 as its only release baseline. Intermediate component builds remain identifiable in their source repositories, but the public documentation below consolidates the complete server, Console, shared-package, and client result delivered on 2026-09-03.

Highlights

  • Replication trust is authorization-derived. X-Minio-Source-Replication-Request and related internal fields gain replication semantics only after signature verification, an exact marker check, and s3:ReplicateObject or s3:ReplicateDelete authorization. Untrusted fields are stripped after authentication so SigV4 remains valid.
  • Per-bucket CORS is complete. PUT, GET, and DELETE ?cors persist a real bucket policy, override the server-wide fallback, and converge through site replication. The pre-authentication lookup is resident-only and remains fail-closed during startup and after a known metadata-load failure.
  • Bucket metadata updates are serialized. A shared metadata.lock covers all whole-record configuration writers, migrations, imports, site adoption, and healing. ForceCreate no longer erases existing configuration, and an Object Lock document always implies plain Enabled versioning.
  • Authorization matches the requested operation. Explicit version deletion requires s3:DeleteObjectVersion; user and group enable/disable calls require the action matching the requested status; policy writes reject empty ARN namespaces.
  • Checksum behavior moves toward AWS S3. Upload parts can receive server-computed checksums, federated UploadPartCopy returns its checksum, multipart completion reports ChecksumType, invalid assertions use AWS-compatible failures, and CRC64NVME with COMPOSITE is rejected.
  • SSE-C reads and copies authenticate the key consistently. Zero-byte objects and GetObjectAttributes no longer bypass key validation; null-version rewrites and in-place key rotation no longer leave unreadable ciphertext or inconsistent checksum metadata.
  • The release was simplified before publication. Dead code and obsolete lint exemptions were removed, compatibility snapshots now track served surfaces instead of source-level noise, dependencies were pinned to reviewed revisions, and flaky timeout tests received a private random source.
  • The client release is part of the same baseline. mcli 20260903 adds read-only checksum verification, fail-closed credential redaction, repaired JSON metrics and S3 Select behavior, strict policy writes, signed packages, provenance, and verified amd64/arm64 images.

Security fixes

The repository security ledger assigns stable local identifiers to five findings without CVEs. An SN- identifier is not a CVE. The complete threat models, compatibility effects, and operator actions are collected in SILO 20260903 Security Notes.

ID Affected surface Fixed invariant Operator impact
SN-2026-006 SSE-C reads and copies of zero-byte objects The supplied customer key is authenticated even when there is no payload block to decrypt Wrong keys now return 403 AccessDenied; no change for correct keys
SN-2026-007 GetObjectAttributes on SSE-C objects Object attributes require the customer key, except for an actually authorized replication peer A bare replication marker cannot skip key authentication
SN-2026-008 Internal replication fields across reads, writes, multipart, deletes, Snowball, and events Replication semantics require authentication plus the matching replication permission Ordinary clients carrying internal-looking headers keep ordinary S3 semantics
SN-2026-009 Admin user and group status changes Enable and disable are authorized against different actions Split custom admin policies that previously granted only one action but relied on both
SN-2026-010 DeleteObject / DeleteObjects with versionId Explicit version deletion requires s3:DeleteObjectVersion Review grants and add an explicit Deny where Deny s3:DeleteObject was intended to block permanent deletion

All five defects were inherited from the archived upstream server lineage and affect every earlier SILO release. SN-2026-008 completes the receiver-wide repair begun by CVE-2026-34204.

The embedded Console v2.3.0 line also contains a trusted-proxy boundary, TLS verification repair, response and log redaction, and bounded WebSocket forwarding. The standalone Console release and the server embedding remain separately verifiable artifacts.

S3 correctness and interoperability

Multipart checksums

This release closes the multipart interoperability group reported in #46, #47, #48, and #50:

  • UploadPart computes the selected checksum when the client selects an algorithm at upload creation but omits a per-part checksum header.
  • UploadPartCopy returns the remote checksum through a legacy federated backend instead of dropping it.
  • CompleteMultipartUpload includes ChecksumType and uses AWS-compatible error codes when a checksum is absent, malformed, contradictory, or unsupported.
  • Unknown checksum algorithms and the invalid CRC64NVME + COMPOSITE combination are rejected rather than silently canonicalized.

The fixes are deliberately layered. The wire parser rejects invalid declarations, the multipart state records the selected algorithm and type, and completion validates the final claim against that state. Ordinary clients that do not opt into additional checksums are unchanged.

The individual evidence records are server-computed UploadPart checksums, multipart completion error semantics, and ChecksumType propagation.

CopyObject and SSE-C

CopyObject now:

  • calculates checksums over the logical object before optional compression;
  • returns the checksum fields in its response;
  • preserves transform state on metadata-only copies;
  • decrypts source checksum metadata with the source key and rewrites it for the destination key;
  • handles null-version copies in either pool direction without losing current-version metadata;
  • re-encrypts an in-place SSE-C key rotation when the object layer must rewrite the data.

The zero-byte and attributes fixes remove two independent places where “no data was decrypted” had accidentally been treated as “the key was authenticated.” The new rule is explicit: access to SSE-C metadata or ciphertext requires a successfully unsealed object key, unless the request has already crossed the authorized replica boundary.

The CopyObject state matrix and live interoperability evidence are preserved in CopyObject SSE-C, checksum, and response correctness.

Listing and federation

  • ListObjects shortcuts now return NoSuchBucket for a missing bucket even when a prefix selects an early-return path (#32, PR #37).
  • Federated UploadPartCopy preserves the backend checksum in the public response (#72).
  • Site-replication status counts metadata operations per site instead of multiplying a group-wide result, and validates CORS as an independent configuration field.

The missing-bucket shortcut is documented in ListObjects must prove the bucket before it optimizes.

Per-bucket CORS and request trust

Bucket CORS was implemented end to end rather than as a handler-only shim:

  1. the S3 XML type and rule matcher enforce the protocol grammar and multi-rule preflight behavior;
  2. bucket metadata stores the raw configuration and returns it byte-for-byte on GET ?cors;
  3. the outer middleware uses the bucket policy when present and the global origin setting only as fallback;
  4. site replication carries CORS in its own tombstone-aware last-writer-wins register;
  5. pre-authentication lookup never loads metadata or creates cache entries;
  6. startup, a known bucket-metadata load failure, deletion, refresh, and on-demand reload all update the fail-closed state explicitly.

The load-failure state is intentionally retained. A pre-signed URL authenticates itself without consulting bucket policy; if the server forgets that a real bucket’s CORS document failed to load, falling back to a permissive global policy would discard the only browser-origin boundary around that otherwise authorized request.

Replication-request hardening shares the same principle. The server authenticates the original request first because internal headers may be covered by SigV4, derives one private trust decision from the authenticated identity and permission, and only then sanitizes an untrusted request clone. The clone shares the original trailer map so streaming checksums remain visible. Snowball workers derive trust per entry rather than inheriting a request-wide privilege bit.

The full design and rejected alternatives are preserved in No I/O Before Auth, No Privilege From Headers.

Bucket metadata and Object Lock

Bucket configuration is stored as one .metadata.bin record but was previously updated through independent locks for policy, lifecycle, encryption, tags, quota, replication, Object Lock, and CORS. Two valid read-modify-write operations could therefore each succeed while the later save silently discarded the earlier field.

This release introduces one bounded metadata.lock transaction around every whole-record mutation. The same lock covers:

  • normal configuration saves and deletes;
  • legacy metadata migration and import;
  • bucket creation, ForceCreate, and site adoption;
  • healing and inconsistent-version repair;
  • replication receive paths that merge changed fields.

The implementation does not turn the metadata system into a generic transaction framework. It keeps the existing record and parsers, centralizes only the serialization boundary, and narrows replicated updates to fields that actually changed.

Object Lock receives a second invariant. Once a valid lock configuration parses as enabled, versioning is normalized to a plain Enabled document; prefix exclusion and suspended states cannot survive. The decision is based on the parsed configuration, not byte equality with the smallest possible XML document, so a valid Default Retention rule cannot bypass it. Update, read-back, and disk-reload tests cover both malformed prior versioning shapes.

IAM, policy, and configuration behavior

  • Explicit version deletion follows AWS s3:DeleteObjectVersion authorization while replication deletes retain s3:ReplicateDelete.
  • SetUserStatus and SetGroupStatus authorize the requested target state instead of always checking the enable action.
  • New and updated named policies and service-account policies reject bare S3, S3 Tables, and KMS ARN namespace prefixes, their historical serialized forms, and statements that combine Resource with NotResource. Stored policies continue to load.
  • Enabled legacy PostgreSQL or MySQL notification targets must supply a connection string. Startup now fails with a credential-free diagnostic instead of silently discarding all targets.
  • MINIO_CONFIG_ENV_FILE parsing preserves named targets, quoted values, and supported shell-like assignments without evaluating the file as shell code.

These changes are compatibility tightenings, not format migrations. Review the upgrade checklist before deploying.

Detailed records cover target-state user/group authorization, safe configuration environment-file parsing, and fail-fast legacy database notification migration.

Components

The 20260903 dependency and companion-release line is pinned as follows:

  • Go 1.27.1
  • minio-go/v7: upstream-compatible pseudo-version ending in 0e78d3f18efe; the temporary silo-go fork is retired from the server graph
  • madmin-go/v3: v3.0.110
  • silo-pkg/v3: v3.13.2, under its own github.com/pgsty/silo-pkg/v3 module path
  • embedded Console: v2.3.0, including the trusted-proxy, TLS, redaction, and WebSocket security work
  • bundled mcli: RELEASE.2026-09-03T07-13-05Z, with the mc compatibility alias preserved
  • Helm chart: 7.0.2, defaulting the server to pgsty/silo:RELEASE.2026-09-03T00-00-00Z and post-install jobs to pgsty/mc:RELEASE.2026-09-03T07-13-05Z

The server deliberately preserves the MinIO-compatible Go module and wire identifiers. Replacing an import target does not rename the public S3/Admin API, MINIO_* configuration, x-minio-* headers, /minio/* routes, or on-disk metadata.

Engineering cleanup

The final release pass removed complexity where it did not protect a compatibility or correctness boundary:

  • removed dead encryption helpers, obsolete handler paths, and unused event-target functions;
  • replaced a source-level exported-symbol inventory with the smaller served-route compatibility baseline;
  • removed the wait_pipe lint exclusion and migrated to gomodguard_v2;
  • consolidated CORS load-failure lifecycle changes behind two helpers instead of open-coding set operations in six paths;
  • narrowed site-replication imports to changed metadata fields;
  • gave dynamic-timeout tests their own random source so parallel tests cannot mutate a package-global seed;
  • retained the shared metadata lock, CORS tombstones, two-level replication trust, and adversarial tests because each protects a reproduced failure rather than a hypothetical abstraction.

The complete adversarial review, including the fixes found after the first “ready” claim, is recorded in SILO Server 20260903 Pre-release Review.

Upgrade checklist

Read Upgrading from RELEASE.2026-08-06 before changing production. At minimum:

  1. grant s3:DeleteObjectVersion to identities that intentionally delete explicit versions; add its Deny next to any Deny s3:DeleteObject intended to prevent permanent deletion;
  2. split custom admin grants for enable and disable operations;
  3. correct bare ARN prefixes before re-submitting policies;
  4. add connection strings to enabled legacy PostgreSQL/MySQL notification targets;
  5. verify applications that explicitly choose checksum algorithms or types;
  6. upgrade every member of a site-replication group before creating or changing per-bucket CORS;
  7. snapshot CORS configuration before rollback, because 20260806 does not understand it;
  8. switch every node of a distributed cluster to the same binary in one maintenance operation; mixed Silo binaries do not form a cluster.

The on-disk object and erasure formats are unchanged. This does not make a mixed-version cluster supported.

Known issues and explicit deferrals

These items are not fixed by this release:

  • Conditional delete (#10, PR #12). DeleteObject ignores HTTP If-Match and DeleteObjects ignores each <Object><ETag>. Both delete unconditionally. A reviewed single-object repair exists outside this release, but batch semantics and the original PR are incomplete; shipping a partial condition contract would be riskier than the documented deferral.
  • Non-CORS multi-site configuration deletion (#77). A peer can restore a policy, SSE, tag, or quota configuration deleted on another site. Single-site deployments are unaffected. CORS is not affected because it uses a tombstone-aware register. Deployments relying on these replicated deletions must verify every site.
  • ListMultipartUploads filters (#79). prefix behaves like an exact key match, while max-uploads, key-marker, and delimiter are not fully honored; see the conformance analysis.
  • Legacy federation CopyObject (#99, #100). The legacy federated backend can ignore a requested checksum algorithm and rejects inline source objects. Deployments not using that backend are unaffected.
  • Mixed-version site replication. A 20260806 peer accepts but ignores bucket CORS and continues reporting a mismatch. Do not configure CORS until all sites are upgraded.
  • Rollback of bucket CORS. 20260806 drops the unknown CORS field if it rewrites the bucket record. Export the configuration first and recreate it after upgrading again.

Open enhancement work such as ILM relocation (PR #60), broader SSE support (#61), operator discovery (#30), NATS target hot reload (#40), and Renovate (#20) is outside this release’s production-safety boundary.

Verification and evidence boundary

The complete local acceptance was run on ebac0ca73bbf251b070bb6df4d8005015841f901:

  • full cmd and internal test suites;
  • go test -race ./cmd, passing in 365.448 seconds;
  • lint with 0 issues, the rebrand/compatibility guard, generated-file checks, and govulncheck;
  • make verify across FS, erasure, distributed erasure, erasure sets, multi-pool, and IPv6 multi-pool: 174 PASS / 0 FAIL.

One subsequent one-line fix, 84e1580a4, clears the CORS load-failure bit after a successful on-demand GetConfig reload. Later dependency work moves the toolchain to Go 1.27.1 and x/crypto 0.56.0. On the reviewed server line, git diff --check, the CORS/Object Lock targeted race tests, rebrand guard, generated-file check, lint, Helm lint/render/package, and the seven-resource legacy-upgrade identity guard all pass; remote Go CI and VulnCheck are green on the final pre-release main line.

Delivery remains independently checkable rather than inferred from those source tests. The server GitHub release identifies the exact tagged source and package assets. The separately published mcli release is immutable, contains 19 verified assets, and publishes matching amd64/arm64 release and latest images. Shared package v3.13.2 and Console v2.3.0 retain their own release evidence.

Resolved issue ledger

The tracker was reconciled during release preparation. Core issues are closed; deliberately excluded work remains in its own open issue:

Tracker Resolution
#102 Closed by merged PR #103: shared metadata.lock and complete writer/migration/adoption coverage; reproduction-first residual audit split to #105
#58 Closed by merged PR #104: explicit-version authorization with multi-delete context preservation and least-privilege replication tests; PR #59 closed as superseded
#46, #47, #48, #50 Multipart checksum selection, computation, response, validation, and errors
#32, PR #37 Missing-bucket listing shortcut returns NoSuchBucket
PR #57 CompleteMultipartUploadResult.ChecksumType is present in the selected client/server stack

Selected changes

  • 1c9a2431f through 13e6458d9: implement per-bucket CORS and site replication
  • 938603458 through 04b097fd9, plus Snowball follow-ups: authenticate replication semantics and remove pre-authentication metadata I/O
  • f9f9fa6c9 through 32a1b81e4: reproduce and serialize cross-type bucket metadata updates
  • 3b5de82f5, 21646eebd: enforce Object Lock’s versioning invariant, including retention-rule documents
  • f8b598f1d through d2d47a41f: align explicit-version delete authorization
  • b73581b05, 474cd5801, 74c97d005: authenticate SSE-C zero-byte and attributes reads
  • 7fea6d5a5, 5d152416d, 7e079ff05, d28885d0e: align multipart checksum behavior
  • c0e715977, e73436c99, ffb70eb37: repair CopyObject transforms, checksums, and SSE-C rotation
  • 84e1580a4: clear the load-failure guard after an on-demand metadata reload succeeds

Acknowledgments

This release incorporates reports and proposed fixes from community contributors as well as the fork’s security and compatibility audit. In particular, the checksum, missing-bucket listing, and explicit-version authorization work started from public issues and pull requests. The release’s final shape also reflects adversarial review: findings were reproduced before repair, inherited limitations were separated from release regressions, and validation claims were rerun against the tree they describe.

The complete authorship record remains in CONTRIBUTORS.md.