larksuite/cli · error
emlbuilder: header name contains ':', CR, or LF: %q
Error message
emlbuilder: header name contains ':', CR, or LF: %q
What it means
validateHeaderName rejects header names containing ':', CR (\r), or LF (\n), which would break RFC 5322 field-name syntax and could enable header injection. It is enforced when Header() is called so a malformed name never reaches the serialized message. Wrapped into a typed ValidationError by the mail command layer.
Source
Thrown at shortcuts/mail/emlbuilder/builder.go:172
case r >= 0x200B && r <= 0x200D: // zero-width space/non-joiner/joiner
return true
case r == 0xFEFF: // BOM / zero-width no-break space
return true
case r >= 0x202A && r <= 0x202E: // Bidi: LRE/RLE/PDF/LRO/RLO
return true
case r >= 0x2028 && r <= 0x2029: // line/paragraph separator
return true
case r >= 0x2066 && r <= 0x2069: // Bidi isolates: LRI/RLI/FSI/PDI
return true
}
return false
}
// validateHeaderName rejects any string that contains ':', CR (\r), LF (\n),
// or non-printable ASCII characters, as required by RFC 5322 field-name syntax.
func validateHeaderName(n string) error {
if strings.ContainsAny(n, ":\r\n") {
return fmt.Errorf("emlbuilder: header name contains ':', CR, or LF: %q", n) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.
}
for _, r := range n {
if r < 0x21 || r > 0x7e {
return fmt.Errorf("emlbuilder: header name contains non-printable character: %q", n) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.
}
}
return nil
}
// validateDisplayName rejects display names containing CR or LF, which could
// escape the quoted-string encoding used by mail.Address.String() and inject headers.
func validateDisplayName(name string) error {
if strings.ContainsAny(name, "\r\n") {
return fmt.Errorf("emlbuilder: display name contains CR or LF: %q", name) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.
}
return nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Remove ':' / CR / LF from the header name; pass only the bare field name to Header().
- Split any 'Name: value' string at the first ':' and pass the two halves as separate arguments.
- Trim/normalize the name with strings.TrimSpace and validate it is printable ASCII before calling Header().
Example fix
// before
b.Header("X-Custom: " + value, value)
// after
b.Header("X-Custom", value) Defensive patterns
Strategy: validation
Validate before calling
func safeHeaderName(n string) bool {
if strings.ContainsAny(n, ":\r\n") { return false }
for _, r := range n {
if r < 0x21 || r > 0x7e { return false }
}
return len(n) > 0
}
// check before b.Header(name, value) Try / catch
if err := b.Header(name, value); err != nil {
var verr *ValidationError
if errors.As(err, &verr) { /* surface to caller with the offending name */ }
return err
} Prevention
- Pass bare field names to Header(); never pre-concatenate 'Name: value' strings.
- Keep a constant list of allowed custom header names instead of accepting arbitrary input.
- Trim whitespace from names read from config before use.
When it happens
Trigger: Calling Builder.Header with a name string containing ':', '\r', or '\n' — e.g. Header("X-Foo: injected", ...) or a name built from user input that includes a newline.
Common situations: Concatenating 'name: value' into one string and passing it as the name; user-controlled header names from a web form; CRLF accidentally included when reading names from config files or CSV.
Related errors
- emlbuilder: header value contains dangerous Unicode characte
- emlbuilder: header name contains non-printable character: %q
- emlbuilder: display name contains CR or LF: %q
- set_subject: value must not contain CR or LF
- set_header: header name must not contain ':', CR, or LF
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/dedaefac67ca1aaa.
Report an issue: GitHub.