Tencent/WeKnora · error
unsafe MinIO endpoint: %w
Error message
unsafe MinIO endpoint: %w
What it means
newMinioClient validates the configured MinIO endpoint with utils.ValidateURLForSSRF before constructing the minio-go client, and wraps any validation failure as "unsafe MinIO endpoint: %w". This is a deliberate SSRF guard: endpoints pointing at loopback, link-local, private/metadata addresses, or malformed URLs are rejected before any network connection is made.
Source
Thrown at internal/application/service/file/minio.go:32
"github.com/Tencent/WeKnora/internal/types/interfaces"
"github.com/Tencent/WeKnora/internal/utils"
"github.com/google/uuid"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
// minioFileService MinIO file service implementation
type minioFileService struct {
client *minio.Client
bucketName string
}
// newMinioClient creates a bare minioFileService with just the SDK client initialised.
// Shared by NewMinioFileService (which also ensures the bucket exists) and
// CheckMinioConnectivity (read-only probe).
func newMinioClient(endpoint, accessKeyID, secretAccessKey, bucketName string, useSSL bool) (*minioFileService, error) {
if err := utils.ValidateURLForSSRF(endpoint); err != nil {
return nil, fmt.Errorf("unsafe MinIO endpoint: %w", err)
}
httpConfig := utils.DefaultSSRFSafeHTTPClientConfig()
client, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
Secure: useSSL,
Transport: &utils.SSRFValidatingRoundTripper{
Base: utils.NewSSRFSafeTransport(httpConfig),
},
})
if err != nil {
return nil, fmt.Errorf("failed to initialize MinIO client: %w", err)
}
return &minioFileService{client: client, bucketName: bucketName}, nil
}
// NewMinioFileService creates a MinIO file service.
// It verifies that the bucket exists and creates it if missing.
func NewMinioFileService(endpoint,View on GitHub (pinned to 988cbb0330)
Solutions
- Set the endpoint to a public, resolvable, non-private host (or an HTTPS domain fronting MinIO) that passes ValidateURLForSSRF
- Log/inspect the wrapped cause (errors.Unwrap) to see exactly which SSRF rule failed and correct the URL format accordingly
- If MinIO genuinely must live on an internal network, front it with an approved internal gateway/domain that the SSRF allowlist accepts, or extend utils.ValidateURLForSSRF allowlisting deliberately (with security review)
- Ensure the env var carries scheme+host consistently (e.g. minio.example.com vs https://minio.example.com) matching what the validator expects
Example fix
// before MINIO_ENDPOINT=http://127.0.0.1:9000 // rejected: loopback // after MINIO_ENDPOINT=https://minio.example.com // public endpoint, passes SSRF validation
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(endpoint)
if err != nil || u.Host == "" {
return fmt.Errorf("endpoint must be scheme+host, got %q", endpoint)
}
host := u.Hostname()
ip := net.ParseIP(host)
if host == "localhost" || (ip != nil && (ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified())) {
return fmt.Errorf("endpoint %q points to a private/loopback address and will be rejected by SSRF validation", endpoint)
} Try / catch
svc, err := file.NewMinioFileService(endpoint, ak, sk, bucket, useSSL)
if err != nil && strings.Contains(err.Error(), "unsafe MinIO endpoint") {
// fail fast at startup with a clear config message; do not retry
return fmt.Errorf("invalid MINIO_ENDPOINT %q: %w", endpoint, err)
} else if err != nil {
return err
} Prevention
- Validate MINIO_ENDPOINT at config-load/startup time, not at first use
- Never point the endpoint at localhost, 127.0.0.1, 169.254.169.254, or RFC1918 addresses in deployments with SSRF validation
- Use a public DNS name or an explicitly allowlisted internal domain for MinIO
- Review utils.ValidateURLForSSRF rules when planning network topology for MinIO
When it happens
Trigger: Calling NewMinioFileService or CheckMinioConnectivity with an endpoint that fails ValidateURLForSSRF: e.g. http://127.0.0.1:9000, http://169.254.169.254, localhost, 10.x/172.16-31.x/192.168.x addresses, missing scheme, or an otherwise invalid URL.
Common situations: Developers pointing MINIO_ENDPOINT at localhost for local development while the SSRF validator rejects private/loopback hosts; misconfigured env var left empty or containing a scheme-less value; Kubernetes setups where MinIO is reached via a cluster-internal .svc address that the validator considers private.
Related errors
- unsafe TOS endpoint: %w
- %w (for private deployments on internal networks, add the ho
- invalid qqbot api_base_url: %w (for private deployments, add
- MinerU URL blocked by SSRF check: %v
- failed to initialize MinIO client: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/f9071458374211c0.
Report an issue: GitHub.