{"record":{"id":"f569a1de501d1102","repo":"micro/go-micro","slug":"invalid-push-callback-url-w","errorCode":null,"errorMessage":"invalid push callback url: %w","messagePattern":"invalid push callback url: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gateway/a2a/pushsecurity.go","lineNumber":114,"sourceCode":"// pushGuardClient is the HTTP client used for default-policy push delivery. Its\n// dialer refuses connections to blocked addresses at connect time.\nvar pushGuardClient = &http.Client{\n\tTimeout: 10 * time.Second,\n\tTransport: &http.Transport{\n\t\tProxy: http.ProxyFromEnvironment,\n\t\tDialContext: (&net.Dialer{\n\t\t\tTimeout: 5 * time.Second,\n\t\t\tControl: pushDialControl,\n\t\t}).DialContext,\n\t},\n}\n\n// checkPushURL validates a callback URL against the dispatcher's effective\n// policy (Options.AllowPushURL, or the default SSRF-safe policy).\nfunc (d *dispatcher) checkPushURL(raw string) error {\n\tu, err := url.Parse(raw)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid push callback url: %w\", err)\n\t}\n\tpolicy := d.allowPushURL\n\tif policy == nil {\n\t\tpolicy = defaultPushURLPolicy\n\t}\n\treturn policy(u)\n}\n\n// pushClient is the HTTP client deliverPush uses: the guarded client under the\n// default policy, or the default client when an operator has taken over the\n// policy via Options.AllowPushURL (they own the trust decision then).\nfunc (d *dispatcher) pushClient() *http.Client {\n\tif d.guardPushDial {\n\t\treturn pushGuardClient\n\t}\n\treturn http.DefaultClient\n}\n","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/gateway/a2a/pushsecurity.go#L96-L132","documentation":"checkPushURL parses the raw callback URL and then runs it through the dispatcher's effective policy: the user-supplied Options.AllowPushURL if set, otherwise the default SSRF-safe policy. If url.Parse fails (malformed URL) this wrapped error is returned. All push registrations and deliveries pass through this check.","triggerScenarios":"Calling setPushConfig or triggering deliverPush with a callback URL string that url.Parse cannot parse, e.g. containing control characters, 'http://%zz', or other malformed syntax.","commonSituations":"Typo or unencoded characters in the callback URL; environment-variable substitution producing a broken URL; concatenating host and path without a separator.","solutions":["Fix the callback URL so it is valid RFC 3986 syntax (scheme://host/path).","URL-encode any special characters (spaces, %, control chars) before passing the URL.","Log/inspect the underlying error (%w) to identify the exact parse failure before retrying."],"exampleFix":"// before\nsetPushConfig(task, \"http://host with space/cb\")\n// after\nsetPushConfig(task, \"http://host-without-space/cb\") // or url.QueryEscape dynamic parts","handlingStrategy":"validation","validationCode":"if _, err := url.Parse(callbackURL); err != nil {\n    return fmt.Errorf(\"invalid callback URL before registration: %w\", err)\n}","typeGuard":"func isValidURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && u.Scheme != \"\" && u.Host != \"\"\n}","tryCatchPattern":"err := d.CheckPushURL(raw)\nvar urlErr *url.Error\nif errors.As(err, &urlErr) {\n    log.Printf(\"push callback URL malformed: %v\", urlErr)\n}","preventionTips":["Validate callback URLs with url.Parse at configuration time, not delivery time.","Escape dynamic URL segments before composing the final string.","Avoid building URLs by raw string concatenation."],"tags":["url-validation","push-callback","parse-error"],"backgroundTag":"invalid-url-parse","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}