From 8b7d3f2b16c14412fd79e7d7fd941f60a5ba7b11 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 02:37:09 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL]?= =?UTF-8?q?=20Fix=20Server-Side=20Request=20Forgery=20(SSRF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: himattm <6266621+himattm@users.noreply.github.com> --- internal/plugin/manager.go | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/internal/plugin/manager.go b/internal/plugin/manager.go index 7aad027..8d6b7d0 100644 --- a/internal/plugin/manager.go +++ b/internal/plugin/manager.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "net" "net/http" "net/url" "os" @@ -16,6 +17,7 @@ import ( "runtime" "sort" "strings" + "syscall" "time" "github.com/himattm/prism/internal/fsutil" @@ -24,6 +26,32 @@ import ( var metadataRegex = regexp.MustCompile(`^#\s*@(\w+[-\w]*)\s+(.+)$`) var versionRegex = regexp.MustCompile(`(?m)^#\s*@version\s+(.+)$`) +func safeHTTPClient() *http.Client { + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DisableKeepAlives = true + dialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + Control: func(network, address string, c syscall.RawConn) error { + host, _, err := net.SplitHostPort(address) + if err != nil { + return err + } + ip := net.ParseIP(strings.Split(host, "%")[0]) + if ip != nil && ip.String() == "169.254.169.254" { + return fmt.Errorf("SSRF restricted IP: %s", ip.String()) + } + return nil + }, + } + transport.DialContext = dialer.DialContext + + return &http.Client{ + Timeout: 10 * time.Second, + Transport: transport, + } +} + // sanitizeFilename ensures a filename cannot be used for path traversal func sanitizeFilename(name string) string { return filepath.Base(filepath.Clean("/" + name)) @@ -410,7 +438,8 @@ func (m *Manager) addScriptPlugin(owner, repo, pluginName string) error { fmt.Printf("Fetching script from: %s\n", rawURL) - resp, err := http.Get(rawURL) + client := safeHTTPClient() + resp, err := client.Get(rawURL) if err != nil { return fmt.Errorf("failed to fetch plugin: %w", err) } @@ -468,7 +497,8 @@ func (m *Manager) addFromDirectURL(rawURL string) error { return fmt.Errorf("unsupported URL scheme: %s", parsedURL.Scheme) } - resp, err := http.Get(parsedURL.String()) + client := safeHTTPClient() + resp, err := client.Get(parsedURL.String()) if err != nil { return fmt.Errorf("failed to fetch plugin: %w", err) }