Add Email Content Injection Query (#108)

This adds a query for Email content injection issues.
It models the Golang's net/smtp library as well as
the Sendgrid email library (581 stars).
This commit is contained in:
porcupineyhairs
2020-05-04 12:24:30 +05:30
committed by GitHub
parent cd1d699208
commit 657108d598
22 changed files with 1319 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
package main
import (
"net/http"
"net/smtp"
)
func mail(w http.ResponseWriter, r *http.Request) {
host := r.Header.Get("Host")
token := backend.getUserSecretResetToken(email)
body := "Click to reset password: " + host + "/" + token
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body))
}

View File

@@ -0,0 +1,13 @@
package main
import (
"net/http"
"net/smtp"
)
func mailGood(w http.ResponseWriter, r *http.Request) {
host := config.Get("Host")
token := backend.getUserSecretResetToken(email)
body := "Click to reset password: " + host + "/" + token
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body))
}

View File

@@ -0,0 +1,48 @@
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
<qhelp>
<overview>
<p>
Using untrusted input to construct an email induces multiple security
vulnerabilities. For instance, inclusion of an untrusted input in a email body
may allow an attacker to conduct Cross Site Scripting (XSS) Attacks. While
inclusion of an HTTP Header in the email body may allow a full account
compromise as shown in the example below.
</p>
</overview>
<recommendation>
<p>
Any data which is passed to an email subject or body must be sanitized before use.
</p>
</recommendation>
<example>
<p>
In the following example snippet, the
<code>host</code>
field is user controlled.
</p>
<p>
A malicious user can send an HTTP request to the targeted web site,
but with a Host header that refers to his own web site. This means the
emails will be sent out to potential victims, originating from a server
they trust, but with links leading to a malicious web site.
</p>
<p>
If the email contains a password reset link, and should the victim click
the link, the secret reset token will be leaked to the attacker. Using the
leaked token, the attacker can then construct the real reset link and use it to
change the victim's password.
</p>
<sample src="EmailBad.go" />
<p>
One way to prevent this is to load the host name from a trusted configuration file instead.
</p>
<sample src="EmailGood.go" />
</example>
<references>
<li>
OWASP
<a href="https://owasp.org/www-community/attacks/Content_Spoofing">Content Spoofing</a>
.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Email content injection
* @description Incorporating untrusted input directly into an email message can enable
* content spoofing, which in turn may lead to information leaks and other
* security issues.
* @id go/email-injection
* @kind path-problem
* @problem.severity error
* @tags security
* external/cwe/cwe-640
*/
import go
import DataFlow::PathGraph
import EmailInjection::EmailInjection
from DataFlow::PathNode source, DataFlow::PathNode sink, Configuration config
where config.hasFlowPath(source, sink)
select sink, source, sink, "Email content may contain $@.", source.getNode(), "untrusted input"

View File

@@ -0,0 +1,29 @@
/**
* Provides a taint-tracking configuration for reasoning about
* server-side email-injection vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `EmailInjection::Configuration` is needed, otherwise
* `EmailInjectionCustomizations` should be imported instead.
*/
import go
/**
* Provides a taint-tracking configuration for reasoning about
* email-injection vulnerabilities.
*/
module EmailInjection {
import EmailInjectionCustomizations::EmailInjection
/**
* A taint-tracking configuration for reasoning about email-injection vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Email Injection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
}
}

View File

@@ -0,0 +1,30 @@
/** Provides classes for reasoning about email-injection vulnerabilities. */
import go
/**
* Provides a library for reasoning about email-injection vulnerabilities.
*/
module EmailInjection {
/**
* A data-flow node that should be considered a source of untrusted data for email-injection vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data-flow node that should be considered a sink for email-injection vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/** A source of untrusted data, considered as a taint source for email injection. */
class UntrustedFlowSourceAsSource extends Source {
UntrustedFlowSourceAsSource() { this instanceof UntrustedFlowSource }
}
/**
* A data-flow node that becomes part of an email considered as a taint sink for email injection.
*/
class MailDataAsSink extends Sink {
MailDataAsSink() { this instanceof MailData }
}
}

View File

@@ -24,6 +24,7 @@ import semmle.go.dataflow.DataFlow
import semmle.go.dataflow.GlobalValueNumbering
import semmle.go.dataflow.TaintTracking
import semmle.go.dataflow.SSA
import semmle.go.frameworks.Email
import semmle.go.frameworks.HTTP
import semmle.go.frameworks.Macaron
import semmle.go.frameworks.SystemCommandExecutors

View File

@@ -0,0 +1,110 @@
/** Provides classes for working with email-related APIs. */
import go
/**
* A data-flow node that represents data written to an email.
* Data in this case includes the email headers and the mail body
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `MailDataCall::Range` instead.
*/
class MailData extends DataFlow::Node {
MailDataCall::Range self;
MailData() { this = self.getData() }
}
/** Provides classes for working with calls which write data to an email. */
module MailDataCall {
/**
* A data-flow node that represents a call which writes data to an email.
* Data in this case refers to email headers and the mail body
*
*/
abstract class Range extends DataFlow::CallNode {
/** Gets data written to an email connection. */
abstract DataFlow::Node getData();
}
/** Get the package name `github.com/sendgrid/sendgrid-go/helpers/mail`. */
bindingset[result]
private string sendgridMail() { result = "github.com/sendgrid/sendgrid-go/helpers/mail" }
/** A Client.Data expression string used in an API function of the net/smtp package. */
private class SmtpData extends Range {
SmtpData() {
// func (c *Client) Data() (io.WriteCloser, error)
this.getTarget().(Method).hasQualifiedName("net/smtp", "Client", "Data")
}
override DataFlow::Node getData() {
exists(DataFlow::CallNode write, DataFlow::Node writer, int i |
this.getResult(0) = writer and
(
write.getTarget().hasQualifiedName("fmt", "Fprintf")
or
write.getTarget().hasQualifiedName("io", "WriteString")
) and
writer.getASuccessor*() = write.getArgument(0) and
i > 0 and
write.getArgument(i) = result
)
}
}
/** A send mail expression string used in an API function of the net/smtp package. */
private class SmtpSendMail extends Range {
SmtpSendMail() {
// func SendMail(addr string, a Auth, from string, to []string, msg []byte) error
this.getTarget().hasQualifiedName("net/smtp", "SendMail")
}
override DataFlow::Node getData() { result = this.getArgument(4) }
}
/** A call to `NewSingleEmail` API function of the Sendgrid mail package. */
private class SendGridSingleEmail extends Range {
SendGridSingleEmail() {
// func NewSingleEmail(from *Email, subject string, to *Email, plainTextContent string, htmlContent string) *SGMailV3
this.getTarget().hasQualifiedName(sendgridMail(), "NewSingleEmail")
}
override DataFlow::Node getData() { result = this.getArgument([1, 3, 4]) }
}
/* Gets the value of the `i`-th content parameter of the given `call` */
private DataFlow::Node getContent(DataFlow::CallNode call, int i) {
exists(DataFlow::CallNode cn, DataFlow::Node content |
// func NewContent(contentType string, value string) *Content
cn.getTarget().hasQualifiedName(sendgridMail(), "NewContent") and
cn.getResult() = content and
content.getASuccessor*() = call.getArgument(i) and
result = cn.getArgument(1)
)
}
/** A call to `NewV3MailInit` API function of the Sendgrid mail package. */
private class SendGridV3Init extends Range {
SendGridV3Init() {
// func NewV3MailInit(from *Email, subject string, to *Email, content ...*Content) *SGMailV3
this.getTarget().hasQualifiedName(sendgridMail(), "NewV3MailInit")
}
override DataFlow::Node getData() {
exists(int i | result = getContent(this, i) and i >= 3)
or
result = this.getArgument(1)
}
}
/** A call to `AddContent` API function of the Sendgrid mail package. */
private class SendGridAddContent extends Range {
SendGridAddContent() {
// func (s *SGMailV3) AddContent(c ...*Content) *SGMailV3
this.getTarget().(Method).hasQualifiedName(sendgridMail(), "SGMailV3", "AddContent")
}
override DataFlow::Node getData() { result = getContent(this, _) }
}
}

View File

@@ -0,0 +1,37 @@
edges
| email.go:24:10:24:17 | selection of Header : Header | email.go:27:56:27:67 | type conversion |
| email.go:34:21:34:31 | call to Referer : string | email.go:36:57:36:78 | type conversion |
| email.go:42:21:42:31 | call to Referer : string | email.go:46:25:46:38 | untrustedInput |
| email.go:51:21:51:31 | call to Referer : string | email.go:57:46:57:59 | untrustedInput |
| email.go:51:21:51:31 | call to Referer : string | email.go:58:52:58:65 | untrustedInput |
| email.go:63:21:63:31 | call to Referer : string | email.go:65:47:65:60 | untrustedInput |
| email.go:73:21:73:31 | call to Referer : string | email.go:79:47:79:60 | untrustedInput |
| email.go:87:21:87:31 | call to Referer : string | email.go:94:37:94:50 | untrustedInput |
| email.go:87:21:87:31 | call to Referer : string | email.go:96:48:96:61 | untrustedInput |
nodes
| email.go:24:10:24:17 | selection of Header : Header | semmle.label | selection of Header : Header |
| email.go:27:56:27:67 | type conversion | semmle.label | type conversion |
| email.go:34:21:34:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:36:57:36:78 | type conversion | semmle.label | type conversion |
| email.go:42:21:42:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:46:25:46:38 | untrustedInput | semmle.label | untrustedInput |
| email.go:51:21:51:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:57:46:57:59 | untrustedInput | semmle.label | untrustedInput |
| email.go:58:52:58:65 | untrustedInput | semmle.label | untrustedInput |
| email.go:63:21:63:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:65:47:65:60 | untrustedInput | semmle.label | untrustedInput |
| email.go:73:21:73:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:79:47:79:60 | untrustedInput | semmle.label | untrustedInput |
| email.go:87:21:87:31 | call to Referer : string | semmle.label | call to Referer : string |
| email.go:94:37:94:50 | untrustedInput | semmle.label | untrustedInput |
| email.go:96:48:96:61 | untrustedInput | semmle.label | untrustedInput |
#select
| email.go:27:56:27:67 | type conversion | email.go:24:10:24:17 | selection of Header : Header | email.go:27:56:27:67 | type conversion | Email content may contain $@. | email.go:24:10:24:17 | selection of Header | untrusted input |
| email.go:36:57:36:78 | type conversion | email.go:34:21:34:31 | call to Referer : string | email.go:36:57:36:78 | type conversion | Email content may contain $@. | email.go:34:21:34:31 | call to Referer | untrusted input |
| email.go:46:25:46:38 | untrustedInput | email.go:42:21:42:31 | call to Referer : string | email.go:46:25:46:38 | untrustedInput | Email content may contain $@. | email.go:42:21:42:31 | call to Referer | untrusted input |
| email.go:57:46:57:59 | untrustedInput | email.go:51:21:51:31 | call to Referer : string | email.go:57:46:57:59 | untrustedInput | Email content may contain $@. | email.go:51:21:51:31 | call to Referer | untrusted input |
| email.go:58:52:58:65 | untrustedInput | email.go:51:21:51:31 | call to Referer : string | email.go:58:52:58:65 | untrustedInput | Email content may contain $@. | email.go:51:21:51:31 | call to Referer | untrusted input |
| email.go:65:47:65:60 | untrustedInput | email.go:63:21:63:31 | call to Referer : string | email.go:65:47:65:60 | untrustedInput | Email content may contain $@. | email.go:63:21:63:31 | call to Referer | untrusted input |
| email.go:79:47:79:60 | untrustedInput | email.go:73:21:73:31 | call to Referer : string | email.go:79:47:79:60 | untrustedInput | Email content may contain $@. | email.go:73:21:73:31 | call to Referer | untrusted input |
| email.go:94:37:94:50 | untrustedInput | email.go:87:21:87:31 | call to Referer : string | email.go:94:37:94:50 | untrustedInput | Email content may contain $@. | email.go:87:21:87:31 | call to Referer | untrusted input |
| email.go:96:48:96:61 | untrustedInput | email.go:87:21:87:31 | call to Referer : string | email.go:96:48:96:61 | untrustedInput | Email content may contain $@. | email.go:87:21:87:31 | call to Referer | untrusted input |

View File

@@ -0,0 +1 @@
experimental/CWE-640/EmailInjection.ql

View File

@@ -0,0 +1,115 @@
package main
//go:generate depstubber -vendor github.com/sendgrid/sendgrid-go/helpers/mail "" NewEmail,NewSingleEmail,NewContent,NewV3Mail,NewV3MailInit
import (
"io"
"log"
"net/http"
"net/smtp"
sendgrid "github.com/sendgrid/sendgrid-go/helpers/mail"
)
// OK
func mailGood(w http.ResponseWriter, r *http.Request) {
host := config["Host"]
token := backend.getUserSecretResetToken(email)
body := "Click to reset password: " + host + "/" + token
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body))
}
// Not OK
func mail(w http.ResponseWriter, r *http.Request) {
host := r.Header.Get("Host")
token := backend.getUserSecretResetToken(email)
body := "Click to reset password: " + host + "/" + token
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body))
}
func main() {
// Not OK
http.HandleFunc("/ex0", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(untrustedInput))
})
// Not OK
http.HandleFunc("/ex1", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
s, _ := smtp.Dial("test.test")
write, _ := s.Data()
io.WriteString(write, untrustedInput)
})
// Not OK
http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
from := sendgrid.NewEmail("from", "from@from.com")
to := sendgrid.NewEmail("to", "to@to.com")
subject := "test"
body := "body"
sendgrid.NewSingleEmail(from, subject, to, untrustedInput, body)
sendgrid.NewSingleEmail(from, subject, to, body, untrustedInput)
})
// Not OK
http.HandleFunc("/ex3", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
content := sendgrid.NewContent("text/html", untrustedInput)
v := sendgrid.NewV3Mail()
v.AddContent(content)
})
// Not OK
http.HandleFunc("/ex4", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
from := sendgrid.NewEmail("from", "from@from.com")
to := sendgrid.NewEmail("to", "to@to.com")
subject := "test"
content := sendgrid.NewContent("text/html", untrustedInput)
v := sendgrid.NewV3MailInit(from, subject, to, content, content)
v.AddContent(content)
})
// Not OK
http.HandleFunc("/ex5", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
from := sendgrid.NewEmail("from", "from@from.com")
to := sendgrid.NewEmail("to", "to@to.com")
content := sendgrid.NewContent("text/html", "test")
v := sendgrid.NewV3MailInit(from, untrustedInput, to, content, content)
content2 := sendgrid.NewContent("text/html", untrustedInput)
v.AddContent(content2)
})
log.Println(http.ListenAndServe(":80", nil))
}
// Backend is an empty struct
type Backend struct{}
func (*Backend) getUserSecretResetToken(email string) string {
return ""
}
var email = "test@test.com"
var config map[string]string
var backend = &Backend{}

View File

@@ -0,0 +1,7 @@
module main
go 1.14
require (
github.com/sendgrid/sendgrid-go v3.5.0+incompatible
)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2019 Twilio SendGrid, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,391 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/sendgrid/sendgrid-go/helpers/mail, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/sendgrid/sendgrid-go/helpers/mail (exports: ; functions: NewEmail,NewSingleEmail,NewContent,NewV3Mail,NewV3MailInit)
// Package mail is a stub of github.com/sendgrid/sendgrid-go/helpers/mail, generated by depstubber.
package mail
import ()
type Asm struct {
GroupID int
GroupsToDisplay []int
}
func (_ *Asm) AddGroupsToDisplay(_ ...int) *Asm {
return nil
}
func (_ *Asm) SetGroupID(_ int) *Asm {
return nil
}
type Attachment struct {
Content string
Type string
Name string
Filename string
Disposition string
ContentID string
}
func (_ *Attachment) SetContent(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetContentID(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetDisposition(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetFilename(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetType(_ string) *Attachment {
return nil
}
type BccSetting struct {
Enable *bool
Email string
}
func (_ *BccSetting) SetEmail(_ string) *BccSetting {
return nil
}
func (_ *BccSetting) SetEnable(_ bool) *BccSetting {
return nil
}
type ClickTrackingSetting struct {
Enable *bool
EnableText *bool
}
func (_ *ClickTrackingSetting) SetEnable(_ bool) *ClickTrackingSetting {
return nil
}
func (_ *ClickTrackingSetting) SetEnableText(_ bool) *ClickTrackingSetting {
return nil
}
type Content struct {
Type string
Value string
}
type Email struct {
Name string
Address string
}
type FooterSetting struct {
Enable *bool
Text string
Html string
}
func (_ *FooterSetting) SetEnable(_ bool) *FooterSetting {
return nil
}
func (_ *FooterSetting) SetHTML(_ string) *FooterSetting {
return nil
}
func (_ *FooterSetting) SetText(_ string) *FooterSetting {
return nil
}
type GaSetting struct {
Enable *bool
CampaignSource string
CampaignTerm string
CampaignContent string
CampaignName string
CampaignMedium string
}
func (_ *GaSetting) SetCampaignContent(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignMedium(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignName(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignSource(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignTerm(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetEnable(_ bool) *GaSetting {
return nil
}
type MailSettings struct {
BCC *BccSetting
BypassListManagement *Setting
Footer *FooterSetting
SandboxMode *Setting
SpamCheckSetting *SpamCheckSetting
}
func (_ *MailSettings) SetBCC(_ *BccSetting) *MailSettings {
return nil
}
func (_ *MailSettings) SetBypassListManagement(_ *Setting) *MailSettings {
return nil
}
func (_ *MailSettings) SetFooter(_ *FooterSetting) *MailSettings {
return nil
}
func (_ *MailSettings) SetSandboxMode(_ *Setting) *MailSettings {
return nil
}
func (_ *MailSettings) SetSpamCheckSettings(_ *SpamCheckSetting) *MailSettings {
return nil
}
func NewContent(_ string, _ string) *Content {
return nil
}
func NewEmail(_ string, _ string) *Email {
return nil
}
func NewSingleEmail(_ *Email, _ string, _ *Email, _ string, _ string) *SGMailV3 {
return nil
}
func NewV3Mail() *SGMailV3 {
return nil
}
func NewV3MailInit(_ *Email, _ string, _ *Email, _ ...*Content) *SGMailV3 {
return nil
}
type OpenTrackingSetting struct {
Enable *bool
SubstitutionTag string
}
func (_ *OpenTrackingSetting) SetEnable(_ bool) *OpenTrackingSetting {
return nil
}
func (_ *OpenTrackingSetting) SetSubstitutionTag(_ string) *OpenTrackingSetting {
return nil
}
type Personalization struct {
To []*Email
CC []*Email
BCC []*Email
Subject string
Headers map[string]string
Substitutions map[string]string
CustomArgs map[string]string
DynamicTemplateData map[string]interface{}
Categories []string
SendAt int
}
func (_ *Personalization) AddBCCs(_ ...*Email) {}
func (_ *Personalization) AddCCs(_ ...*Email) {}
func (_ *Personalization) AddTos(_ ...*Email) {}
func (_ *Personalization) SetCustomArg(_ string, _ string) {}
func (_ *Personalization) SetDynamicTemplateData(_ string, _ interface{}) {}
func (_ *Personalization) SetHeader(_ string, _ string) {}
func (_ *Personalization) SetSendAt(_ int) {}
func (_ *Personalization) SetSubstitution(_ string, _ string) {}
type SGMailV3 struct {
From *Email
Subject string
Personalizations []*Personalization
Content []*Content
Attachments []*Attachment
TemplateID string
Sections map[string]string
Headers map[string]string
Categories []string
CustomArgs map[string]string
SendAt int
BatchID string
Asm *Asm
IPPoolID string
MailSettings *MailSettings
TrackingSettings *TrackingSettings
ReplyTo *Email
}
func (_ *SGMailV3) AddAttachment(_ ...*Attachment) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddCategories(_ ...string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddContent(_ ...*Content) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddPersonalizations(_ ...*Personalization) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddSection(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetASM(_ *Asm) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetBatchID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetCustomArg(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetFrom(_ *Email) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetHeader(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetIPPoolID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetMailSettings(_ *MailSettings) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetReplyTo(_ *Email) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetSendAt(_ int) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetTemplateID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetTrackingSettings(_ *TrackingSettings) *SGMailV3 {
return nil
}
type SandboxModeSetting struct {
Enable *bool
ForwardSpam *bool
SpamCheck *SpamCheckSetting
}
type Setting struct {
Enable *bool
}
type SpamCheckSetting struct {
Enable *bool
SpamThreshold int
PostToURL string
}
func (_ *SpamCheckSetting) SetEnable(_ bool) *SpamCheckSetting {
return nil
}
func (_ *SpamCheckSetting) SetPostToURL(_ string) *SpamCheckSetting {
return nil
}
func (_ *SpamCheckSetting) SetSpamThreshold(_ int) *SpamCheckSetting {
return nil
}
type SubscriptionTrackingSetting struct {
Enable *bool
Text string
Html string
SubstitutionTag string
}
func (_ *SubscriptionTrackingSetting) SetEnable(_ bool) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetHTML(_ string) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetSubstitutionTag(_ string) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetText(_ string) *SubscriptionTrackingSetting {
return nil
}
type TrackingSettings struct {
ClickTracking *ClickTrackingSetting
OpenTracking *OpenTrackingSetting
SubscriptionTracking *SubscriptionTrackingSetting
GoogleAnalytics *GaSetting
BCC *BccSetting
BypassListManagement *Setting
Footer *FooterSetting
SandboxMode *SandboxModeSetting
}
func (_ *TrackingSettings) SetClickTracking(_ *ClickTrackingSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetGoogleAnalytics(_ *GaSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetOpenTracking(_ *OpenTrackingSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetSubscriptionTracking(_ *SubscriptionTrackingSetting) *TrackingSettings {
return nil
}

View File

@@ -0,0 +1,3 @@
# github.com/sendgrid/sendgrid-go v3.5.0+incompatible
## explicit
github.com/sendgrid/sendgrid-go

View File

@@ -0,0 +1,9 @@
| mail.go:16:56:16:77 | type conversion |
| mail.go:22:24:22:37 | untrustedInput |
| mail.go:29:32:29:36 | alert |
| mail.go:29:43:29:47 | alert |
| mail.go:29:50:29:54 | alert |
| mail.go:32:46:32:50 | alert |
| mail.go:36:47:36:51 | alert |
| mail.go:37:47:37:51 | alert |
| mail.go:40:35:40:39 | alert |

View File

@@ -0,0 +1,4 @@
import go
from MailData f
select f

View File

@@ -0,0 +1,8 @@
module main
go 1.14
require (
github.com/sendgrid/sendgrid-go v3.5.0+incompatible
github.com/stretchr/testify v1.5.1 // indirect
)

View File

@@ -0,0 +1,42 @@
package main
//go:generate depstubber -vendor github.com/sendgrid/sendgrid-go/helpers/mail "" NewEmail,NewSingleEmail,NewContent,NewV3Mail,NewV3MailInit
import (
"io"
"net/smtp"
sendgrid "github.com/sendgrid/sendgrid-go/helpers/mail"
)
func main() {
untrustedInput := "test"
// Not OK - 1 alert
smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(untrustedInput))
s, _ := smtp.Dial("test.test")
write, _ := s.Data()
// Not OK - 1 alert
io.WriteString(write, untrustedInput)
from := sendgrid.NewEmail("from", "from@from.com")
to := sendgrid.NewEmail("to", "to@to.com")
alert := "sub"
// Not OK - 3 alerts
sendgrid.NewSingleEmail(from, alert, to, alert, alert)
// Not OK - 1 alert
content := sendgrid.NewContent("text/html", alert)
v := sendgrid.NewV3Mail()
v.AddContent(content)
content2 := sendgrid.NewContent("text/html", alert)
content3 := sendgrid.NewContent("text/html", alert)
// Not OK - 3 alerts
v = sendgrid.NewV3MailInit(from, alert, to, content2, content3)
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2019 Twilio SendGrid, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,391 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/sendgrid/sendgrid-go/helpers/mail, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/sendgrid/sendgrid-go/helpers/mail (exports: ; functions: NewEmail,NewSingleEmail,NewContent,NewV3Mail,NewV3MailInit)
// Package mail is a stub of github.com/sendgrid/sendgrid-go/helpers/mail, generated by depstubber.
package mail
import ()
type Asm struct {
GroupID int
GroupsToDisplay []int
}
func (_ *Asm) AddGroupsToDisplay(_ ...int) *Asm {
return nil
}
func (_ *Asm) SetGroupID(_ int) *Asm {
return nil
}
type Attachment struct {
Content string
Type string
Name string
Filename string
Disposition string
ContentID string
}
func (_ *Attachment) SetContent(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetContentID(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetDisposition(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetFilename(_ string) *Attachment {
return nil
}
func (_ *Attachment) SetType(_ string) *Attachment {
return nil
}
type BccSetting struct {
Enable *bool
Email string
}
func (_ *BccSetting) SetEmail(_ string) *BccSetting {
return nil
}
func (_ *BccSetting) SetEnable(_ bool) *BccSetting {
return nil
}
type ClickTrackingSetting struct {
Enable *bool
EnableText *bool
}
func (_ *ClickTrackingSetting) SetEnable(_ bool) *ClickTrackingSetting {
return nil
}
func (_ *ClickTrackingSetting) SetEnableText(_ bool) *ClickTrackingSetting {
return nil
}
type Content struct {
Type string
Value string
}
type Email struct {
Name string
Address string
}
type FooterSetting struct {
Enable *bool
Text string
Html string
}
func (_ *FooterSetting) SetEnable(_ bool) *FooterSetting {
return nil
}
func (_ *FooterSetting) SetHTML(_ string) *FooterSetting {
return nil
}
func (_ *FooterSetting) SetText(_ string) *FooterSetting {
return nil
}
type GaSetting struct {
Enable *bool
CampaignSource string
CampaignTerm string
CampaignContent string
CampaignName string
CampaignMedium string
}
func (_ *GaSetting) SetCampaignContent(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignMedium(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignName(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignSource(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetCampaignTerm(_ string) *GaSetting {
return nil
}
func (_ *GaSetting) SetEnable(_ bool) *GaSetting {
return nil
}
type MailSettings struct {
BCC *BccSetting
BypassListManagement *Setting
Footer *FooterSetting
SandboxMode *Setting
SpamCheckSetting *SpamCheckSetting
}
func (_ *MailSettings) SetBCC(_ *BccSetting) *MailSettings {
return nil
}
func (_ *MailSettings) SetBypassListManagement(_ *Setting) *MailSettings {
return nil
}
func (_ *MailSettings) SetFooter(_ *FooterSetting) *MailSettings {
return nil
}
func (_ *MailSettings) SetSandboxMode(_ *Setting) *MailSettings {
return nil
}
func (_ *MailSettings) SetSpamCheckSettings(_ *SpamCheckSetting) *MailSettings {
return nil
}
func NewContent(_ string, _ string) *Content {
return nil
}
func NewEmail(_ string, _ string) *Email {
return nil
}
func NewSingleEmail(_ *Email, _ string, _ *Email, _ string, _ string) *SGMailV3 {
return nil
}
func NewV3Mail() *SGMailV3 {
return nil
}
func NewV3MailInit(_ *Email, _ string, _ *Email, _ ...*Content) *SGMailV3 {
return nil
}
type OpenTrackingSetting struct {
Enable *bool
SubstitutionTag string
}
func (_ *OpenTrackingSetting) SetEnable(_ bool) *OpenTrackingSetting {
return nil
}
func (_ *OpenTrackingSetting) SetSubstitutionTag(_ string) *OpenTrackingSetting {
return nil
}
type Personalization struct {
To []*Email
CC []*Email
BCC []*Email
Subject string
Headers map[string]string
Substitutions map[string]string
CustomArgs map[string]string
DynamicTemplateData map[string]interface{}
Categories []string
SendAt int
}
func (_ *Personalization) AddBCCs(_ ...*Email) {}
func (_ *Personalization) AddCCs(_ ...*Email) {}
func (_ *Personalization) AddTos(_ ...*Email) {}
func (_ *Personalization) SetCustomArg(_ string, _ string) {}
func (_ *Personalization) SetDynamicTemplateData(_ string, _ interface{}) {}
func (_ *Personalization) SetHeader(_ string, _ string) {}
func (_ *Personalization) SetSendAt(_ int) {}
func (_ *Personalization) SetSubstitution(_ string, _ string) {}
type SGMailV3 struct {
From *Email
Subject string
Personalizations []*Personalization
Content []*Content
Attachments []*Attachment
TemplateID string
Sections map[string]string
Headers map[string]string
Categories []string
CustomArgs map[string]string
SendAt int
BatchID string
Asm *Asm
IPPoolID string
MailSettings *MailSettings
TrackingSettings *TrackingSettings
ReplyTo *Email
}
func (_ *SGMailV3) AddAttachment(_ ...*Attachment) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddCategories(_ ...string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddContent(_ ...*Content) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddPersonalizations(_ ...*Personalization) *SGMailV3 {
return nil
}
func (_ *SGMailV3) AddSection(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetASM(_ *Asm) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetBatchID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetCustomArg(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetFrom(_ *Email) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetHeader(_ string, _ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetIPPoolID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetMailSettings(_ *MailSettings) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetReplyTo(_ *Email) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetSendAt(_ int) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetTemplateID(_ string) *SGMailV3 {
return nil
}
func (_ *SGMailV3) SetTrackingSettings(_ *TrackingSettings) *SGMailV3 {
return nil
}
type SandboxModeSetting struct {
Enable *bool
ForwardSpam *bool
SpamCheck *SpamCheckSetting
}
type Setting struct {
Enable *bool
}
type SpamCheckSetting struct {
Enable *bool
SpamThreshold int
PostToURL string
}
func (_ *SpamCheckSetting) SetEnable(_ bool) *SpamCheckSetting {
return nil
}
func (_ *SpamCheckSetting) SetPostToURL(_ string) *SpamCheckSetting {
return nil
}
func (_ *SpamCheckSetting) SetSpamThreshold(_ int) *SpamCheckSetting {
return nil
}
type SubscriptionTrackingSetting struct {
Enable *bool
Text string
Html string
SubstitutionTag string
}
func (_ *SubscriptionTrackingSetting) SetEnable(_ bool) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetHTML(_ string) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetSubstitutionTag(_ string) *SubscriptionTrackingSetting {
return nil
}
func (_ *SubscriptionTrackingSetting) SetText(_ string) *SubscriptionTrackingSetting {
return nil
}
type TrackingSettings struct {
ClickTracking *ClickTrackingSetting
OpenTracking *OpenTrackingSetting
SubscriptionTracking *SubscriptionTrackingSetting
GoogleAnalytics *GaSetting
BCC *BccSetting
BypassListManagement *Setting
Footer *FooterSetting
SandboxMode *SandboxModeSetting
}
func (_ *TrackingSettings) SetClickTracking(_ *ClickTrackingSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetGoogleAnalytics(_ *GaSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetOpenTracking(_ *OpenTrackingSetting) *TrackingSettings {
return nil
}
func (_ *TrackingSettings) SetSubscriptionTracking(_ *SubscriptionTrackingSetting) *TrackingSettings {
return nil
}

View File

@@ -0,0 +1,6 @@
# github.com/sendgrid/sendgrid-go v3.5.0+incompatible
## explicit
github.com/sendgrid/sendgrid-go
# github.com/stretchr/testify v1.5.1
## explicit
github.com/stretchr/testify