{"record":{"id":"f8dcef6afc26d10c","repo":"juanfont/headscale","slug":"s-confirm-form-unterminated-input-tag","errorCode":null,"errorMessage":"%s confirm form: unterminated input tag","messagePattern":"(.+?) confirm form: unterminated input tag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/scenario.go","lineNumber":1282,"sourceCode":"\t}\n\n\tformAction := htmlBody[actionStart : actionStart+actionEnd]\n\n\t// Extract hidden CSRF input value. The rendered <input> has\n\t// attributes in name-type-value order so we grab the whole tag.\n\tbefore, _, ok := strings.Cut(htmlBody, `name=\"headscale_register_confirm\"`)\n\tif !ok {\n\t\treturn \"\", nil, fmt.Errorf(\"%s confirm form: no CSRF input\", hostname) //nolint:err113\n\t}\n\n\ttagStart := strings.LastIndex(before, \"<input\")\n\tif tagStart == -1 {\n\t\treturn \"\", nil, fmt.Errorf(\"%s confirm form: no input tag for CSRF\", hostname) //nolint:err113\n\t}\n\n\ttagEnd := strings.Index(htmlBody[tagStart:], \">\")\n\tif tagEnd == -1 {\n\t\treturn \"\", nil, fmt.Errorf(\"%s confirm form: unterminated input tag\", hostname) //nolint:err113\n\t}\n\n\tinputTag := htmlBody[tagStart : tagStart+tagEnd+1]\n\n\tvalIdx := strings.Index(inputTag, `value=\"`)\n\tif valIdx == -1 {\n\t\treturn \"\", nil, fmt.Errorf(\"%s confirm form: no value in CSRF input\", hostname) //nolint:err113\n\t}\n\n\tvalStart := valIdx + len(`value=\"`)\n\tvalEnd := strings.Index(inputTag[valStart:], `\"`)\n\tcsrfToken := inputTag[valStart : valStart+valEnd]\n\n\t// Build the absolute POST URL from the response's request URL.\n\tbase := prevResp.Request.URL\n\tconfirmURL := &url.URL{\n\t\tScheme: base.Scheme,\n\t\tHost:   base.Host,","sourceCodeStart":1264,"sourceCodeEnd":1300,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/scenario.go#L1264-L1300","documentation":"After locating the `<input` tag for the CSRF field, the parser could not find a closing `>` in the remainder of the document (`strings.Index(htmlBody[tagStart:], \">\")` returned -1). The tag is never terminated, so its attributes cannot be sliced out safely.","triggerScenarios":"The document ends (or is truncated) between `<input` and its closing angle bracket — truncated response body, connection cut mid-body, or a template that emits a malformed input tag.","commonSituations":"Proxy or test harness truncates the HTML body; template file corrupted or partially written; the page is streamed and read before completion.","solutions":["Dump `htmlBody` length and tail when the error fires to confirm truncation.","Retry the GET of the confirm page; transient truncation in containerized tests is usually network flake.","If reproducible, fix the template that renders the unterminated input tag."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check Content-Length vs actual bytes read to detect truncated bodies early.","Retry the GET once on truncation — usually a flaky container network.","Fix malformed templates at the source rather than loosening the parser."],"tags":["html-parsing","integration","csrf"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}