{"record":{"id":"f835ec2b32642ea4","repo":"projectdiscovery/nuclei","slug":"http-stopped-after-d-redirects","errorCode":null,"errorMessage":"http: stopped after %d redirects","messagePattern":"http: stopped after (.+?) redirects","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/http/http.go","lineNumber":315,"sourceCode":"\t\tResponseHeaderTimeout: time.Duration(c.TimeoutSeconds) * time.Second,\n\t}\n\n\thttpClient := &http.Client{\n\t\tTransport: transport,\n\t\tTimeout:   time.Duration(c.TimeoutSeconds) * time.Second,\n\t}\n\tif c.jar != nil {\n\t\thttpClient.Jar = c.jar\n\t}\n\tif !c.FollowRedirects {\n\t\thttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {\n\t\t\treturn http.ErrUseLastResponse\n\t\t}\n\t} else {\n\t\tmax := c.MaxRedirects\n\t\thttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {\n\t\t\tif len(via) >= max {\n\t\t\t\treturn fmt.Errorf(\"http: stopped after %d redirects\", max)\n\t\t\t}\n\t\t\tif nextHost := req.URL.Hostname(); nextHost != \"\" && !protocolstate.IsHostAllowed(executionID, nextHost) {\n\t\t\t\treturn protocolstate.ErrHostDenied.Msgf(nextHost)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tvar bodyReader io.Reader\n\tif body != \"\" && method != http.MethodHead && method != http.MethodGet {\n\t\tbodyReader = strings.NewReader(body)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, method, parsed.String(), bodyReader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor k, vals := range c.headers {","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/http/http.go#L297-L333","documentation":"FollowRedirects is on (the Client default) and the redirect chain exceeded MaxRedirects (default 10), so the CheckRedirect hook aborts. Every hop is also re-checked against host policy, so this cap bounds both redirect loops and policy-evading chains. The error is raised by net/http's redirect machinery and surfaces from Get/Post/Request.","triggerScenarios":"Auth flows bouncing between /login, /auth, and an IdP more than 10 times; CDN/geo chains (http->https->host->www) forming a cycle; Options.MaxRedirects set lower than the chain depth of the target.","commonSituations":"SAML/OAuth-protected targets with deep redirect chains; marketing/geo redirects looping between regions; templates using the default client where the first request legitimately hops more than 10 times.","solutions":["Raise the cap: const o = new http.Options(); o.MaxRedirects = 25; const c = new http.Client(o);","Disable following and walk Location yourself: o.DisableRedirects = true, then read resp.GetHeader('Location') per hop","Probe the final URL directly when it is predictable, skipping the chain"],"exampleFix":"// before: default cap of 10, deep auth chain\nconst client = new http.Client();\nconst resp = client.Get('https://acme.com/'); // -> stopped after 10 redirects\n\n// after: raise the cap for targets known to hop a lot\nconst o = new http.Options();\no.MaxRedirects = 25;\nconst client = new http.Client(o);\nconst resp = client.Get('https://acme.com/');","handlingStrategy":"fallback","validationCode":"const o = new http.Options();\no.MaxRedirects = 25; // set above the known chain depth for auth-heavy targets\nconst client = new http.Client(o);","typeGuard":null,"tryCatchPattern":"let resp;\ntry {\n  resp = client.Get(url);\n} catch (e) {\n  if (/stopped after \\d+ redirects/.test(e.message || '')) {\n    const o = new http.Options();\n    o.DisableRedirects = true;\n    const first = new http.Client(o).Get(url); // stop following; walk Location headers manually\n  }\n}","preventionTips":["Set MaxRedirects per target class instead of relying on the default 10","Use DisableRedirects when only the first hop matters","Probe the final URL directly when the redirect target is predictable"],"tags":["http","redirects","javascript","configuration"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}