Skip to content

runtimevar/httpvar: SSRF via unvalidated URL — no private IP range blocking #3668

@Ryujiyasu

Description

@Ryujiyasu

Summary

The runtimevar/httpvar package makes periodic HTTP GET requests to a user-supplied URL using http.DefaultClient with no validation of the target host, IP range, or scheme. Any application or user that passes an attacker-controlled URL to httpvar.OpenVariable can trigger SSRF to internal services including cloud metadata endpoints.

Vulnerable Code

File: runtimevar/httpvar/httpvar.go:131-138

func OpenVariable(client *http.Client, urlStr string, decoder *runtimevar.Decoder, opts *Options) (*runtimevar.Variable, error) {
    endpointURL, err := url.Parse(urlStr)
    // ← No check: isPrivateIP(), no metadata endpoint blocklist, no scheme restriction
    return runtimevar.New(newWatcher(client, endpointURL, decoder, opts)), nil
}

File: runtimevar/httpvar/httpvar.go:216-226

func (w *watcher) WatchVariable(ctx context.Context, _ driver.State) (driver.State, time.Duration) {
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, w.endpoint.String(), nil)
    resp, err := w.client.Do(req)  // ← follows redirects, no SSRF protection
    b, err := io.ReadAll(resp.Body)  // ← response body returned as variable value

Attack Scenario

gocdk-runtimevar cat "http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-role"

Suggested Fix

Add URL validation in OpenVariable() to reject private IP ranges, cloud metadata endpoints, and loopback addresses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions