mirror of
https://github.com/golang/go.git
synced 2026-06-27 19:30:52 +00:00
net/textproto: escape arbitrary input when including them in errors
When returning errors, functions in the net/textproto package would include its input as part of the error, without any escaping. Note that said input is often controlled by external parties when using this package naturally. For example, a net/http client uses ReadMIMEHeader when parsing the headers it receive from a server. As a result, an attacker could inject arbitrary content into the error. Practically, this can result in an attacker injecting misleading content, terminal control bytes, etc. into a victim's output or logs. Fix this issue by making sure that ProtocolError usages within the package are properly escaped, and that Error.String will escape its Msg. Fixes #79346 Fixes CVE-2026-42507 Change-Id: Ide4c1005d8254f90d95d7a389b8ca3a26a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/777060 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Nicholas Husin <husin@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
ab7c8279a0
commit
1a7e601d07
4 changed files with 15 additions and 13 deletions
|
|
@ -695,7 +695,7 @@ func TestHello(t *testing.T) {
|
|||
err = c.Hello("customhost")
|
||||
case 1:
|
||||
err = c.StartTLS(nil)
|
||||
if err.Error() == "502 Not implemented" {
|
||||
if err.Error() == `502 "Not implemented"` {
|
||||
err = nil
|
||||
}
|
||||
case 2:
|
||||
|
|
@ -953,8 +953,8 @@ func TestAuthFailed(t *testing.T) {
|
|||
|
||||
if err == nil {
|
||||
t.Error("Auth: expected error; got none")
|
||||
} else if err.Error() != "535 Invalid credentials\nplease see www.example.com" {
|
||||
t.Errorf("Auth: got error: %v, want: %s", err, "535 Invalid credentials\nplease see www.example.com")
|
||||
} else if err.Error() != `535 "Invalid credentials\nplease see www.example.com"` {
|
||||
t.Errorf("Auth: got error: %v, want: %s", err, `535 "Invalid credentials\nplease see www.example.com"`)
|
||||
}
|
||||
|
||||
bcmdbuf.Flush()
|
||||
|
|
|
|||
|
|
@ -215,13 +215,13 @@ func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message
|
|||
|
||||
func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
|
||||
if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
|
||||
err = ProtocolError("short response: " + line)
|
||||
err = ProtocolError(fmt.Sprintf("short response: %q", line))
|
||||
return
|
||||
}
|
||||
continued = line[3] == '-'
|
||||
code, err = strconv.Atoi(line[0:3])
|
||||
if err != nil || code < 100 {
|
||||
err = ProtocolError("invalid response code: " + line)
|
||||
err = ProtocolError(fmt.Sprintf("invalid response code: %q", line))
|
||||
return
|
||||
}
|
||||
message = line[4:]
|
||||
|
|
@ -253,7 +253,7 @@ func parseCodeLine(line string, expectCode int) (code int, continued bool, messa
|
|||
func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
|
||||
code, continued, message, err := r.readCodeLine(expectCode)
|
||||
if err == nil && continued {
|
||||
err = ProtocolError("unexpected multi-line response: " + message)
|
||||
err = ProtocolError(fmt.Sprintf("unexpected multi-line response: %q", message))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
|||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
return m, ProtocolError("malformed MIME header initial line: " + string(line))
|
||||
return m, ProtocolError(fmt.Sprintf("malformed MIME header initial line: %q", line))
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -553,15 +553,15 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
|||
// Key ends at first colon.
|
||||
k, v, ok := bytes.Cut(kv, colon)
|
||||
if !ok {
|
||||
return m, ProtocolError("malformed MIME header line: " + string(kv))
|
||||
return m, ProtocolError(fmt.Sprintf("malformed MIME header line: %q", kv))
|
||||
}
|
||||
key, ok := canonicalMIMEHeaderKey(k)
|
||||
if !ok {
|
||||
return m, ProtocolError("malformed MIME header line: " + string(kv))
|
||||
return m, ProtocolError(fmt.Sprintf("malformed MIME header line: %q", kv))
|
||||
}
|
||||
for _, c := range v {
|
||||
if !validHeaderValueByte(c) {
|
||||
return m, ProtocolError("malformed MIME header line: " + string(kv))
|
||||
return m, ProtocolError(fmt.Sprintf("malformed MIME header line: %q", kv))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -411,6 +411,8 @@ func TestReadMultiLineError(t *testing.T) {
|
|||
"Unexpected but legal text!\n" +
|
||||
"5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp"
|
||||
|
||||
wantError := `550 "5.1.1 The email account that you tried to reach does not exist. Please try\n5.1.1 double-checking the recipient's email address for typos or\n5.1.1 unnecessary spaces. Learn more at\nUnexpected but legal text!\n5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp"`
|
||||
|
||||
code, msg, err := r.ReadResponse(250)
|
||||
if err == nil {
|
||||
t.Errorf("ReadResponse: no error, want error")
|
||||
|
|
@ -421,8 +423,8 @@ func TestReadMultiLineError(t *testing.T) {
|
|||
if msg != wantMsg {
|
||||
t.Errorf("ReadResponse: msg=%q, want %q", msg, wantMsg)
|
||||
}
|
||||
if err != nil && err.Error() != "550 "+wantMsg {
|
||||
t.Errorf("ReadResponse: error=%q, want %q", err.Error(), "550 "+wantMsg)
|
||||
if err != nil && err.Error() != wantError {
|
||||
t.Errorf("ReadResponse: error=%q, want %q", err.Error(), wantError)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type Error struct {
|
|||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%03d %s", e.Code, e.Msg)
|
||||
return fmt.Sprintf("%03d %q", e.Code, e.Msg)
|
||||
}
|
||||
|
||||
// A ProtocolError describes a protocol violation such
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue