{"record":{"id":"ba6c20e9aa5469a1","repo":"shadow1ng/fscan","slug":"imap-credential-contains-line-break","errorCode":null,"errorMessage":"imap credential contains line break","messagePattern":"imap credential contains line break","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/text_protocol.go","lineNumber":26,"sourceCode":"\t\"strings\"\n)\n\nfunc hasLineBreak(s string) bool {\n\treturn strings.ContainsAny(s, \"\\r\\n\")\n}\n\nfunc rejectLineBreaks(values ...string) error {\n\tfor _, value := range values {\n\t\tif hasLineBreak(value) {\n\t\t\treturn fmt.Errorf(\"credential contains line break\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc imapQuotedString(s string) (string, error) {\n\tif hasLineBreak(s) {\n\t\treturn \"\", fmt.Errorf(\"imap credential contains line break\")\n\t}\n\treturn strconv.Quote(s), nil\n}\n\nfunc buildIMAPLoginCommand(tag, username, password string) (string, error) {\n\tquotedUser, err := imapQuotedString(username)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tquotedPass, err := imapQuotedString(password)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn fmt.Sprintf(\"%s LOGIN %s %s\\r\\n\", tag, quotedUser, quotedPass), nil\n}\n\nfunc buildRedisAuthCommand(password string) []byte {\n\treturn buildRedisCommand(\"AUTH\", password)","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/text_protocol.go#L8-L44","documentation":"imapQuotedString refuses to IMAP-quote a value containing CR/LF, returning 'imap credential contains line break'. Like the sibling rejectLineBreaks guard, this prevents IMAP command injection via literal line breaks inside a quoted string of the LOGIN command built by buildIMAPLoginCommand.","triggerScenarios":"Calling buildIMAPLoginCommand (hence imapQuotedString) with a username or password containing '\\r' or '\\n'.","commonSituations":"Credentials sourced from files/configs with trailing newlines; user-supplied input not sanitized; fuzzing or adversarial target lists designed to inject IMAP commands.","solutions":["Sanitize/trim the username and password before building the LOGIN command.","Validate credentials when they are loaded and fail early with a clear config error.","Fix the credential source to not embed newlines (e.g. scanner.Text() instead of raw reads).","Retain the guard; it is the correct security behavior."],"exampleFix":"// before\nuser := string(b) // may contain \\n\n_ = user\n// after\nuser := strings.TrimSpace(string(b))\nif strings.ContainsAny(user, \"\\r\\n\") {\n    return fmt.Errorf(\"imap credential contains line break\")\n}","handlingStrategy":"validation","validationCode":"if strings.ContainsAny(username, \"\\r\\n\") || strings.ContainsAny(password, \"\\r\\n\") {\n    return errors.New(\"imap credential contains line break\")\n}","typeGuard":"func imapSafe(s string) bool { return !strings.ContainsAny(s, \"\\r\\n\") }","tryCatchPattern":null,"preventionTips":["Sanitize username/password before building IMAP commands","Use line-aware readers so trailing newlines are stripped","Reject multiline credentials at config load","Preserve the quoting/injection guard for all IMAP inputs"],"tags":["imap","injection","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}