Resolve SSRF in the function Execute

Add a function to block requests to private/internal addresses. SSRF resolved.
This commit is contained in:
Chengpeng Wang 2026-03-03 12:51:24 +08:00 committed by GitHub
parent 435223f500
commit 09d4f3ffb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"regexp"
@ -582,6 +583,24 @@ func (t *WebFetchTool) Parameters() map[string]any {
}
}
func blockPrivateTarget(ctx context.Context, parsedURL *url.URL) error {
hostname := parsedURL.Hostname() // strips port and IPv6 brackets
addrs, err := net.DefaultResolver.LookupHost(ctx, hostname)
if err != nil {
return fmt.Errorf("could not resolve host %q", hostname)
}
for _, addr := range addrs {
ip := net.ParseIP(addr)
if ip == nil {
continue
}
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified() {
return fmt.Errorf("requests to private/internal addresses are not allowed")
}
}
return nil
}
func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolResult {
urlStr, ok := args["url"].(string)
if !ok {
@ -601,6 +620,10 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe
return ErrorResult("missing domain in URL")
}
if err := blockPrivateTarget(ctx, parsedURL); err != nil {
return ErrorResult(err.Error())
}
maxChars := t.maxChars
if mc, ok := args["maxChars"].(float64); ok {
if int(mc) > 100 {