shadow1ng/fscan · error

imap credential contains line break

Error message

imap credential contains line break

What it means

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.

Source

Thrown at plugins/services/text_protocol.go:26

	"strings"
)

func hasLineBreak(s string) bool {
	return strings.ContainsAny(s, "\r\n")
}

func rejectLineBreaks(values ...string) error {
	for _, value := range values {
		if hasLineBreak(value) {
			return fmt.Errorf("credential contains line break")
		}
	}
	return nil
}

func imapQuotedString(s string) (string, error) {
	if hasLineBreak(s) {
		return "", fmt.Errorf("imap credential contains line break")
	}
	return strconv.Quote(s), nil
}

func buildIMAPLoginCommand(tag, username, password string) (string, error) {
	quotedUser, err := imapQuotedString(username)
	if err != nil {
		return "", err
	}
	quotedPass, err := imapQuotedString(password)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s LOGIN %s %s\r\n", tag, quotedUser, quotedPass), nil
}

func buildRedisAuthCommand(password string) []byte {
	return buildRedisCommand("AUTH", password)

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Sanitize/trim the username and password before building the LOGIN command.
  2. Validate credentials when they are loaded and fail early with a clear config error.
  3. Fix the credential source to not embed newlines (e.g. scanner.Text() instead of raw reads).
  4. Retain the guard; it is the correct security behavior.

Example fix

// before
user := string(b) // may contain \n
_ = user
// after
user := strings.TrimSpace(string(b))
if strings.ContainsAny(user, "\r\n") {
    return fmt.Errorf("imap credential contains line break")
}
Defensive patterns

Strategy: validation

Validate before calling

if strings.ContainsAny(username, "\r\n") || strings.ContainsAny(password, "\r\n") {
    return errors.New("imap credential contains line break")
}

Type guard

func imapSafe(s string) bool { return !strings.ContainsAny(s, "\r\n") }

Prevention

When it happens

Trigger: Calling buildIMAPLoginCommand (hence imapQuotedString) with a username or password containing '\r' or '\n'.

Common situations: Credentials sourced from files/configs with trailing newlines; user-supplied input not sanitized; fuzzing or adversarial target lists designed to inject IMAP commands.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/ba6c20e9aa5469a1. Report an issue: GitHub.