{"record":{"id":"dedaefac67ca1aaa","repo":"larksuite/cli","slug":"emlbuilder-header-name-contains-cr-or-lf","errorCode":null,"errorMessage":"emlbuilder: header name contains ':', CR, or LF: %q","messagePattern":"emlbuilder: header name contains ':', CR, or LF: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/emlbuilder/builder.go","lineNumber":172,"sourceCode":"\tcase r >= 0x200B && r <= 0x200D: // zero-width space/non-joiner/joiner\n\t\treturn true\n\tcase r == 0xFEFF: // BOM / zero-width no-break space\n\t\treturn true\n\tcase r >= 0x202A && r <= 0x202E: // Bidi: LRE/RLE/PDF/LRO/RLO\n\t\treturn true\n\tcase r >= 0x2028 && r <= 0x2029: // line/paragraph separator\n\t\treturn true\n\tcase r >= 0x2066 && r <= 0x2069: // Bidi isolates: LRI/RLI/FSI/PDI\n\t\treturn true\n\t}\n\treturn false\n}\n\n// validateHeaderName rejects any string that contains ':', CR (\\r), LF (\\n),\n// or non-printable ASCII characters, as required by RFC 5322 field-name syntax.\nfunc validateHeaderName(n string) error {\n\tif strings.ContainsAny(n, \":\\r\\n\") {\n\t\treturn fmt.Errorf(\"emlbuilder: header name contains ':', CR, or LF: %q\", n) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.\n\t}\n\tfor _, r := range n {\n\t\tif r < 0x21 || r > 0x7e {\n\t\t\treturn fmt.Errorf(\"emlbuilder: header name contains non-printable character: %q\", n) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.\n\t\t}\n\t}\n\treturn nil\n}\n\n// validateDisplayName rejects display names containing CR or LF, which could\n// escape the quoted-string encoding used by mail.Address.String() and inject headers.\nfunc validateDisplayName(name string) error {\n\tif strings.ContainsAny(name, \"\\r\\n\") {\n\t\treturn fmt.Errorf(\"emlbuilder: display name contains CR or LF: %q\", name) //nolint:forbidigo // intermediate EML builder error; mail command layer wraps into typed ValidationError.\n\t}\n\treturn nil\n}\n","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/emlbuilder/builder.go#L154-L190","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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()."],"exampleFix":"// before\nb.Header(\"X-Custom: \" + value, value)\n// after\nb.Header(\"X-Custom\", value)","handlingStrategy":"validation","validationCode":"func safeHeaderName(n string) bool {\n    if strings.ContainsAny(n, \":\\r\\n\") { return false }\n    for _, r := range n {\n        if r < 0x21 || r > 0x7e { return false }\n    }\n    return len(n) > 0\n}\n// check before b.Header(name, value)","typeGuard":null,"tryCatchPattern":"if err := b.Header(name, value); err != nil {\n    var verr *ValidationError\n    if errors.As(err, &verr) { /* surface to caller with the offending name */ }\n    return err\n}","preventionTips":["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."],"tags":["email","header-validation","header-injection","eml"],"backgroundTag":"header-injection-crlf","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}