CVE-2026-67445: Mailpit SMTP Command Parser Buffers Unbounded Vulnerability

HIGH
Advisory Identifier: GHSA-w878-pj84-3j5v
CVSS 7.5
CWE-400
Published
Advisory Summary

CVE-2026-67445 is a HIGH (CVSS 7.5) smtp command parser buffers unbounded vulnerability (CWE-400: Uncontrolled Resource Consumption) affecting Mailpit libraries in the Go ecosystem. The issue involves smtp command parser buffers unbounded command lines before syntax rejection. Remediation is available by upgrading affected packages to version 1.30.4.

CVE-2026-67445 at a Glance

CVE Identifier CVE-2026-67445
GHSA Identifier GHSA-w878-pj84-3j5v
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-400: Uncontrolled Resource Consumption
Affected Product Mailpit
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (A:H)

How to Fix CVE-2026-67445

To remediate this vulnerability, upgrade all affected Mailpit dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/axllent/mailpit fixed: 1.30.4
Upgrade github.com/axllent/mailpit to 1.30.4
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/axllent/mailpit

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-67445, inspect your project dependencies for Mailpit:

inspect dependencies for github.com/axllent/mailpit

Analyze the terminal output to locate any version of Mailpit in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.30.4), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption, where the product does not properly control the allocation and maintenance of a limited resource. In Mailpit, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary Mailpit's SMTP server reads each command line with an unbounded `bufio.Reader.ReadString('\n')` before parsing the command or enforcing any protocol length limit. A remote SMTP client can send an oversized single command line and force Mailpit to allocate attacker-controlled memory before the server returns a syntax error or times out, even though RFC 5321 limits SMTP command lines to 512 octets including CRLF. ## Technical Details Mailpit enables SMTP by default. `config/config.go` sets `SMTPListen = "[::]:1025"`, and `cmd/root.go` calls `smtpd.Listen()` during normal startup. The SMTP server configures recipient and message DATA size limits in `internal/smtpd/main.go`, including the default 50 MiB `MaxMessageSize`, but those limits do not apply to command lines. The vulnerable path is in the SMTP command loop. `internal/smtpd/smtpd.go` calls `s.readLine()` for every command before parsing the verb or arguments: ```go line, err := s.readLine() if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { s.writef("421 4.4.2 %s %s ESMTP Service closing transmission channel after timeout exceeded", s.srv.Hostname, s.srv.AppName) } break } verb, args := s.parseLine(line) ``` `readLine()` then buffers until newline without a maximum length: ```go func (s *session) readLine() (string, error) { if s.srv.Timeout > 0 { _ = s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout)) } line, err := s.br.ReadString('\n') if err != nil { return "", err } line = strings.TrimSpace(line) return line, err } ``` This violates the SMTP command-line invariant before later validation can help. Address length validation in `extractAndValidateAddress()` runs only after the entire command line has already been buffered and parsed. The DATA reader has a separate `srv.MaxSize` check, but the issue is pre-DATA command input. ## PoV The following bounded test exercises the same command reader with a normal `NOOP` control and an 8 MiB oversized command line: ```go package smtpd import ( "bufio" "bytes" "strings" "testing" ) func TestUnboundedSMTPCommandLinePoV(t *testing.T) { short := "NOOP\r\n" shortSession := session{srv: &Server{}, br: bufio.NewReader(strings.NewReader(short))} shortLine, err := shortSession.readLine() if err != nil { t.Fatalf("short control readLine failed: %v", err) } t.Logf("short control: accepted len=%d command=%q", len(shortLine), shortLine) oversizedLen := 8 * 1024 * 1024 oversized := strings.Repeat("X", oversizedLen) + "\r\n" oversizedSession := session{srv: &Server{}, br: bufio.NewReader(bytes.NewBufferString(oversized))} oversizedLine, err := oversizedSession.readLine() if err != nil { t.Fatalf("oversized readLine failed: %v", err) } t.Logf("oversized command: accepted len=%d; RFC 5321 command-line limit is 512 octets including CRLF", len(oversizedLine)) if len(oversizedLine) != oversizedLen { t.Fatalf("readLine length = %d, want %d", len(oversizedLine), oversizedLen) } if len(oversizedLine) <= 512 { t.Fatalf("oversized command did not exceed SMTP command-line limit") } } ``` ## PoC From a Mailpit checkout, save the PoV above as `internal/smtpd/smtp_command_line_pov_test.go` and run: ```fish docker run --rm -v "$PWD:/src" -w /src golang:1.25 go test ./internal/smtpd -run TestUnboundedSMTPCommandLinePoV -v ``` On current `develop` commit `cd7661fd5b23cce1e218b583b21e157cfa612051`, the test prints: ```text === RUN TestUnboundedSMTPCommandLinePoV smtp_command_line_pov_test.go:17: short control: accepted len=4 command="NOOP" smtp_command_line_pov_test.go:26: oversized command: accepted len=8388608; RFC 5321 command-line limit is 512 octets including CRLF --- PASS: TestUnboundedSMTPCommandLinePoV (0.01s) PASS ok github.com/axllent/mailpit/internal/smtpd 0.017s ``` The same test against release `v1.30.3` commit `6acf5b8f942ab0e007b1227d31dfb3c3303e8d13` prints: ```text === RUN TestUnboundedSMTPCommandLinePoV smtp_command_line_pov_test.go:17: short control: accepted len=4 command="NOOP" smtp_command_line_pov_test.go:26: oversized command: accepted len=8388608; RFC 5321 command-line limit is 512 octets including CRLF --- PASS: TestUnboundedSMTPCommandLinePoV (0.02s) PASS ok github.com/axllent/mailpit/internal/smtpd 0.020s ``` The `NOOP` control shows the normal reader path. The oversized case shows the parser accepting an 8 MiB command line into memory instead of rejecting at the SMTP command-line limit. ## Impact An unauthenticated remote client that can reach Mailpit's SMTP listener can force heap allocation proportional to a single command line before any SMTP command is parsed. Repeating the input across concurrent connections can consume process memory and degrade or deny Mailpit service availability. This is distinct from message DATA size handling: the default `MaxMessageSize` cap is enforced after `DATA`, while the command-line reader is reached before DATA and before `MAIL FROM SIZE=` handling. Suggested advisory metadata: CWE-400 (Uncontrolled Resource Consumption). Conservative CVSS 3.1 vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`, base score 7.5 (High). If a deployment explicitly binds SMTP to trusted loopback-only clients, environmental severity may be lower; the project default is a network SMTP listener on `[::]:1025`. ## Suggested Fix Bound SMTP command-line reads before buffering the full line. For ordinary SMTP commands, reject input exceeding RFC 5321's 512-octet command-line limit including CRLF, returning a `500 5.5.2`-style command-line-too-long response before allocating the entire attacker-controlled line. Apply the same pre-parse bound to AUTH continuation lines because `handleAuthLogin()`, `handleAuthPlain()`, and `handleAuthCramMD5()` also call `readLine()`. Consider adding a similar POP3 command-line cap in `internal/pop3/server.go`, where the optional POP3 server also uses `ReadString('\n')` for commands. Regression tests should cover a normal short command, an over-limit command line, and over-limit AUTH continuation input. They should assert that the over-limit cases fail without returning the oversized string to command parsing. ## Affected Package/Versions Confirmed affected: - Current `develop`: `cd7661fd5b23cce1e218b583b21e157cfa612051` - Latest release: `v1.30.3`, tag commit `6acf5b8f942ab0e007b1227d31dfb3c3303e8d13`, published 2026-06-27 No fixed version was identified during this review. ## Advisory History The closest published Mailpit advisory is `GHSA-fpxj-m5q8-fphw`, which covers unauthenticated memory exhaustion through unlimited SMTP DATA and `/api/v1/send` body sizes. This report is different: it targets the pre-DATA SMTP command-line reader before `srv.MaxSize`, `MAIL FROM SIZE=`, or DATA handling applies. Other published Mailpit advisories checked were `GHSA-28pq-6qxg-wg5r` for HTTP JSON body limits, `GHSA-54wq-72mp-cq7c` for SMTP header injection, `GHSA-w4vj-r5pg-3722` for proxy CSS map concurrency, `GHSA-qx5x-85p8-vg4j` for dump path traversal, the SSRF/link-check/proxy advisories `GHSA-8v65-47jx-7mfr`, `GHSA-mpf7-p9x7-96r3`, `GHSA-6jxm-fv7w-rw5j`, `GHSA-j3fj-qppj-fmmc`, `GHSA-w4mc-hhc6-xp28`, and `GHSA-524m-q5m7-79mm` for CSWSH. None of these describe unbounded SMTP command-line buffering. Public Mailpit issue searches for `SMTP command line too long ReadString`, `SMTP 512 octets command line`, `SMTP memory DoS command line`, and `ReadString smtpd` found no matching issue. Public commit searches for `ReadString smtpd`, `command line too long`, and `MaxMessageSize smtp` found no matching fix. No prior submitted, ready-for-review, or completed-but-unsubmitted Mailpit report available in the review materials matched this root cause. ## References - RFC 5321 section 4.5.3.1.4, command-line length limit: https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.4 - Mailpit security policy: https://github.com/axllent/mailpit/security/policy - `GHSA-fpxj-m5q8-fphw`: https://github.com/axllent/mailpit/security/advisories/GHSA-fpxj-m5q8-fphw - `GHSA-28pq-6qxg-wg5r`: https://github.com/axllent/mailpit/security/advisories/GHSA-28pq-6qxg-wg5r - `GHSA-54wq-72mp-cq7c`: https://github.com/axllent/mailpit/security/advisories/GHSA-54wq-72mp-cq7c

CVE-2026-67445 Affected Mailpit Versions

1 component(s)
Fixed Versions:
1.30.4
Product / Package Ecosystem Affected Versions Fixed Version
github.com/axllent/mailpit
Go
< 1.30.4
1.30.4

References

Frequently Asked Questions

What is CVE-2026-67445?
CVE-2026-67445 is a security vulnerability in Mailpit involving SMTP command parser buffers unbounded command lines before syntax rejection under CWE-400: Uncontrolled Resource Consumption.
Which Mailpit versions are affected?
Affected versions include releases prior to 1.30.4 across affected packages: github.com/axllent/mailpit.
What version fixes CVE-2026-67445?
Upgrading to 1.30.4 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/axllent/mailpit affected?
Yes, github.com/axllent/mailpit is affected in releases prior to 1.30.4. Upgrade your dependency to 1.30.4 or later.
What is the CVSS score of CVE-2026-67445?
CVE-2026-67445 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with CVE-2026-67445?
CVE-2026-67445 is classified under CWE-400: Uncontrolled Resource Consumption (The product does not properly control the allocation and maintenance of a limited resource.).
How can I check Go dependencies for CVE-2026-67445?
Run the dependency tree command: 'inspect dependencies for github.com/axllent/mailpit'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-w878-pj84-3j5v",
  "modified" : "2026-09-02T23:42:25Z",
  "published" : "2026-09-02T23:42:25Z",
  "aliases" : [ "CVE-2026-67445" ],
  "summary" : "Mailpit: SMTP command parser buffers unbounded command lines before syntax rejection",
  "details" : "## Summary\n\nMailpit's SMTP server reads each command line with an unbounded `bufio.Reader.ReadString('\\n')` before parsing the command or enforcing any protocol length limit. A remote SMTP client can send an oversized single command line and force Mailpit to allocate attacker-controlled memory before the server returns a syntax error or times out, even though RFC 5321 limits SMTP command lines to 512 octets including CRLF.\n\n## Technical Details\n\nMailpit enables SMTP by default. `config/config.go` sets `SMTPListen = \"[::]:1025\"`, and `cmd/root.go` calls `smtpd.Listen()` during normal startup. The SMTP server configures recipient and message DATA size limits in `internal/smtpd/main.go`, including the default 50 MiB `MaxMessageSize`, but those limits do not apply to command lines.\n\nThe vulnerable path is in the SMTP command loop. `internal/smtpd/smtpd.go` calls `s.readLine()` for every command before parsing the verb or arguments:\n\n```go\nline, err := s.readLine()\nif err != nil {\n    if netErr, ok := err.(net.Error); ok && netErr.Timeout() {\n        s.writef(\"421 4.4.2 %s %s ESMTP Service closing transmission channel after timeout exceeded\", s.srv.Hostname, s.srv.AppName)\n    }\n    break\n}\n\nverb, args := s.parseLine(line)\n```\n\n`readLine()` then buffers until newline without a maximum length:\n\n```go\nfunc (s *session) readLine() (string, error) {\n    if s.srv.Timeout > 0 {\n        _ = s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout))\n    }\n\n    line, err := s.br.ReadString('\\n')\n    if err != nil {\n        return \"\", err\n    }\n    line = strings.TrimSpace(line)\n    return line, err\n}\n```\n\nThis violates the SMTP command-line invariant before later validation can help. Address length validation in `extractAndValidateAddress()` runs only after the entire command line has already been buffered and parsed. The DATA reader has a separate `srv.MaxSize` check, but the issue is pre-DATA command input.\n\n## PoV\n\nThe following bounded test exercises the same command reader with a normal `NOOP` control and an 8 MiB oversized command line:\n\n```go\npackage smtpd\n\nimport (\n    \"bufio\"\n    \"bytes\"\n    \"strings\"\n    \"testing\"\n)\n\nfunc TestUnboundedSMTPCommandLinePoV(t *testing.T) {\n    short := \"NOOP\\r\\n\"\n    shortSession := session{srv: &Server{}, br: bufio.NewReader(strings.NewReader(short))}\n    shortLine, err := shortSession.readLine()\n    if err != nil {\n        t.Fatalf(\"short control readLine failed: %v\", err)\n    }\n    t.Logf(\"short control: accepted len=%d command=%q\", len(shortLine), shortLine)\n\n    oversizedLen := 8 * 1024 * 1024\n    oversized := strings.Repeat(\"X\", oversizedLen) + \"\\r\\n\"\n    oversizedSession := session{srv: &Server{}, br: bufio.NewReader(bytes.NewBufferString(oversized))}\n    oversizedLine, err := oversizedSession.readLine()\n    if err != nil {\n        t.Fatalf(\"oversized readLine failed: %v\", err)\n    }\n    t.Logf(\"oversized command: accepted len=%d; RFC 5321 command-line limit is 512 octets including CRLF\", len(oversizedLine))\n\n    if len(oversizedLine) != oversizedLen {\n        t.Fatalf(\"readLine length = %d, want %d\", len(oversizedLine), oversizedLen)\n    }\n    if len(oversizedLine) <= 512 {\n        t.Fatalf(\"oversized command did not exceed SMTP command-line limit\")\n    }\n}\n```\n\n## PoC\n\nFrom a Mailpit checkout, save the PoV above as `internal/smtpd/smtp_command_line_pov_test.go` and run:\n\n```fish\ndocker run --rm -v \"$PWD:/src\" -w /src golang:1.25 go test ./internal/smtpd -run TestUnboundedSMTPCommandLinePoV -v\n```\n\nOn current `develop` commit `cd7661fd5b23cce1e218b583b21e157cfa612051`, the test prints:\n\n```text\n=== RUN   TestUnboundedSMTPCommandLinePoV\n    smtp_command_line_pov_test.go:17: short control: accepted len=4 command=\"NOOP\"\n    smtp_command_line_pov_test.go:26: oversized command: accepted len=8388608; RFC 5321 command-line limit is 512 octets including CRLF\n--- PASS: TestUnboundedSMTPCommandLinePoV (0.01s)\nPASS\nok  \tgithub.com/axllent/mailpit/internal/smtpd\t0.017s\n```\n\nThe same test against release `v1.30.3` commit `6acf5b8f942ab0e007b1227d31dfb3c3303e8d13` prints:\n\n```text\n=== RUN   TestUnboundedSMTPCommandLinePoV\n    smtp_command_line_pov_test.go:17: short control: accepted len=4 command=\"NOOP\"\n    smtp_command_line_pov_test.go:26: oversized command: accepted len=8388608; RFC 5321 command-line limit is 512 octets including CRLF\n--- PASS: TestUnboundedSMTPCommandLinePoV (0.02s)\nPASS\nok  \tgithub.com/axllent/mailpit/internal/smtpd\t0.020s\n```\n\nThe `NOOP` control shows the normal reader path. The oversized case shows the parser accepting an 8 MiB command line into memory instead of rejecting at the SMTP command-line limit.\n\n## Impact\n\nAn unauthenticated remote client that can reach Mailpit's SMTP listener can force heap allocation proportional to a single command line before any SMTP command is parsed. Repeating the input across concurrent connections can consume process memory and degrade or deny Mailpit service availability. This is distinct from message DATA size handling: the default `MaxMessageSize` cap is enforced after `DATA`, while the command-line reader is reached before DATA and before `MAIL FROM SIZE=` handling.\n\nSuggested advisory metadata: CWE-400 (Uncontrolled Resource Consumption). Conservative CVSS 3.1 vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`, base score 7.5 (High). If a deployment explicitly binds SMTP to trusted loopback-only clients, environmental severity may be lower; the project default is a network SMTP listener on `[::]:1025`.\n\n## Suggested Fix\n\nBound SMTP command-line reads before buffering the full line. For ordinary SMTP commands, reject input exceeding RFC 5321's 512-octet command-line limit including CRLF, returning a `500 5.5.2`-style command-line-too-long response before allocating the entire attacker-controlled line. Apply the same pre-parse bound to AUTH continuation lines because `handleAuthLogin()`, `handleAuthPlain()`, and `handleAuthCramMD5()` also call `readLine()`. Consider adding a similar POP3 command-line cap in `internal/pop3/server.go`, where the optional POP3 server also uses `ReadString('\\n')` for commands.\n\nRegression tests should cover a normal short command, an over-limit command line, and over-limit AUTH continuation input. They should assert that the over-limit cases fail without returning the oversized string to command parsing.\n\n## Affected Package/Versions\n\nConfirmed affected:\n\n- Current `develop`: `cd7661fd5b23cce1e218b583b21e157cfa612051`\n- Latest release: `v1.30.3`, tag commit `6acf5b8f942ab0e007b1227d31dfb3c3303e8d13`, published 2026-06-27\n\nNo fixed version was identified during this review.\n\n## Advisory History\n\nThe closest published Mailpit advisory is `GHSA-fpxj-m5q8-fphw`, which covers unauthenticated memory exhaustion through unlimited SMTP DATA and `/api/v1/send` body sizes. This report is different: it targets the pre-DATA SMTP command-line reader before `srv.MaxSize`, `MAIL FROM SIZE=`, or DATA handling applies.\n\nOther published Mailpit advisories checked were `GHSA-28pq-6qxg-wg5r` for HTTP JSON body limits, `GHSA-54wq-72mp-cq7c` for SMTP header injection, `GHSA-w4vj-r5pg-3722` for proxy CSS map concurrency, `GHSA-qx5x-85p8-vg4j` for dump path traversal, the SSRF/link-check/proxy advisories `GHSA-8v65-47jx-7mfr`, `GHSA-mpf7-p9x7-96r3`, `GHSA-6jxm-fv7w-rw5j`, `GHSA-j3fj-qppj-fmmc`, `GHSA-w4mc-hhc6-xp28`, and `GHSA-524m-q5m7-79mm` for CSWSH. None of these describe unbounded SMTP command-line buffering.\n\nPublic Mailpit issue searches for `SMTP command line too long ReadString`, `SMTP 512 octets command line`, `SMTP memory DoS command line`, and `ReadString smtpd` found no matching issue. Public commit searches for `ReadString smtpd`, `command line too long`, and `MaxMessageSize smtp` found no matching fix. No prior submitted, ready-for-review, or completed-but-unsubmitted Mailpit report available in the review materials matched this root cause.\n\n## References\n\n- RFC 5321 section 4.5.3.1.4, command-line length limit: https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.4\n- Mailpit security policy: https://github.com/axllent/mailpit/security/policy\n- `GHSA-fpxj-m5q8-fphw`: https://github.com/axllent/mailpit/security/advisories/GHSA-fpxj-m5q8-fphw\n- `GHSA-28pq-6qxg-wg5r`: https://github.com/axllent/mailpit/security/advisories/GHSA-28pq-6qxg-wg5r\n- `GHSA-54wq-72mp-cq7c`: https://github.com/axllent/mailpit/security/advisories/GHSA-54wq-72mp-cq7c",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/axllent/mailpit"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.30.4"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 1.30.3"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/axllent/mailpit/security/advisories/GHSA-w878-pj84-3j5v"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-67445"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/axllent/mailpit/commit/993bed95b3c74d95231af93bd0e0d4c3d5b4db4d"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/axllent/mailpit"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/axllent/mailpit/releases/tag/v1.30.4"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-400" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-09-02T23:42:25Z",
    "nvd_published_at" : "2026-08-20T21:17:07Z"
  }
}