SILO 20261112: Security Hardening, Service-Account Policy Inheritance and Multi-Pool Repairs
SILO Server 20261112 is now released. Tag: RELEASE.2026-11-12T00-00-00Z; package version: 20261112000000.0.0; source: 44e848fedf8c. It delivers the SN-2026-020 through SN-2026-025 security repairs, strict policy JSON decoding, Object Lock null-version and replica hardening, and multi-pool storage fixes after Server 20261109, built with Go 1.27.4 alongside embedded Console 2.7.2, mcli 20261112, and silo-pkg 3.16.1.
GitHub Release · Full Changelog · Security Advisories · Upgrade Guide · Downloads
Components
| Component | Released version | Fixed source |
|---|---|---|
| SILO Server | RELEASE.2026-11-12T00-00-00Z, package 20261112000000.0.0 |
44e848fedf8cec3d8c0da4b1aa8422390a2b7a8b |
| Embedded / standalone Console | v2.7.2 | 0e7953ff59c4a1eb77c7d203b265e6783ff18d01 |
| MC module / image-bundled mcli | 20261112 | a37a9f054fba828a0bbbceb4e9ff247ccf09c28d |
| Shared package | silo-pkg v3.16.1 | 433f7eefa714a30b72ca70c4dffcd5faca25804f |
| Optional external KES | 20261026 | e9b4f1acebc11d61b42f876da8df48f548750cc9 |
| Go / upstream S3 SDK | Go 1.27.4 / pinned upstream minio-go/v7 |
v7.4.2-0.20261025165926-320af050c445 |
The component matrix records exact module versions. Updating standalone Console, mcli, or silo-pkg does not replace components inside an older Server binary. KES remains a separate, optional external key service with its own release cycle. The maintained PGSTY stack is the supported target; upstream MinIO/MC compatibility remains best effort.
S3, replication and Object Lock security
- Single-pool
DeleteObjectscontainment (SN-2026-020): stops single-poolDeleteObjectsentries that fail object-name validation (..segments) before drive dispatch, returningXMinioInvalidObjectNameinstead of traversing into sibling buckets or.minio.sysor bypassingCOMPLIANCEObject Lock (a18293d0c). - Active-active tagging and read proxies (SN-2026-022, #337): authenticates
DeleteObjectTaggingbefore replication proxying, evaluates stored remote replica tags acrossGetObjectTagging,PutObjectTagging,DeleteObjectTagging, and proxiedGET/HEAD(14ecb222e,67a90dfef,293ab78b4,c39605d4f), fails closed on unreadable targets while skipping missing replicas caused by replication lag, and strips bothx-amz-tagging-count/X-Amz-Taggingand canonical-caseX-Amz-Object-Lock-*headers across local and proxiedGET/HEADresponses unless the corresponding tagging or retention/legal-hold read permission is granted without explicitDeny(ea37a7e8b). - SigV4 and streaming-trailer authentication (SN-2026-023, #338): enforces the 15-minute clock-skew window and
checkUnsignedHeaderscoverage on authenticatedSTREAMING-UNSIGNED-PAYLOAD-TRAILERuploads while keeping bucket-policy-authorized anonymous uploads intact (14ecb222e,296c9710b), and rejects SigV4 credential-scope date mismatches, negativeX-Amz-Decoded-Content-Lengthheaders, and truncated or oversized (> 64 KiB) streaming trailers. - Stored-tag and version authorization (SN-2026-024, #293, #342): evaluates
s3:ExistingObjectTag/<key>onGetObjectAttributes,CopyObject,UploadPartCopy,SelectObjectContent, and side-effect-free in-memory ZIP member reads/listings (s3:ListBucket+s3:GetObject), preserves5xxstorage read-quorum errors on tag-conditionedGET/HEAD, evaluatesCopyObjectCOPY-directive destination tag conditions against the tags actually copied, and enforces explicit version-action denies on version-addressed reads and tagging calls while retaining legacy base-action grants when no explicit version deny applies. - Replica and
null-version Object Lock (#336): reconciles destination lock/tag state under the mutation lock, verifies staged replica content hashes, SSE-C status, and compressedActualSizebefore committing, prevents peer timestamps from weakening unexpiredCOMPLIANCEretention, requires header-based SigV4 signing onX-Minio-Replication-*headers, fails closed whenx-minio-force-deletecannot read bucket lock metadata (cf486df66), and protects lockednullversions in versioning-suspended or prefix-excluded buckets against overwrites, delete markers, and shadowed unversionedDELETEcalls across single-pool and multi-pool deployments.
IAM, service accounts and strict policy validation
- Service-account inline policy tri-state (SN-2026-021, SN-2026-025, #331, #339, #345):
UpdateServiceAccountpreserves existing inline session policies whennewPolicyis omitted ornull(including historical pre-20261111emptyembedded-policydeny-all accounts), removes the inline restriction and restores parent inheritance only when an explicit empty policy document ({}or{"Statement":[]}) is sent, and fills defaultVersion: "2012-10-17"on nonempty versionless inline policies. IAM imports preserve disabled service-account and group states and report group failures accurately (1d714834c). - Strict policy JSON decoding: IAM named policies, service-account session policies, STS
Policyparameters, IAM imports/replication, and bucket policies reject unknown JSON fields, trailing tokens, non-object inputs, emptyPrincipal: {}, and unsupportedNotPrincipalblocks via silo-pkg v3.16.1 (34ba7cc1f), validating whole policy archives before applying entries while keeping stored on-disk IAM policy reads and explicitnullbucket-policy replication tombstones compatible. - Site-replication concurrency and credential hygiene: IAM healing, bucket/metadata healing, status collection, and replication hooks snapshot site topology and release the cluster state lock before storage I/O and peer RPCs (design note), and exported/replicated credentials strip derived policy claims.
Storage pools, compressed encrypted ranges, lifecycle and batch
- Multi-pool copy and moving-pool authority (#343): historical-version self-copy (
PUT ?versionId=...to the same key) creates a readable new version across multi-pool clusters for plaintext, SSE-S3, SSE-KMS, SSE-C, and multi-block S2 compressed objects (Parts[0].Indexpreserved), and in-place replica metadata updates preserve authoritative content on draining/rebalancing pools (design note). - Compressed + encrypted
Rangereads: indexed byte-range reads on objects using both compression and server-side encryption (SSE-S3,SSE-KMS,SSE-C) advance DARE decryption frames accurately when the target compressed block starts inside the first 64 KiB encrypted frame (decryptSkip > 0), without rewriting existing objects, while still failing closed on corrupted DARE authentication tags (939cb2600). - Lifecycle/restore revision quorum and metadata cache (#332, #344): normalizes pre-
2024-04-28partially healedxl.metaheaders (design note) and clears the time-dependentxlFlagUsesDataDirbit fromrevisionKeycomparisons so partial heals and expired restored copies do not split cross-drive quorum; guardsBucketMetadataSys.GetConfigagainst stale cache overwrites. - Pool decommission (#334): stops stalled passes that make zero physical progress, returns cancellation errors promptly, rescans child keys previously hidden beneath an exact object key, and tolerates offline drives within the erasure set’s read quorum when verifying source cleanup.
- SSE-KMS encryption context and batch
keyrotate: S3 write endpoints (PutObject,CopyObject,CreateMultipartUpload, browserPOST) reject empty, malformed Base64/UTF-8/JSON, trailing-token, or non-string/non-nullX-Amz-Server-Side-Encryption-Contextheaders with400 InvalidArgumentinstead of500 InternalError. Batchkeyrotatepreserves configured KMS context across execution, retry, and manifest reload (design note), stream-rewrites legacyXLV1objects ontoXLV2with sealed plaintext MD5 ETags and preserved tags/expiry, and keeps internal multipart/tier headers duringSSE-S3->SSE-KMSrotation.
Console, client and dependencies
Embedded and standalone Console 2.7.2 carries forward 2.7.1’s tri-state service-account policy editor, in-modal error reporting, strict policy JSON validation, and --host 0.0.0.0 / CONSOLE_SECURE_TLS_HOST HTTP-to-HTTPS redirect host preservation (unrolled/secure v1.18.0), with synchronized 2.7.2 release metadata and optimized web assets. mcli 20261112 aligns explicit empty-policy ({}) resets across access-key edit commands (#78) and enforces client-side strict policy JSON validation. silo-pkg 3.16.1 provides ParseConfigStrict / ParseBucketPolicyConfig hardening and base dependency updates on Go 1.27.4, while retaining go-systemd v22.6.0 for NetBSD cross-compilation (72a6047bf). Release gates now verify the coordinated silo-pkg, embedded Console v2.7.2, mcli tag/commit, DCO sign-off on main, and Helm chart 7.0.5 appVersion/image.tag alignment (c83dbe0ea).
Upgrade and rollback
- Verify
.minio.sysquorum and retain 20261109 rollout prerequisites. Confirm healthy read quorum across erasure sets before restarting. When upgrading directly from20261026or earlier, also follow the 20261109 upgrade checklist (drain or cancel unfinished batch jobs; stop all nodes simultaneously on single-pool layouts whose erasure sets do not share identical hosts, such as 18+ auto-layout hosts; pausePOST ?restoreduring mixed-version windows). - Drain or pause concurrent S3 writes during mixed-version multi-pool rolling restarts. Old and new nodes can otherwise interleave multi-pool write lock ordering or skip suspended/excluded
null-version Object Lock checks on un-upgraded peers until every node runs20261112. - Freeze service-account edits on un-upgraded
20261109sites during multi-site rollout. On20261109and earlier, status toggles or metadata edits without--policystill strip inline session policies and replicate that weakened state. After every site runs20261112, audit accounts wheremcli admin user svcacct inforeportsPolicy: impliedagainst reviewed intended policies rather than running a blindsite-replication resync. - Audit policy automation for strict JSON compliance before rollout. Automated tooling that submits misspelled IAM or bucket policy keys (for example
Conditionsinstead ofCondition), trailing JSON, emptyPrincipal: {},NotPrincipal, or non-string KMS encryption-context values now receives400instead of silent field dropping or500. - Verify per-node S3 data paths and set Helm
image.tagexplicitly. Run bounded signed S3 write/read checks against every restarted node, and pass--set image.tag=RELEASE.2026-11-12T00-00-00Zwhen runninghelm upgrade --reuse-valueswith chart7.0.5.
Costs and limits
Every explicit version removal (VersionId specified) in S3 DeleteObjects now executes sequentially through the single-object path across all buckets — including buckets without Object Lock — as do unaddressed deletes that could replace a locked null version, so large explicit version-purge batches take longer than unversioned bulk deletes. Ordinary delete-marker creation and unversioned deletes that do not touch locked null versions retain concurrent bulk execution.
Storage timeouts still do not prove that a disk write did not commit, and this release does not add distributed fencing or recover previously deleted data or stripped policies. Known open limitations remain in ListMultipartUploads prefix/pagination (#79), multi-site delete-marker purges (#217), replayed bucket creation under site replication (PR #241), and upstream SDK multipart-completion retry headers (mcli put --if-not-exists; see multipart completion retries).
Delivery and verification
Release commit 44e848fedf8c passed Go CI, VulnCheck, DCO, Test Release Pipeline, the tagged release build, package finalization, and multi-arch Docker publication, along with eight-node two-pool runtime verification across compressed encrypted range reads, replication proxy header authorization, service-account tri-state policy updates, and upgrade checks.
The GitHub release publishes 36 Server assets (Linux/macOS tar.gz and Windows ZIP archives, GPG-signed x86_64 and aarch64 RPMs, DEB and APK packages, SHA-256 checksums, SPDX SBOMs, Sigstore bundles, and provenance attestations), alongside 44 Console 2.7.2 assets, 19 mcli 20261112 assets, 19 KES 20261026 assets, and the source-only silo-pkg 3.16.1 module. Multi-architecture container images (linux/amd64 and linux/arm64) are published on Docker Hub:
docker.io/pgsty/silo:RELEASE.2026-11-12T00-00-00Z(latest):sha256:c20d112390b9a9ce8c11b8af95ad35bcaa62f4759663c09c936cd8d2b511f329docker.io/pgsty/silo:RELEASE.2026-11-12T00-00-00Z-distroless(distroless):sha256:a72e17773bdeb151999f9bf9d3bd842fb03850a577b730ab8c63343bb1f468fd
Thanks to @botdeniska for the tag-conditioned read-error and pool-decommission nested-key fixes (#294, #335) and the bulk-delete Object Lock report behind SN-2026-020, and @seumasdunlop for the Helm chart default image tag report (#296). Component and community credits are recorded in the contributor record.
Source Changelog · Changes Since 20261109