Silo Console lets authenticated users create time-limited links that allow recipients to download an object without signing in. By default, these links use a public Console endpoint that proxies the download from the configured Silo server.
The endpoint checks that the initial URL points to that server, but not that it is a genuine presigned object URL. It can therefore proxy unauthenticated GET requests to other paths on the server. No configuration option disables this behavior without disabling the entire Console UI.
In a deployment running with MINIO_PROMETHEUS_AUTH_TYPE=public, the demonstrated impact is access across a network boundary to internal metrics endpoints. This is not a demonstrated general SSRF. Redirects could broaden the reachable targets, but no anonymous redirect primitive has been demonstrated.
Observed behavior
The route is declared without authentication (security: [],swagger.yml:3200-3204):
/api/v1/download-shared-object/{encoded-url}
decodeMinIOStringURL base64-decodes the supplied URL and compares its host to CONSOLE_MINIO_SERVER. It does not inspect the path, the query string, or the presence of X-Amz-Signature. Endpoints requiring SigV4 still reject the request. The Console relays the body only when the final response is 200 OK. For other responses, it reveals only the upstream status code and status text.
Security-boundary bypass
MINIO_PROMETHEUS_AUTH_TYPE=public removes authentication from the metrics endpoints on the Silo S3 API port. The Console port is reachable externally. The proxy target is the loopback endpoint 127.0.0.1:9000, which is not.
The proxy therefore carries an anonymous external request to an endpoint that is otherwise reachable only from inside the pod.
The encoded path is the base64url form of http://127.0.0.1:9000/minio/metrics/v3/cluster/usage/buckets; adjust the scheme and port to the deployment's CONSOLE_MINIO_SERVER value.
GET /api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL21pbmlvL21ldHJpY3MvdjMvY2x1c3Rlci91c2FnZS9idWNrZXRz
Host: <console-host>
(no Authorization header, no session cookie)
HTTP/1.1 200 OK
<Prometheus text exposition: one series per bucket, bucket
names as label values, with object counts and sizes>
The same method reaches /minio/v2/metrics/cluster, which returns node names, drive count and the quorum and erasure layout.
Why deployment-side mitigation fails
- Creating a share link through the Console requires authentication, but calling the proxy endpoint does not. Because callers can construct proxy URLs themselves, restricting share-link creation does not prevent anonymous use of the proxy.
CONSOLE_SHARE_MINIO_URL controls only the default format of generated share links. An authenticated user can select the other format for an individual link using toggle_url (api/user_objects.go:1074–1078). Neither setting disables or restricts the public proxy endpoint.
- The supported
CONSOLE_* environment variables include no option to disable object sharing or the public proxy (api/consts.go:20–91).
MINIO_BROWSER=off disables the entire embedded Console, including its UI. This is not a practical mitigation for deployments that require Console access.
Request
Would you consider a server-side option to disable object sharing? When set, it could reject share-link creation, reject requests to the public proxy, and hide the share controls in the UI.
As defense in depth, the HTTP client should reject redirects or apply the configured-host restriction to every redirect target. Merely requiring presigned-S3 query parameters would not be sufficient: an attacker could attach fake signing parameters to an otherwise public internal endpoint. A stronger design could authenticate the encoded proxy URL itself — for example, with a Console-generated MAC — or retain server-side state for issued share links. Silo would continue to validate the underlying S3 presigned request.
Version tested: Silo RELEASE.2026-09-03T13-18-01Z
Code: decodeMinIOStringURL, api/public_objects.go:45-113. The proxy behavior originates in MinIO Console commit ceee83f — "Use Console as proxy for share object logic" (#3284, April 2024).
Silo Console lets authenticated users create time-limited links that allow recipients to download an object without signing in. By default, these links use a public Console endpoint that proxies the download from the configured Silo server.
The endpoint checks that the initial URL points to that server, but not that it is a genuine presigned object URL. It can therefore proxy unauthenticated GET requests to other paths on the server. No configuration option disables this behavior without disabling the entire Console UI.
In a deployment running with
MINIO_PROMETHEUS_AUTH_TYPE=public, the demonstrated impact is access across a network boundary to internal metrics endpoints. This is not a demonstrated general SSRF. Redirects could broaden the reachable targets, but no anonymous redirect primitive has been demonstrated.Observed behavior
The route is declared without authentication (
security: [],swagger.yml:3200-3204):/api/v1/download-shared-object/{encoded-url}decodeMinIOStringURLbase64-decodes the supplied URL and compares its host toCONSOLE_MINIO_SERVER. It does not inspect the path, the query string, or the presence ofX-Amz-Signature. Endpoints requiring SigV4 still reject the request. The Console relays the body only when the final response is 200 OK. For other responses, it reveals only the upstream status code and status text.Security-boundary bypass
MINIO_PROMETHEUS_AUTH_TYPE=publicremoves authentication from the metrics endpoints on the Silo S3 API port. The Console port is reachable externally. The proxy target is the loopback endpoint 127.0.0.1:9000, which is not.The proxy therefore carries an anonymous external request to an endpoint that is otherwise reachable only from inside the pod.
The encoded path is the base64url form of
http://127.0.0.1:9000/minio/metrics/v3/cluster/usage/buckets; adjust the scheme and port to the deployment'sCONSOLE_MINIO_SERVERvalue.The same method reaches
/minio/v2/metrics/cluster, which returns node names, drive count and the quorum and erasure layout.Why deployment-side mitigation fails
CONSOLE_SHARE_MINIO_URLcontrols only the default format of generated share links. An authenticated user can select the other format for an individual link usingtoggle_url(api/user_objects.go:1074–1078). Neither setting disables or restricts the public proxy endpoint.CONSOLE_*environment variables include no option to disable object sharing or the public proxy (api/consts.go:20–91).MINIO_BROWSER=offdisables the entire embedded Console, including its UI. This is not a practical mitigation for deployments that require Console access.Request
Would you consider a server-side option to disable object sharing? When set, it could reject share-link creation, reject requests to the public proxy, and hide the share controls in the UI.
As defense in depth, the HTTP client should reject redirects or apply the configured-host restriction to every redirect target. Merely requiring presigned-S3 query parameters would not be sufficient: an attacker could attach fake signing parameters to an otherwise public internal endpoint. A stronger design could authenticate the encoded proxy URL itself — for example, with a Console-generated MAC — or retain server-side state for issued share links. Silo would continue to validate the underlying S3 presigned request.
Version tested: Silo
RELEASE.2026-09-03T13-18-01ZCode:
decodeMinIOStringURL, api/public_objects.go:45-113. The proxy behavior originates in MinIO Console commit ceee83f — "Use Console as proxy for share object logic" (#3284, April 2024).