{"record":{"id":"026f3fc764460e55","repo":"projectdiscovery/nuclei","slug":"http-invalid-url-w","errorCode":null,"errorMessage":"http: invalid url: %w","messagePattern":"http: invalid url: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/http/http.go","lineNumber":259,"sourceCode":"\t\tFollowRedirects: true,\n\t\tMaxRedirects:    defaultMaxRedirects,\n\t\tTimeoutSeconds:  defaultTimeoutSeconds,\n\t\tMaxBodyBytes:    defaultMaxBodyBytes,\n\t\theaders:         make(http.Header),\n\t}\n}\n\nfunc (c *Client) do(ctx context.Context, method, rawURL, body string) (*Response, error) {\n\tc.init()\n\n\texecutionID := executionIDFrom(ctx, c)\n\tif executionID == \"\" {\n\t\treturn nil, fmt.Errorf(\"http: executionId not set\")\n\t}\n\n\tparsed, err := url.Parse(rawURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http: invalid url: %w\", err)\n\t}\n\tif parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn nil, fmt.Errorf(\"http: url must include scheme and host\")\n\t}\n\n\thost := parsed.Hostname()\n\tif !protocolstate.IsHostAllowed(executionID, host) {\n\t\treturn nil, protocolstate.ErrHostDenied.Msgf(host)\n\t}\n\n\tdialers := protocolstate.GetDialersWithId(executionID)\n\tif dialers == nil {\n\t\treturn nil, fmt.Errorf(\"dialers not initialized for %s\", executionID)\n\t}\n\n\ttlsConfig := &tls.Config{\n\t\tInsecureSkipVerify: true,\n\t\tMinVersion:         tls.VersionTLS10,","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/http/http.go#L241-L277","documentation":"url.Parse rejected the raw URL string: Go's parser fails on control characters, raw spaces in some positions, invalid percent-escapes, or other malformed input. The nuclei/http client requires a well-formed absolute URL before host policy can be evaluated, so it aborts with the parser's error wrapped.","triggerScenarios":"URL containing raw spaces or control characters ('https://ex.com/a b'); broken percent-encoding ('https://ex.com/%zz'); passing a base64 blob, file path, or host:port string instead of a URL; trailing newline from a variables file.","commonSituations":"Interpolating extractor output into a URL without encoding; copy-pasting URLs with invisible characters; concatenating template variables that inject whitespace or line breaks.","solutions":["Encode interpolated path/query parts with encodeURIComponent before building the URL","Trim whitespace/newlines from every variable used in a URL","Validate the URL shape with a regex before calling Get/Post/Request"],"exampleFix":"// before: raw extractor output with spaces\nconst resp = client.Get('https://example.com/' + extracted);\n\n// after: trim and encode the interpolated part\nconst resp = client.Get('https://example.com/' + encodeURIComponent(extracted.trim()));","handlingStrategy":"validation","validationCode":"const u = String(rawUrl || '').trim();\nif (/[\\x00-\\x1f]/.test(u) || /%(?![0-9a-fA-F]{2})/.test(u)) {\n  throw new Error('URL contains control chars or broken percent-encoding');\n}\nconst resp = client.Get(u);","typeGuard":"const isParseableUrl = (u) => { const s = String(u || '').trim(); return s.length > 0 && !/[\\x00-\\x1f\\s]/.test(s) && !/%(?![0-9a-fA-F]{2})/.test(s); };","tryCatchPattern":"try { const resp = client.Get(u); }\ncatch (e) { if (/http: invalid url/.test(e.message || '')) { /* trim + encode parts, rebuild the URL */ } }","preventionTips":["Trim every variable before splicing it into a URL","encodeURIComponent any interpolated path/query segment","Never pass raw base64 blobs or file paths as URLs"],"tags":["http","url","validation","javascript"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}