mirror of
https://github.com/mudler/LocalAI.git
synced 2026-02-14 08:31:10 -05:00
User-supplied URLs passed to GetContentURIAsBase64() and downloadFile() were fetched without validation, allowing SSRF attacks against internal services. Added URL validation that blocks private IPs, loopback, link-local, and cloud metadata endpoints before fetching. Co-authored-by: kolega.dev <faizan@kolega.ai>
56 lines
1.4 KiB
Go
56 lines
1.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/mudler/xlog"
|
|
)
|
|
|
|
var base64DownloadClient http.Client = http.Client{
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
|
|
var dataURIPattern = regexp.MustCompile(`^data:([^;]+);base64,`)
|
|
|
|
// GetContentURIAsBase64 checks if the string is an URL, if it's an URL downloads the content in memory encodes it in base64 and returns the base64 string, otherwise returns the string by stripping base64 data headers
|
|
func GetContentURIAsBase64(s string) (string, error) {
|
|
if strings.HasPrefix(s, "http") || strings.HasPrefix(s, "https") {
|
|
if err := ValidateExternalURL(s); err != nil {
|
|
return "", fmt.Errorf("URL validation failed: %w", err)
|
|
}
|
|
|
|
// download the image
|
|
resp, err := base64DownloadClient.Get(s)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// read the image data into memory
|
|
data, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// encode the image data in base64
|
|
encoded := base64.StdEncoding.EncodeToString(data)
|
|
|
|
// return the base64 string
|
|
return encoded, nil
|
|
}
|
|
|
|
// Match any data URI prefix pattern
|
|
if match := dataURIPattern.FindString(s); match != "" {
|
|
xlog.Debug("Found data URI prefix", "prefix", match)
|
|
return strings.Replace(s, match, "", 1), nil
|
|
}
|
|
|
|
return "", fmt.Errorf("not valid base64 data type string")
|
|
}
|