All vulnerabilities
GHSA-whx4-hxwq-qgjh

github.com/getfider/fider: SSRF via DNS Rebinding in Webhook and Custom OAuth Provider URL Validation

github.com/getfider/fider
CVSS
7.1High
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in0.38.0Fixed versionGitHub
Published28 Sep 2026Updated 1 Oct 2026GitHub

What fixes it

  • 0.38.0github.com/getfider/fider, goGitHubgo get github.com/getfider/fider@v0.38.0

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

Fider validates admin-supplied webhook URLs and custom OAuth provider profile/token URLs by resolving the hostname and checking that the resolved IP is not private/internal (validate.WebhookURL). This validation happens as a separate DNS lookup from the actual outgoing HTTP request made later (when the webhook fires, or when the OAuth profile is fetched during login), which performs its own independent DNS resolution via the shared http.DefaultClient. An attacker who controls DNS for the domain used in the webhook/OAuth URL can answer the validation lookup with a public IP and the connection lookup with a private/internal one (DNS rebinding), completely bypassing the intended SSRF protection.

Affected versions: confirmed against the current default branch as of 2026-09-16.

Details

app/pkg/validate/general.go's WebhookURL:

func WebhookURL(rawurl string) []string {
    ...
    addrs, err := net.LookupHost(hostname)
    ...
    for _, addr := range addrs {
        if ip := net.ParseIP(addr); ip != nil && isBlockedIP(ip) {
            return []string{"This URL is not allowed because it targets a private or internal network address."}
        }
    }
    return []string{}
}

Called at webhook creation time and webhook trigger time (services/webhook/webhook.go), and for custom OAuth provider TokenURL/ProfileURL (services/oauth/oauth.go).

The actual outgoing request goes through app/services/httpclient/httpclient.go's requestHandler, which (before the fix) always used the process-wide http.DefaultClient with no further IP validation:

res, err := http.DefaultClient.Do(req)

http.DefaultClient's transport resolves the hostname itself when it dials the TCP connection, independently of validate.WebhookURL's earlier lookup. An attacker-controlled authoritative DNS server with a low TTL can return a public IP for the validation query and a private/internal IP (e.g. 169.254.169.254, 127.0.0.1, an internal service) for the connection query moments later.

PoC

server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("internal-response-should-never-be-seen"))
}))
defer server.Close()

req, _ := http.NewRequest("GET", server.URL, nil) // resolves to 127.0.0.1
res, err := http.DefaultClient.Do(req)
// err == nil, res.StatusCode == 200: connection to a loopback address succeeds,
// regardless of any earlier, separate validation of the same hostname

I validated the fix with two Go tests exercising the real requestHandler function directly:

  • With the new BlockPrivateNetworkTargets flag unset (matching every other current caller): request to a loopback target succeeds (documents the vulnerable behavior).
  • With the flag set (as the fix now sets on the webhook trigger and OAuth-profile-fetch call sites): the identical request is blocked, since the fix re-validates the exact IP at the moment of dialing rather than relying on an earlier separate lookup.

All pre-existing validate/httpclient tests pass, and go build ./... succeeds project-wide, confirming no regression to the other unrelated callers of cmd.HTTPRequest (userlist sync, Mailgun, Gravatar, OAuth token exchange).

Impact

An account with permission to create webhooks or configure a custom OAuth provider (administrator role) can cause the Fider server to make outbound HTTP requests to arbitrary internal network addresses via DNS rebinding, bypassing the application's own explicit SSRF protection. In cloud deployments this can reach the instance metadata service (potentially exposing IAM credentials) or other internal services not otherwise exposed to that admin's trust level.

Suggested fix

Re-validate the exact IP address at the moment the connection is dialed, using a custom Transport.DialContext that performs its own resolution and IP check immediately before connecting, so no separate earlier lookup's result can be stale. I have a working patch (adds an opt-in BlockPrivateNetworkTargets field to cmd.HTTPRequest, set only on the webhook-trigger and OAuth-profile-fetch call sites, respecting the existing AllowPrivateNetworkTargets escape hatch) and regression tests, happy to open a PR against a private fork if useful.

Text from GitHub Advisory Database

Affected versions 1

  • github.com/getfider/fider, go<= 0.37.0GitHub