juanfont/headscale · error
%s confirm form: no value in CSRF input
Error message
%s confirm form: no value in CSRF input
What it means
The CSRF `<input>` tag was captured whole, but it contains no `value="` attribute, so there is no token to submit with the confirm POST. The template is expected to render attributes in name-type-value order; a missing value means the form was rendered without a token.
Source
Thrown at integration/scenario.go:1289
if !ok {
return "", nil, fmt.Errorf("%s confirm form: no CSRF input", hostname) //nolint:err113
}
tagStart := strings.LastIndex(before, "<input")
if tagStart == -1 {
return "", nil, fmt.Errorf("%s confirm form: no input tag for CSRF", hostname) //nolint:err113
}
tagEnd := strings.Index(htmlBody[tagStart:], ">")
if tagEnd == -1 {
return "", nil, fmt.Errorf("%s confirm form: unterminated input tag", hostname) //nolint:err113
}
inputTag := htmlBody[tagStart : tagStart+tagEnd+1]
valIdx := strings.Index(inputTag, `value="`)
if valIdx == -1 {
return "", nil, fmt.Errorf("%s confirm form: no value in CSRF input", hostname) //nolint:err113
}
valStart := valIdx + len(`value="`)
valEnd := strings.Index(inputTag[valStart:], `"`)
csrfToken := inputTag[valStart : valStart+valEnd]
// Build the absolute POST URL from the response's request URL.
base := prevResp.Request.URL
confirmURL := &url.URL{
Scheme: base.Scheme,
Host: base.Host,
Path: formAction,
}
log.Printf("%s auto-submitting confirm form: %s", hostname, confirmURL)
formData := url.Values{
"headscale_register_confirm": {csrfToken},View on GitHub (pinned to 565fd254d0)
Solutions
- Print the captured `inputTag` to see exactly how the value attribute is rendered.
- Align the parser with the template's current attribute order/quoting.
- Use x/net/html to read form values robustly instead of substring matching.
Defensive patterns
Strategy: validation
Prevention
- Log the captured input tag whenever extraction fails.
- Handle both quote styles (`value=\"` and `value='`) if you keep scraping.
- Use html.Parse + form traversal to read values regardless of attribute order.
When it happens
Trigger: `strings.Index(inputTag, "value=\"")` returns -1 on the captured tag. Occurs when the hidden input is rendered with `value=''`, no value at all, or a differently ordered/quoted attribute so the slice from `<input` to `>` missed it.
Common situations: Template change altering attribute order or quoting (e.g. value='...' with single quotes); server renders an empty token because the registration session expired; HTML attribute escaping mangles the value attribute.
Related errors
- %s confirm form: no CSRF input
- %s confirm form: no input tag for CSRF
- %s confirm form: unterminated input tag
- tag should be lowercase
- %s confirm form: unterminated action attribute
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/264992248cb5cf4d.
Report an issue: GitHub.