### Minimal SafeURL Client Example Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Demonstrates creating a SafeURL client with a basic configuration and making a protected HTTP GET request. Ensure the target host is allowed in the configuration. ```go package main import ( "fmt" "github.com/doyensec/safeurl" ) func main() { // Create configuration with default settings config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). Build() // Create SafeURL client client := safeurl.Client(config) // Make a request (protected by SafeURL validation) resp, err := client.Get("https://example.com") if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() fmt.Printf("Status: %d\n", resp.StatusCode) } ``` -------------------------------- ### Minimal SafeURL Example in Go Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/README.md Demonstrates basic usage of SafeURL to create a client with a configured allowed host and make a GET request. Ensure the 'github.com/doyensec/safeurl' package is imported. ```go package main import ( "fmt" "github.com/doyensec/safeurl" ) func main() { config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). Build() client := safeurl.Client(config) resp, err := client.Get("https://example.com") if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() fmt.Printf("Status: %d\n", resp.StatusCode) } ``` -------------------------------- ### Example Test with SafeURL Client and Test Servers Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/utilities.md Demonstrates how to configure and use the SafeURL client in test mode, interacting with the running test servers. This setup is crucial for end-to-end testing of SafeURL's functionality. ```go // In test file: config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("service.test"). Build() client := safeurl.Client(config) // Make request (requires test server running) resp, err := client.Get("http://service.test:8080") ``` -------------------------------- ### Install SafeURL Go Module Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Add the SafeURL module to your Go project using the go get command or by updating your go.mod file. ```bash go get github.com/doyensec/safeurl ``` ```go require github.com/doyensec/safeurl v1.x.x ``` -------------------------------- ### Builder Constructor Example Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Demonstrates chaining multiple builder methods to configure allowed hosts, ports, and then building the final configuration. This is a common pattern for setting up SafeURL. ```go builder := safeurl.GetConfigBuilder(). SetAllowedHosts("api.example.com"). SetAllowedPorts(80, 443, 8080). Build() ``` -------------------------------- ### Configure and create SafeURL client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Example of building a SafeURL client with specific allowed hosts and ports. This client can then be used to make secure HTTP requests. ```Go package main import ( "fmt" "github.com/doyensec/safeurl" ) func main() { config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com", "api.github.com"). SetAllowedPorts(80, 443). Build() client := safeurl.Client(config) resp, err := client.Get("https://example.com") if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() // Process response... } ``` -------------------------------- ### Build and Use SafeURL Client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Configure the SafeURL client with allowed hosts, ports, schemes, timeouts, and credential settings. Then, use the client to make a GET request and handle potential errors. ```go package main import ( "fmt" "io" "time" "github.com/doyensec/safeurl" ) func main() { // Build secure configuration config := safeurl.GetConfigBuilder(). SetAllowedHosts("api.example.com", "cdn.example.com"). SetAllowedPorts(443). SetAllowedSchemes("https"). SetTimeout(10 * time.Second). AllowSendingCredentials(false). EnableDebugLogging(true). Build() // Create protected client client := safeurl.Client(config) // Make request resp, err := client.Get("https://api.example.com/data") if err != nil { switch err.(type) { case *safeurl.AllowedHostError: fmt.Println("Host not allowed") case *safeurl.AllowedIPError: fmt.Println("IP not allowed") case *safeurl.AllowedPortError: fmt.Println("Port not allowed") default: fmt.Printf("Error: %v\n", err) } return } defer resp.Body.Close() // Read response body, _ := io.ReadAll(resp.Body) fmt.Printf("Status: %d\n", resp.StatusCode) fmt.Printf("Body: %s\n", string(body)) } ``` -------------------------------- ### Run SafeURL Unit Tests Source: https://github.com/doyensec/safeurl/blob/main/README.md After starting the local servers, run this command to execute all unit tests for the safeurl library. ```bash go test -v ``` -------------------------------- ### Example Allowed URLs for Credentials Validation Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md These URLs are allowed when `AllowSendingCredentials(true)` is configured. ```text https://user:pass@example.com https://admin:secret123@api.example.com ``` -------------------------------- ### Run Local DNS and HTTP Servers for Testing Source: https://github.com/doyensec/safeurl/blob/main/README.md Execute this command to start the necessary local servers required for running the unit tests of the safeurl library. ```bash go run testing/servers.go ``` -------------------------------- ### GetConfigBuilder() - Create New Builder Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Initializes a new configuration builder with default security policy settings. Use this as the starting point for configuring SafeURL. ```go builder := safeurl.GetConfigBuilder() ``` -------------------------------- ### Minimal SafeURL Configuration (Public IPs) Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Builds a basic SafeURL configuration that only allows public IP addresses. This is a good starting point for most use cases. ```go config := safeurl.GetConfigBuilder().Build() client := safeurl.Client(config) ``` -------------------------------- ### Making HTTP Requests with SafeURL Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Demonstrates how to perform GET, HEAD, POST (JSON and form data), and custom requests using the SafeURL client. All methods include SafeURL validation. ```go // GET request resp, err := client.Get("https://example.com/api") ``` ```go // HEAD request resp, err := client.Head("https://example.com") ``` ```go // POST with JSON resp, err := client.Post( "https://api.example.com/data", "application/json", bytes.NewReader(jsonData), ) ``` ```go // POST form data data := url.Values{} data.Set("key", "value") resp, err := client.PostForm("https://example.com/form", data) ``` ```go // Custom request (with headers, etc.) req, _ := http.NewRequest("PATCH", url, body) req.Header.Set("X-Custom", "value") resp, err := client.Do(req) ``` -------------------------------- ### Get Method Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Performs a GET request to the specified URL with SSRF validation. ```APIDOC ## Get ### `Get(url string) (*http.Response, error)` Performs a GET request to the specified URL with SSRF validation. **Parameters**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | url | `string` | Yes | The target URL (must include scheme, e.g., `https://example.com`) | **Returns**: `(*http.Response, error)` — Response object or error if validation fails or request fails. **Throws/Rejects**: | Error Type | Condition | |------------|-----------| | `AllowedHostError` | Host not in allowlist | | `AllowedIPError` | Resolved IP not in allowlist or in blocklist | | `AllowedPortError` | Port not in allowlist | | `AllowedSchemeError` | Scheme not in allowlist | | `IPv6BlockedError` | IPv6 disabled but IPv6 address used | | `SendingCredentialsBlockedError` | Credentials in URL when not allowed | | `InvalidHostError` | Empty or unparseable host | **Example**: ```go resp, err := client.Get("https://example.com/api/endpoint") if err != nil { if _, ok := err.(*safeurl.AllowedHostError); ok { fmt.Println("Host not allowed") } return } defer resp.Body.Close() fmt.Printf("Status: %d\n", resp.StatusCode) ``` ``` -------------------------------- ### Perform a GET request with SafeURL client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Execute a GET request to a specified URL using the SafeURL client. The client automatically validates the URL against configured security policies before sending the request. Handles various SSRF-related errors. ```Go resp, err := client.Get(url) ``` ```Go resp, err := client.Get("https://example.com/api/endpoint") if err != nil { if _, ok := err.(*safeurl.AllowedHostError); ok { fmt.Println("Host not allowed") } return } deferr resp.Body.Close() fmt.Printf("Status: %d\n", resp.StatusCode) ``` -------------------------------- ### Complete Validation Flow - Credentials Blocked Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md Demonstrates a validation flow where sending credentials is blocked by configuration, resulting in an error. This example shows the request, configuration, and the resulting failure. ```text Request: client.Get("https://user:pass@api.example.com:8080") [1. Parse URL] → OK URL: https://user:pass@api.example.com:8080 [2. Validate Credentials] Config: AllowSendingCredentials = false (default) Found credentials: user:pass Result: FAIL → SendingCredentialsBlockedError ``` -------------------------------- ### Example Blocked URLs for URL Parsing Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md These URLs fail basic URL format validation during the parsing stage. ```text http://[invalid-ipv6-format http://space in url.com ``` -------------------------------- ### Handle Blocked Credential Sending Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Shows examples of URLs with embedded credentials that trigger SendingCredentialsBlockedError by default and how to allow them. ```go // Default config (credentials blocked) config := safeurl.GetConfigBuilder().Build() client := safeurl.Client(config) // These fail with SendingCredentialsBlockedError resp, err := client.Get("https://user:pass@example.com") // Error: SendingCredentialsBlockedError resp, err := client.Get("https://admin:secret123@api.example.com") // Error: SendingCredentialsBlockedError ``` ```go // Allowing credentials config := safeurl.GetConfigBuilder(). AllowSendingCredentials(true). Build() client := safeurl.Client(config) // Now credentials are allowed resp, err := client.Get("https://user:pass@example.com") // Succeeds (subject to other validation) ``` -------------------------------- ### Complete Validation Flow - Host Not Allowed Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md Illustrates a validation scenario where the requested host is not present in the allowed hosts list, leading to an `AllowedHostError`. This example details the request, configuration, and the validation steps. ```text Request: client.Get("https://api.example.com:443") Config: AllowedHosts: ["example.com"] AllowedPorts: [443] AllowedSchemes: ["https"] AllowedIPsCIDR: ["93.184.216.0/24"] [1. Parse URL] → OK [2. Validate Credentials] → OK (no credentials) [3. Validate Scheme] Scheme: https In allowed: ["https"] Result: OK [4. Validate Host] Host: api.example.com In allowed: ["example.com"] Result: FAIL → AllowedHostError ``` -------------------------------- ### Minimal Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Creates a SafeURL client with default settings. This is the simplest way to initialize the client. ```go // Uses all defaults (HTTP/HTTPS on ports 80/443, public IPs only) config := safeurl.GetConfigBuilder().Build() client := safeurl.Client(config) ``` -------------------------------- ### Build and Initialize Client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Validate configuration at application startup by calling Build(). This panics on invalid configuration, catching errors early. Then, initialize the SafeURL client. ```go // Build() panics on invalid config (bad IP/CIDR/port) // Place at application startup to catch errors early config := builder.Build() client := safeurl.Client(config) ``` -------------------------------- ### HTTP GET Request Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/README.md Performs an HTTP GET request to the specified URL, applying SafeURL's validation and security measures. ```APIDOC ## HTTP GET Request ### Description Executes an HTTP GET request to the given URL. ### Method `.Get(url)` ### Parameters - **url** (string) - The URL to send the GET request to. ``` -------------------------------- ### Configure SafeURL Client with Allowed Hosts Source: https://github.com/doyensec/safeurl/blob/main/README.md Demonstrates how to initialize the safeurl.Client with a specific configuration, setting allowed hosts. Ensure the 'github.com/doyensec/safeurl' module is included in your project. ```go import ( "fmt" "github.com/doyensec/safeurl" ) func main() { config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). Build() client := safeurl.Client(config) resp, err := client.Get("https://example.com") if err != nil { fmt.Errorf("request return error: %v", err) } // read response body } ``` -------------------------------- ### Example Blocked URLs for Credentials Validation Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md These URLs contain embedded credentials, which are blocked by default. ```text https://admin:password@example.com https://user:@example.com https://:password@example.com ``` -------------------------------- ### Testing with Local DNS and SafeURL Client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/utilities.md Shows how to configure and use the SafeURL client in test mode with a local DNS server. This requires running a local server as specified in the comments. ```go func TestWithLocalDNS(t *testing.T) { config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("example.com"). Build() client := safeurl.Client(config) // Requires: go run testing/servers.go resp, err := client.Get("http://example.com:8080") if err != nil { t.Fatalf("Failed: %v", err) } defer resp.Body.Close() if resp.StatusCode != 200 { t.Errorf("Expected 200, got %d", resp.StatusCode) } } ``` -------------------------------- ### Handle IPv6 Connection Blocking Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Demonstrates how IPv6 connections are blocked by default and how to enable them. ```go // Default config (IPv6 disabled) config := safeurl.GetConfigBuilder().Build() client := safeurl.Client(config) // This fails with IPv6BlockedError resp, err := client.Get("https://[::1]") // Error: IPv6BlockedError resp, err := client.Get("https://[2606:2800:220:1:248:1893:25c8:1946]") // Error: IPv6BlockedError ``` ```go // Enabling IPv6 config := safeurl.GetConfigBuilder(). EnableIPv6(true). Build() client := safeurl.Client(config) // Now IPv6 addresses are allowed (subject to IP validation) resp, err := client.Get("https://[2606:2800:220:1:248:1893:25c8:1946]") // Succeeds (subject to other validation) ``` -------------------------------- ### Build SafeURL Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Demonstrates how to use the configuration builder to set allowed hosts and ports for a SafeURL client. This is useful for restricting the domains and ports the client can connect to. ```go config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). SetAllowedPorts(443). Build() ``` -------------------------------- ### Client Constructor Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Creates a new SSRF-protected HTTP client with the given configuration. ```APIDOC ## Client Constructor ### `Client(config *Config) *WrappedClient` Creates and returns a new SSRF-protected HTTP client with the given configuration. **Parameters**: | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | config | `*Config` | Yes | — | Configuration object defining allowed/blocked hosts, IPs, ports, schemes | **Returns**: `*WrappedClient` — A wrapped HTTP client ready for use. The underlying `http.Client` is exposed as the `Client` field. **Example**: ```go package main import ( "fmt" "github.com/doyensec/safeurl" ) func main() { config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com", "api.github.com"). SetAllowedPorts(80, 443). Build() client := safeurl.Client(config) resp, err := client.Get("https://example.com") if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() // Process response... } ``` ``` -------------------------------- ### Create a new SafeURL client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Instantiate a new SSRF-protected HTTP client using a configuration object. The configuration defines security policies like allowed hosts and ports. ```Go client := safeurl.Client(config) ``` -------------------------------- ### Configure Allowed Hosts Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Use `SetAllowedHosts` to define a whitelist of hosts. Subdomains must be explicitly listed. Host matching is case-insensitive. ```go builder.SetAllowedHosts("example.com") ``` ```go builder.SetAllowedHosts("example.com", "api.example.com", "cdn.example.com") ``` ```go builder.SetAllowedHosts("api.example.com") ``` ```go builder.SetAllowedHosts("api.example.com", "app.example.com") ``` -------------------------------- ### Get IPs in CIDR Range Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/utilities.md Enumerates all individual IP addresses within a given CIDR range. Be cautious with large ranges as it can be memory-intensive. IPs are returned in order from network to broadcast address. ```Go ips := safeurl.GetIPsInCIRDRange("192.168.1.0/24") ``` ```Go // Small range ips := safeurl.GetIPsInCIRDRange("192.168.1.0/30") // Returns: []string{"192.168.1.0", "192.168.1.1", "192.168.1.2", "192.168.1.3"} ``` ```Go // Single IP (as /32) ips := safeurl.GetIPsInCIRDRange("8.8.8.8/32") // Returns: []string{"8.8.8.8"} ``` -------------------------------- ### Configure and Use AllowedHosts in Go Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Illustrates configuring SafeURL with an explicit allowlist for hosts and demonstrates a successful request and a request that fails with AllowedHostError. This error is only checked if AllowedHosts is explicitly set. ```go // Config with explicit allowlist config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). Build() // This succeeds client.Get("https://example.com") // This fails with AllowedHostError client.Get("https://api.example.com") ``` ```go resp, err := client.Get("https://example.com") if err != nil { if _, ok := err.(*safeurl.AllowedHostError); ok { fmt.Println("Host not in allowlist") } } ``` -------------------------------- ### Configure Allowed IPs Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Use `SetAllowedIPs` to create an allowlist of specific IP addresses. Invalid IP formats will cause a panic at `Build()` time. This takes precedence over all other IP rules for positive matching. ```go builder.SetAllowedIPs("93.184.216.34") ``` ```go builder.SetAllowedIPs("93.184.216.34", "2606:2800:220:1:248:1893:25c8:1946") ``` ```go builder.SetAllowedIPs("2606:2800:220:1:248:1893:25c8:1946") ``` -------------------------------- ### Complete Validation Flow - Successful Execution Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md Presents a successful validation flow for a SafeURL request, covering all steps from URL parsing to port validation. This example shows a request that passes all configured checks. ```text Request: client.Get("https://example.com:443") Config: AllowedHosts: ["example.com"] AllowedPorts: [443] AllowedSchemes: ["https"] IsIPv6Enabled: false [1. Parse URL] → OK [2. Validate Credentials] → OK [3. Validate Scheme] → OK [4. Validate Host] → OK [5. DNS Resolution] example.com → 93.184.216.34 [6. Validate IP Address] IP: 93.184.216.34 AllowedIPs: nil BlockedIPs: nil Is private?: NO Result: OK [7. Validate Port] Port: 443 In allowed: [443] Result: OK → Request Executed Successfully ``` -------------------------------- ### Client Constructor Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/README.md Creates a new SafeURL client instance with the provided configuration. ```APIDOC ## Client Constructor ### Description Creates a new SafeURL client instance. ### Method `Client(config)` ### Parameters - **config** (Config) - The configuration object for the client. ``` -------------------------------- ### Enable Test Mode Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Activate test mode for local development and testing. Uses a local DNS resolver and enables DNS tracing. Requires a test DNS server to be running. ```go // Enable test mode config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("service.test"). Build() client := safeurl.Client(config) // In another terminal: // $ go run testing/servers.go // Then run your tests ``` -------------------------------- ### Build Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Finalizes the configuration and returns a Config object ready for client creation. ```APIDOC ## Build() *Config ### Description Finalizes the configuration and returns a `Config` object ready for client creation. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Returns - **Config** (*Config) - A ready-to-use configuration object ### Behavior - Normalizes all string values (lowercase, trimmed) - Parses all IP and CIDR strings; panics on invalid formats - Validates port numbers (1-65535); panics on invalid values - Must be called after all configuration calls ### Example ```go config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). SetAllowedPorts(443). SetAllowedSchemes("https"). Build() ``` ``` -------------------------------- ### Configure Allowed Hosts Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Specify a whitelist of allowed hosts for enhanced security. This is more secure than using blacklists. ```go .SetAllowedHosts("api.trusted.com") ``` -------------------------------- ### Build Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/README.md Finalizes the configuration settings and returns the complete configuration object. ```APIDOC ## Build Configuration ### Description Finalizes the configuration settings. ### Method `.Build()` ### Returns - Config: The finalized configuration object. ``` -------------------------------- ### Configuration Builder Methods Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Methods for building and customizing the SafeURL client configuration. ```APIDOC ## Configuration Builder ### Description Allows for the fluent configuration of the SafeURL client's behavior and security settings. ### Methods - **GetConfigBuilder()**: Constructor for the configuration builder. - **SetTimeout(timeout time.Duration)**: Sets the request timeout. - **SetCheckRedirect(f func(req *http.Request, via []*http.Request) error)**: Configures the redirect policy. - **SetCookieJar(jar http.CookieJar)**: Sets a custom cookie jar. - **SetAllowedSchemes(schemes ...string)**: Defines allowed URL schemes. - **SetAllowedHosts(hosts ...string)**: Defines allowed hostnames. - **SetAllowedPorts(ports ...int)**: Defines allowed ports. - **SetBlockedIPs(ips ...string)**: Defines IP addresses that are blocked. - **SetAllowedIPs(ips ...string)**: Defines IP addresses that are allowed. - **SetBlockedIPsCIDR(cidrs ...string)**: Defines CIDR blocks that are blocked. - **SetAllowedIPsCIDR(cidrs ...string)**: Defines CIDR blocks that are allowed. - **EnableIPv6()**: Enables IPv6 support. - **EnableDebugLogging()**: Enables debug logging. - **AllowSendingCredentials()**: Allows sending credentials. - **EnableTestMode()**: Enables test mode. - **SetTlsConfig(config *tls.Config)**: Sets custom TLS configuration. - **SetTransport(transport http.RoundTripper)**: Sets a custom HTTP transport. - **Build() (*Config, error)**: Builds and returns the final configuration. ``` -------------------------------- ### Set Allowed IP Addresses Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Establishes a whitelist of IP addresses. Only IPs within this list (and not blocked by other rules) will be permitted. Invalid IPs will cause a panic during Build(). ```go builder := builder.SetAllowedIPs("93.184.216.34", "2606:2800:220:1:248:1893:25c8:1946") ``` ```go builder.SetAllowedIPs("93.184.216.34") // Only this IP allowed ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Enable verbose logging of validation steps and connection attempts to stdout. Logs are prefixed with '[safeurl]'. Minimal performance impact. ```go // Enable debug logging builder.EnableDebugLogging(true) ``` ```go // Disable debug logging (default) builder.EnableDebugLogging(false) ``` -------------------------------- ### Troubleshoot Scheme Not Allowed Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md For 'scheme not allowed' errors, specify the necessary URL schemes (protocols) in your configuration. ```go config := safeurl.GetConfigBuilder(). SetAllowedSchemes("https", "wss"). // Add your scheme Build() ``` -------------------------------- ### Minimal SafeURL Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Builds a basic configuration that allows HTTP/HTTPS to public IPs on ports 80/443. It blocks IPv6, credentials, and private IPs by default. ```go config := safeurl.GetConfigBuilder().Build() // Allows: HTTP/HTTPS to public IPs on ports 80/443 // Blocks: IPv6, credentials, private IPs ``` -------------------------------- ### Configure Allowed Hosts Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md Specify a list of hostnames that are permitted. If not set, all hostnames are allowed (subject to IP validation). Exact matches are required, and subdomains must be explicitly listed. ```go // No host allowlist - all hostnames allowed (subject to IP validation) .SetAllowedHosts() // or omit the call ``` ```go // Specific hosts only .SetAllowedHosts("example.com", "api.example.com") ``` -------------------------------- ### Production-Secure SafeURL Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Sets up a secure configuration for production environments, enforcing HTTPS, allowing only port 443, and setting a timeout. This is recommended for handling untrusted URLs. ```go config := safeurl.GetConfigBuilder(). SetAllowedSchemes("https"). SetAllowedPorts(443). SetTimeout(10 * time.Second). Build() ``` -------------------------------- ### Configure Allowed Schemes Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/validation-flow.md Customize the list of permitted URL schemes. By default, only 'http' and 'https' are allowed. Use this to enable protocols like 'wss'. ```go // Allow WebSocket .SetAllowedSchemes("https", "wss") ``` ```go // HTTPS only .SetAllowedSchemes("https") ``` -------------------------------- ### Testing IP Enumeration with SafeURL Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/utilities.md Demonstrates how to retrieve a list of IP addresses within a specified CIDR range using the GetIPsInCIRDRange function. This is useful for testing IP-related logic. ```go package main import ( "fmt" "github.com/doyensec/safeurl" ) func main() { // Get first 10 IPs in a range ips := safeurl.GetIPsInCIRDRange("10.0.0.0/24") for i, ip := range ips { if i >= 10 { break } fmt.Println(ip) } // Output: // 10.0.0.0 // 10.0.0.1 // ... // 10.0.0.9 } ``` -------------------------------- ### Configure SafeURL for Development with Self-Signed Certificates Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md This pattern enables debugging and allows the use of self-signed certificates during development by skipping TLS verification. Warning: Never use `InsecureSkipVerify: true` in production environments. ```go import "crypto/tls" config := safeurl.GetConfigBuilder(). SetTlsConfig(&tls.Config{ InsecureSkipVerify: true, // ⚠️ DEV ONLY }). EnableDebugLogging(true). Build() client := safeurl.Client(config) ``` -------------------------------- ### Builder Constructor Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Creates a new configuration builder with default settings. This is the entry point for configuring SafeURL policies. ```APIDOC ## GetConfigBuilder() ### Description Creates a new configuration builder with sensible defaults. ### Method GET ### Endpoint /configBuilder ### Returns - `*configBuilder` — A new builder instance ### Example ```go builder := safeurl.GetConfigBuilder() ``` ``` -------------------------------- ### Do Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Executes a pre-constructed *http.Request with SSRF validation. This is the lowest-level method; all other HTTP methods use it internally. ```APIDOC ## Do(req *http.Request) (*http.Response, error) ### Description Executes a pre-constructed `*http.Request` with SSRF validation. This is the lowest-level method; all other HTTP methods use it internally. ### Method [HTTP method specified in the `req` object] ### Endpoint [URL specified in the `req` object] ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **req** (*http.Request) - Required - Pre-built request object from `http.NewRequest()` ### Request Example ```go import "net/http" req, _ := http.NewRequest("PATCH", "https://api.example.com/resource", body) req.Header.Set("X-Custom", "value") resp, err := client.Do(req) if err != nil { return } deffer resp.Body.Close() ``` ### Response #### Success Response (200) - **resp** (*http.Response) - The HTTP response object. #### Response Example [Response body depends on the server] ### Throws/Rejects Same error types as `Get()`. In test mode, also attaches DNS tracing via `httptrace.ClientTrace`. ``` -------------------------------- ### Build Final SafeURL Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Finalizes the configuration process and returns a `Config` object. This method should be called last, after all desired settings have been applied. It performs normalization, parsing, and validation of all configured values. ```go config := builder.Build() ``` ```go config := safeurl.GetConfigBuilder(). SetAllowedHosts("example.com"). SetAllowedPorts(443). SetAllowedSchemes("https"). Build() ``` -------------------------------- ### Enable Test Mode for DNS Mocking Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Enables test mode for DNS resolution, directing queries to a local mock server. This should only be used during testing and requires a test DNS server to be running. ```go builder := builder.EnableTestMode(true) ``` ```go builder.EnableTestMode(true) // Then run: go run testing/servers.go ``` -------------------------------- ### Perform a HEAD request with SafeURL client Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Initiate a HEAD request to a URL with SSRF protection. This method is useful for checking resource availability without downloading the body. It also enforces security policies. ```Go resp, err := client.Head(url) ``` ```Go resp, err := client.Head("https://example.com") if err != nil { return } deferr resp.Body.Close() if resp.StatusCode == 200 { fmt.Println("URL is reachable") } ``` -------------------------------- ### Production Secure SafeURL Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Sets up a secure production configuration with HTTPS, specific hosts/ports, a timeout, and disabled credential sending. Includes cookie jar integration. ```go jar, _ := cookiejar.New() config := safeurl.GetConfigBuilder(). SetAllowedSchemes("https"). SetAllowedHosts("api.production.com"). SetAllowedPorts(443). SetTimeout(30 * time.Second). SetCookieJar(jar). AllowSendingCredentials(false). EnableIPv6(false). EnableDebugLogging(false). Build() ``` -------------------------------- ### GetConfigBuilder Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/README.md Initiates the configuration building process, returning a configuration builder object. ```APIDOC ## GetConfigBuilder ### Description Starts the process of building a SafeURL configuration. ### Method `GetConfigBuilder()` ### Returns - ConfigBuilder: An object to configure the SafeURL client. ``` -------------------------------- ### Configure Blocked IPs Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Use `SetBlockedIPs` to block specific IP addresses. Invalid IP formats will cause a panic at `Build()` time. This takes precedence over allowed IPs. ```go builder.SetBlockedIPs("1.2.3.4", "5.6.7.8") ``` ```go builder.SetBlockedIPs("2001:db8::1") ``` ```go builder.SetBlockedIPs("1.2.3.4", "2001:db8::1") ``` -------------------------------- ### Enable IPv6 Support Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md If you are blocked from using IPv6 addresses, enable IPv6 support in the SafeURL configuration. ```go config := safeurl.GetConfigBuilder(). EnableIPv6(true). Build() ``` -------------------------------- ### Configure Allowed URL Schemes Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Use `SetAllowedSchemes` to specify which URL schemes are permitted. Passing an empty list blocks all schemes. Matching is case-insensitive. ```go builder.SetAllowedSchemes("https") ``` ```go builder.SetAllowedSchemes("http", "https") ``` ```go builder.SetAllowedSchemes("ws", "wss") ``` ```go builder.SetAllowedSchemes("http", "https", "ws", "wss") ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Activates debug logging to standard output, which includes details on validation decisions and connection attempts. Logs are prefixed with '[safeurl]'. ```go builder := builder.EnableDebugLogging(true) ``` ```go builder.EnableDebugLogging(true) // Output: [safeurl] calling proxied Get... // Output: [safeurl] connection to address: 93.184.216.34:443 ``` -------------------------------- ### Catch InvalidHostError Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Demonstrates how to catch an InvalidHostError when a hostname is empty or cannot be resolved. ```go resp, err := client.Get(url) if err != nil { if _, ok := err.(*safeurl.InvalidHostError); ok { fmt.Println("Invalid or empty hostname") } } ``` -------------------------------- ### Configure for Internal Service Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Use this configuration to allow access to internal services on the local network. It permits access to the '10.0.0.0/8' IP range on port 8080. ```go config := safeurl.GetConfigBuilder(). SetAllowedIPsCIDR("10.0.0.0/8"). SetAllowedPorts(8080). Build() ``` -------------------------------- ### SafeURL Configuration with IP Allowlist Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Enables IPv6 and allows specific IPv4 and IPv6 CIDR ranges. Use this to permit access to designated IP addresses. ```go config := safeurl.GetConfigBuilder(). SetAllowedIPsCIDR("93.184.216.0/24", "2606:2800::/32"). EnableIPv6(true). Build() ``` -------------------------------- ### Testing with Local DNS Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Enables test mode and configures allowed hosts for testing purposes. This is useful for integration tests with local services. ```go config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("service.test"). Build() client := safeurl.Client(config) // Run: go run testing/servers.go (in another terminal) ``` -------------------------------- ### Troubleshoot Host Not Found in Allowlist Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md If you encounter a 'host not found in allowlist' error, ensure the hostname is correctly added to your allowed hosts list. ```go config := safeurl.GetConfigBuilder(). SetAllowedHosts("correct-domain.com"). Build() ``` -------------------------------- ### Configure Allowed Ports Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Use `SetAllowedPorts` to specify which ports are allowed for connections. Invalid port values will cause a panic at `Build()` time. This applies to all schemes. ```go builder.SetAllowedPorts(443) ``` ```go builder.SetAllowedPorts(80, 443) ``` ```go builder.SetAllowedPorts(8080) ``` ```go builder.SetAllowedPorts(8000, 8001, 8002, 8003) ``` ```go builder.SetAllowedPorts(443, 8443) ``` -------------------------------- ### Handle Multiple SafeURL Error Types in Go Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Demonstrates how to use a type switch to differentiate and handle various SafeURL-specific errors returned by the client. This allows for targeted responses to different validation failures. ```go resp, err := client.Do(req) if err != nil { switch err.(type) { case *safeurl.AllowedHostError: fmt.Println("Host not allowed") case *safeurl.AllowedIPError: fmt.Println("IP not allowed") case *safeurl.AllowedPortError: fmt.Println("Port not allowed") case *safeurl.AllowedSchemeError: fmt.Println("Scheme not allowed") case *safeurl.IPv6BlockedError: fmt.Println("IPv6 disabled") case *safeurl.SendingCredentialsBlockedError: fmt.Println("Credentials blocked") case *safeurl.InvalidHostError: fmt.Println("Invalid hostname") default: fmt.Printf("Other error: %v\n", err) } } ``` -------------------------------- ### SafeURL Testing Configuration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Enables test mode and whitelists a specific host for testing purposes. This is useful for local development and integration tests. ```go config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("service.test"). Build() ``` -------------------------------- ### Development SafeURL Configuration with TLS Bypass Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Configures SafeURL for development environments, bypassing TLS verification and enabling debug logging and test mode. ```go config := safeurl.GetConfigBuilder(). SetTlsConfig(&tls.Config{InsecureSkipVerify: true}). EnableDebugLogging(true). EnableTestMode(true). Build() ``` -------------------------------- ### Enable IPv6 Connections Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Controls whether IPv6 connections are permitted. By default, IPv6 is disabled. ```go builder := builder.EnableIPv6(true) ``` ```go builder.EnableIPv6(true) // Allow IPv6 connections ``` -------------------------------- ### Error Unwrapping with SafeURL Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/utilities.md Demonstrates how to unwrap errors returned by the SafeURL client to inspect specific SafeURL error types, such as AllowedHostError. ```go func TestErrorWrapping(t *testing.T) { config := safeurl.GetConfigBuilder(). SetAllowedHosts("allowed.com"). Build() client := safeurl.Client(config) _, err := client.Get("https://notallowed.com") // Unwrap to get SafeURL error innerErr := unwrap(err) if _, ok := innerErr.(*safeurl.AllowedHostError); !ok { t.Errorf("Expected AllowedHostError, got %T", innerErr) } } ``` -------------------------------- ### Configure for CDN Integration Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md This configuration is designed for CDN integration, allowing connections to specific IP ranges used by CDNs. ```go config := safeurl.GetConfigBuilder(). SetAllowedIPsCIDR("151.101.0.0/16", "104.16.0.0/12"). Build() ``` -------------------------------- ### Custom TLS and Timeout Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Sets a custom TLS configuration and request timeout for the client. This allows for fine-tuning security and performance. ```go config := safeurl.GetConfigBuilder(). SetTlsConfig(&tls.Config{InsecureSkipVerify: true}). SetTimeout(10 * time.Second). Build() client := safeurl.Client(config) ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md Enable debug logging during development to understand SafeURL's validation behavior. ```go .EnableDebugLogging(true) ``` -------------------------------- ### Configure SafeURL for Testing with Local DNS Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/quick-start.md This configuration enables test mode and allows specifying custom hosts for local DNS resolution, which is useful for unit tests with controlled environments. Ensure the test server is running separately. ```go config := safeurl.GetConfigBuilder(). EnableTestMode(true). SetAllowedHosts("service.test"). Build() client := safeurl.Client(config) // In another terminal: go run testing/servers.go // Then run tests ``` -------------------------------- ### Set Allowed CIDR Ranges Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Configure specific IPv4 or IPv6 CIDR ranges that are permitted. IPs outside these ranges will be blocked. Configuration is validated at Build() time. ```go // Allow specific /24 subnet builder.SetAllowedIPsCIDR("93.184.216.0/24") ``` ```go // Allow AWS IP range builder.SetAllowedIPsCIDR("52.0.0.0/8") ``` ```go // Allow CDN provider ranges builder.SetAllowedIPsCIDR("151.101.0.0/16", "104.16.0.0/12") ``` ```go // Allow IPv6 range builder.SetAllowedIPsCIDR("2606:2800::/32") ``` ```go // Multiple ranges builder.SetAllowedIPsCIDR("10.0.0.0/8", "172.16.0.0/12") ``` -------------------------------- ### Post Method Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/client.md Performs a POST request with SSRF validation. ```APIDOC ## Post ### `Post(url string, contentType string, body io.Reader) (*http.Response, error)` Performs a POST request with SSRF validation. **Parameters**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | url | `string` | Yes | The target URL | | contentType | `string` | Yes | MIME type (e.g., `application/json`, `application/x-www-form-urlencoded`) | | body | `io.Reader` | Yes | Request body; can be `bytes.Buffer`, `strings.Reader`, or any `io.Reader` | **Returns**: `(*http.Response, error)` — Response object or error if validation or request fails. **Throws/Rejects**: Same error types as `Get()`. **Example**: ```go import ( "bytes" "encoding/json" ) data := map[string]string{"key": "value"} jsonData, _ := json.Marshal(data) resp, err := client.Post( "https://api.example.com/data", "application/json", bytes.NewReader(jsonData), ) if err != nil { return } defer resp.Body.Close() ``` ``` -------------------------------- ### Config Struct Definition Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/types.md Defines security policies and options for the SafeURL client. Used when creating a new client or building a configuration. ```go type Config struct { Timeout time.Duration CheckRedirect func(req *http.Request, via []*http.Request) error Jar http.CookieJar AllowedPorts []int AllowedSchemes []string AllowedHosts []string BlockedIPs []net.IP AllowedIPs []net.IP BlockedIPsCIDR []net.IPNet AllowedIPsCIDR []net.IPNet AllowSendingCredentials bool IsIPv6Enabled bool IsDebugLoggingEnabled bool InTestMode bool TlsConfig *tls.Config Transport *http.Transport } ``` -------------------------------- ### Custom Connection Limits Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Configure custom limits for HTTP connections, such as the maximum number of idle connections and their timeouts. This helps manage resource usage. ```go import "time" // Custom connection limits builder.SetTransport(&http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, IdleConnTimeout: 90 * time.Second, }) ``` -------------------------------- ### EnableIPv6 Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/api-reference/config-builder.md Enables or disables IPv6 connections. Default is false. ```APIDOC ## EnableIPv6(enable bool) *configBuilder ### Description Enables or disables IPv6 connections. Default is `false`. ### Parameters #### Path Parameters - **enable** (`bool`) - Required - `true` to allow IPv6, `false` to block ### Behavior - When `false`, connections to IPv6 addresses (including `[::1]`) are blocked - When `true`, IPv6 addresses are allowed (subject to other IP validation) ### Example ```go builder.EnableIPv6(true) // Allow IPv6 connections ``` ``` -------------------------------- ### Configure for Web Scraper Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/INDEX.md Use this configuration to scrape web pages from user input. It restricts allowed schemes to 'https' and ports to 443, and disallows sending credentials. ```go config := safeurl.GetConfigBuilder(). SetAllowedSchemes("https"). SetAllowedPorts(443). AllowSendingCredentials(false). SetTimeout(10 * time.Second). Build() ``` -------------------------------- ### Accept Self-Signed Certificates Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/configuration.md Configure TLS to accept self-signed certificates. This is intended for testing environments only and should not be used in production due to security risks. ```go import "crypto/tls" // Accept self-signed certificates (testing only!) builder.SetTlsConfig(&tls.Config{ InsecureSkipVerify: true, }) ``` -------------------------------- ### Catch AllowedIPError in Go Source: https://github.com/doyensec/safeurl/blob/main/_autodocs/errors.md Demonstrates how to catch an AllowedIPError, which occurs when a resolved IP address is not allowed due to allowlist/blocklist rules or being a private/reserved IP. This error is checked after hostname resolution. ```go // Attempting to connect to localhost (127.0.0.1) resp, err := client.Get("http://localhost") // Error: AllowedIPError (127.0.0.1 is private) // Attempting to connect to 192.168.1.1 resp, err := client.Get("http://192.168.1.1") // Error: AllowedIPError (192.168.1.1 is private) // Blocking a specific public IP config := safeurl.GetConfigBuilder(). SetBlockedIPs("93.184.216.34"). Build() resp, err := client.Get("https://example.com") // Error: AllowedIPError (93.184.216.34 is blocked) // Allowing only specific IPs config := safeurl.GetConfigBuilder(). SetAllowedIPs("93.184.216.34"). Build() resp, err := client.Get("https://other-example.com") // Error: AllowedIPError (IP not in allowlist) ``` ```go resp, err := client.Get("http://private.local") if err != nil { if _, ok := err.(*safeurl.AllowedIPError); ok { fmt.Println("IP not allowed") } } ```