Skip to content

fix(email): strip CR/LF in imap_quote to prevent IMAP command injection#135

Closed
guanlan wants to merge 1 commit into
mainfrom
fix/imap-command-injection
Closed

fix(email): strip CR/LF in imap_quote to prevent IMAP command injection#135
guanlan wants to merge 1 commit into
mainfrom
fix/imap-command-injection

Conversation

@guanlan

@guanlan guanlan commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

imap_quote() was escaping backslashes and double-quotes but not stripping carriage returns or newlines. RFC 3501 forbids CR and LF inside IMAP quoted strings, and their presence allows an attacker to inject arbitrary IMAP commands via user-controlled input (e.g. the from_contains or subject_contains search parameters).

Example attack vector

from_contains = "x\r\nA001 STORE 1 +FLAGS (\\Deleted)"

This would cause imap_quote to produce a string that, when embedded in a UID SEARCH command, sends an extra STORE command to the IMAP server.

Fix

Sanitize the input in imap_quote by removing \r and \n before escaping:

fn imap_quote(value: &str) -> String {
    let sanitized = value.replace('\r', "").replace('\n', "");
    let escaped = sanitized.replace('\\', "\\\\").replace('"', "\\\"");
    format!("\"{escaped}\"")
}

Tests

Two new unit tests added:

  • test_imap_quote_strips_crlf_injection — verifies CR and LF are removed from quoted output
  • test_imap_quote_escapes_backslash_and_quote — verifies existing escape logic is unaffected

All 347 tests pass.


View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

RFC 3501 prohibits CR and LF inside IMAP quoted strings.
Previously, user-controlled inputs (from_contains, subject_contains,
login credentials) were passed through imap_quote() without removing
newline characters, allowing an attacker to inject arbitrary IMAP
commands by embedding \r\n in those fields.

Fix: sanitize the input by stripping \r and \n before escaping and
quoting.

Add two unit tests:
- test_imap_quote_strips_crlf_injection: verifies newlines are removed
- test_imap_quote_escapes_backslash_and_quote: verifies existing escape
  behaviour is preserved

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

RFC 3501 also prohibits NUL bytes (%x00) in quoted strings. While NUL cannot inject IMAP commands (unlike CR/LF), it could cause truncation in servers that use C-style string handling. Consider adding null-byte stripping in a follow-up if this fits your threat model.

TL;DR — Strip \r and \n from strings passed through imap_quote() to prevent injected IMAP commands via search parameters and other user-controlled inputs.

Key changes

  • Strip CR/LF before IMAP quoting — removes \r and \n from the value in imap_quote() per RFC 3501, then escapes \ and " as before
  • Add injection and escape tests — two unit tests verifying the CR/LF injection payload is neutralized and existing escape logic is preserved

Summary | 1 file | 1 commit | base: mainfix/imap-command-injection

The change adds a sanitization step that removes CR and LF before the standard IMAP quoting logic, closing the command injection vector via user-controlled from_contains or subject_contains parameters. All four call sites (LOGIN, SELECT, FROM, SUBJECT) already use imap_quote, so they are automatically protected. The stripping-before-escaping order is correct (the byte values for \r and \n don't overlap with \ or "), and the test coverage is appropriate.

src/email.rs

Pullfrog  | View workflow run | Using Big Pickle (free) | 𝕏

@guanlan guanlan closed this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant