Skip to content

Commit 79ce159

Browse files
committed
max size and check whether doer is allowed
1 parent 13190eb commit 79ce159

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

custom/conf/app.example.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,9 @@ LEVEL = Info
17071707
;;
17081708
;; convert links of attached images to inline images. Only for images hosted in this gitea instance.
17091709
;BASE64_EMBED_IMAGES = false
1710+
;;
1711+
;; The maximum size of an image attachment to be embedded in the email.
1712+
;BASE64_EMBED_IMAGES_MAX_SIZE = 5242880
17101713

17111714
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17121715
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

modules/setting/mailer.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,23 @@ import (
1313

1414
"code.gitea.io/gitea/modules/log"
1515

16-
shellquote "github.com/kballard/go-shellquote"
16+
"github.com/kballard/go-shellquote"
1717
)
1818

1919
// Mailer represents mail service.
2020
type Mailer struct {
2121
// Mailer
22-
Name string `ini:"NAME"`
23-
From string `ini:"FROM"`
24-
EnvelopeFrom string `ini:"ENVELOPE_FROM"`
25-
OverrideEnvelopeFrom bool `ini:"-"`
26-
FromName string `ini:"-"`
27-
FromEmail string `ini:"-"`
28-
SendAsPlainText bool `ini:"SEND_AS_PLAIN_TEXT"`
29-
SubjectPrefix string `ini:"SUBJECT_PREFIX"`
30-
OverrideHeader map[string][]string `ini:"-"`
31-
Base64EmbedImages bool `ini:"BASE64_EMBED_IMAGES"`
22+
Name string `ini:"NAME"`
23+
From string `ini:"FROM"`
24+
EnvelopeFrom string `ini:"ENVELOPE_FROM"`
25+
OverrideEnvelopeFrom bool `ini:"-"`
26+
FromName string `ini:"-"`
27+
FromEmail string `ini:"-"`
28+
SendAsPlainText bool `ini:"SEND_AS_PLAIN_TEXT"`
29+
SubjectPrefix string `ini:"SUBJECT_PREFIX"`
30+
OverrideHeader map[string][]string `ini:"-"`
31+
Base64EmbedImages bool `ini:"BASE64_EMBED_IMAGES"`
32+
Base64EmbedImagesMaxSizePerAttachment int64 `ini:"BASE64_EMBED_IMAGES_MAX_SIZE_PER_ATTACHMENT"`
3233

3334
// SMTP sender
3435
Protocol string `ini:"PROTOCOL"`
@@ -152,6 +153,7 @@ func loadMailerFrom(rootCfg ConfigProvider) {
152153
sec.Key("SENDMAIL_CONVERT_CRLF").MustBool(true)
153154
sec.Key("FROM").MustString(sec.Key("USER").String())
154155
sec.Key("BASE64_EMBED_IMAGES").MustBool(false)
156+
sec.Key("BASE64_EMBED_IMAGES_MAX_SIZE_PER_ATTACHMENT").MustInt64(5 * 1024 * 1024)
155157

156158
// Now map the values on to the MailService
157159
MailService = &Mailer{}

services/mailer/mail.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121

2222
activities_model "code.gitea.io/gitea/models/activities"
2323
issues_model "code.gitea.io/gitea/models/issues"
24+
access_model "code.gitea.io/gitea/models/perm/access"
2425
repo_model "code.gitea.io/gitea/models/repo"
26+
"code.gitea.io/gitea/models/unit"
2527
user_model "code.gitea.io/gitea/models/user"
2628
"code.gitea.io/gitea/modules/base"
2729
"code.gitea.io/gitea/modules/emoji"
@@ -421,6 +423,7 @@ func Base64InlineImages(body string, ctx *MailCommentContext) (string, error) {
421423
}
422424

423425
func AttachmentSrcToBase64DataURI(attachmentPath string, ctx *MailCommentContext) (string, error) {
426+
maxSizePerImageAttachment := setting.MailService.Base64EmbedImagesMaxSizePerAttachment
424427
if !strings.HasPrefix(attachmentPath, setting.AppURL) { // external image
425428
return "", fmt.Errorf("external image")
426429
}
@@ -435,6 +438,16 @@ func AttachmentSrcToBase64DataURI(attachmentPath string, ctx *MailCommentContext
435438
return "", err
436439
}
437440

441+
// "Doer" is theoretically not the correct permission check (as Doer created the action on which to send), but as this is batch processed the receipants can't be accessed.
442+
// Therefore we check the Doer, with which we counter leaking information as a Doer brute force attack on attachments would be possible.
443+
perm, err := access_model.GetUserRepoPermission(ctx, ctx.Issue.Repo, ctx.Doer)
444+
if err != nil {
445+
return "", err
446+
}
447+
if !perm.CanRead(unit.TypeIssues) {
448+
return "", fmt.Errorf("no permission")
449+
}
450+
438451
fr, err := storage.Attachments.Open(attachment.RelativePath())
439452
if err != nil {
440453
return "", err
@@ -446,7 +459,16 @@ func AttachmentSrcToBase64DataURI(attachmentPath string, ctx *MailCommentContext
446459
return "", err
447460
}
448461

462+
if len(content) > int(maxSizePerImageAttachment) {
463+
return "", fmt.Errorf("image too large (%d bytes) of max %d bytes", len(content), maxSizePerImageAttachment)
464+
}
465+
449466
mimeType := http.DetectContentType(content)
467+
468+
if !strings.HasPrefix(mimeType, "image/") {
469+
return "", fmt.Errorf("not an image")
470+
}
471+
450472
encoded := base64.StdEncoding.EncodeToString(content)
451473
dataURI := fmt.Sprintf("data:%s;base64,%s", mimeType, encoded)
452474

0 commit comments

Comments
 (0)