High Severity
Brand impersonation: DocuSign
Description
Attack impersonating a DocuSign request for signature.
Sublime Security
Created Aug 17th, 2023 • Last updated May 21st, 2025
Feed Source
Sublime Core Feed
Source
type.inbound
and (
// orgs can have docusign.company.com
strings.ilike(sender.email.email, '*docusign.net*', '*docusign.com*')
// if the above is true, you'll see a "via Docusign"
or strings.ilike(sender.display_name, '*docusign*')
// detects 1 character variations,
// such as DocuSlgn (with an "L" instead of an "I")
or strings.ilevenshtein(sender.display_name, "docusign") == 1
or strings.ilike(sender.display_name, "*docuonline*", "*via *signature*")
or (
strings.istarts_with(body.html.inner_text, "docusign")
and not strings.istarts_with(body.current_thread.text, "docusign")
)
// docusign is found in current thread AND contains docusign wording within current_thread or subject
or (
regex.icontains(body.current_thread.text, '\bdocu.?sign\b')
and (
// additional context from body.current_thread.text
strings.istarts_with(body.current_thread.text, "DOCUSIGN\n", )
or regex.icontains(body.current_thread.text,
'You have received a ([^\s]+\s)?document',
)
or strings.icontains(body.current_thread.text,
'a document to review and sign',
)
or strings.icontains(body.current_thread.text,
'A document is available for you',
)
or strings.icontains(body.current_thread.text,
'a document ready for you',
)
or strings.icontains(body.current_thread.text,
'This email contains a secure link to DocuSign'
)
or strings.icontains(body.current_thread.text,
'All parties have completed with Docusign'
)
or strings.icontains(body.current_thread.text,
'the signing of this document has been completed'
)
or strings.icontains(body.current_thread.text,
'Please use the link above to Docusign'
)
or strings.icontains(body.current_thread.text, 'Review on Docusign')
or strings.icontains(body.current_thread.text, 'Completed with Docusign')
or strings.icontains(body.current_thread.text, 'Completed on Docusign')
or strings.icontains(body.current_thread.text, 'Complete with Docusign')
or strings.icontains(body.current_thread.text,
'please review and complete with DocuSign'
)
or strings.icontains(body.current_thread.text,
'We appreciate you choosing DocuSign'
)
or strings.icontains(body.current_thread.text,
'A document has been sent to you for'
)
or strings.icontains(body.current_thread.text, 'Please Sign docusign')
or strings.icontains(body.current_thread.text, 'This email was sent via DocuSign')
or strings.icontains(body.current_thread.text, 'This email was sent to you via DocuSign')
or strings.icontains(body.current_thread.text, 'This message was sent via DocuSign')
or strings.icontains(body.current_thread.text, 'This message was sent to you via DocuSign')
or strings.icontains(body.current_thread.text, 'review via DocuSign Electronic Signature')
or strings.icontains(body.current_thread.text, 'sent to you by DocuSign')
or strings.icontains(body.current_thread.text, 'Processed by DocuSign')
or strings.icontains(body.current_thread.text,
'Please read and sign the document'
)
or strings.icontains(body.current_thread.text,
'Please kindly review and sign the '
)
or strings.icontains(body.current_thread.text,
'Your document is pending review and signature'
)
or strings.icontains(body.current_thread.text,
'pending document for your signature'
)
or strings.icontains(body.current_thread.text,
'your review and signature'
)
or strings.icontains(body.current_thread.text, 'a pending document for')
or strings.icontains(body.current_thread.text, 'Your document is ready')
or strings.icontains(body.current_thread.text,
'This email is automatically generated by DocuSign'
)
or strings.icontains(body.current_thread.text,
'Your document has been completed'
)
// docusign is "near" review and sign or sign and return
or regex.icontains(body.current_thread.text,
'Review\s*(?:and\s*|&\s*)Sign.{0,40}docusign',
'docusign.{0,40}Review\s*(?:and\s*|&\s*)Sign',
'Sign\s*(?:and\s*|&\s*)Return.{0,40}docusign',
'Sign\s*(?:and\s*|&\s*)Return.docusign.{0,40}'
)
// additional context from subject.subject
or strings.icontains(subject.subject, 'complete with docusign')
or strings.icontains(subject.subject, 'signature request')
or regex.icontains(subject.subject, 'Review\s*(?:and\s*|&\s*)Sign')
or regex.icontains(subject.subject, 'Sign\s*(?:and\s*|&\s*)Return')
or strings.icontains(subject.subject, 'Please Docusign')
or strings.icontains(subject.subject, 'Docusign has sent')
)
)
or (
// negate replies/forwards which involve a legit docusign message-id format
not any(headers.references,
strings.iends_with(., 'docusign.net')
and regex.imatch(., '[0-9a-f]{32}@(?:[^\.]+\.)?docusign.net')
)
and (
(
sender.display_name is not null
and regex.icontains(sender.display_name, '\bdocu\b')
and strings.icontains(sender.display_name, 'sign')
)
or (
subject.subject is not null
and regex.icontains(subject.subject, '\bdocu\b')
and strings.icontains(subject.subject, 'sign')
)
or (
(
regex.icontains(body.html.raw,
'Powered by.{0,6}(?:\s*<\/?[^\>]+\>\s*)+<img[^\>]+(?:src="https:\/\/docucdn-a\.akamaihd\.net\/[^\"]+email-logo.png"|alt="DocuSign")'
)
or regex.icontains(body.current_thread.text, 'Powered by\s*DocuSign')
)
// limit it to where the powered by is within the current thread
and strings.icontains(body.current_thread.text, 'Powered by')
)
// footer disclaimers
or strings.icontains(body.current_thread.text,
'using the Docusign Electronic Signature Service'
)
or strings.icontains(body.current_thread.text,
'who uses the DocuSign Electronic Signature Service'
)
or strings.icontains(body.current_thread.text,
'Thank you for choosing DocuSign'
)
or (
(
strings.icontains(body.current_thread.text,
'Alternate Signing Method'
)
or strings.icontains(body.current_thread.text, 'Alternative Access')
)
and regex.icontains(body.current_thread.text,
'(?:Click|Select) ''Access Documents'', and enter '
)
)
or (
strings.icontains(body.current_thread.text,
'Please do not share this email, link, or access code with others'
)
and not sender.email.domain.root_domain in (
"insuresign.com",
"clixsign.com",
"esignlive.com",
"clickcontracts.com",
"sadq.sa",
"vasion.com",
"chubb.com", // insurance company
)
)
or (
strings.icontains(body.current_thread.text, 'Docusign provides a ')
and strings.icontains(body.current_thread.text,
'solution for Digital Transaction Management'
)
)
or strings.icontains(body.current_thread.text,
'a secure link to DocuSign'
)
// footer links
or (
length(filter(body.links,
(
.href_url.domain.domain == "support.docusign.com"
and strings.contains(.href_url.path, '/articles/')
)
or .href_url.domain.domain == "community.docusign.com"
or .href_url.domain.domain == "protect.docusign.com"
or .href_url.domain.domain == "app.esign.docusign.com"
)
) >= 2
// and the display_text for these links are within the current thread
and (
strings.icontains(body.current_thread.text, 'Declining to sign')
or strings.icontains(body.current_thread.text,
'Managing notifications'
)
or strings.icontains(body.current_thread.text,
'How to Sign a Document'
)
or strings.icontains(body.current_thread.text,
'Docusign Support Center'
)
or strings.icontains(body.current_thread.text, 'Report this email')
or strings.icontains(body.current_thread.text, 'Docusign Community')
or strings.icontains(body.current_thread.text,
'Connect with our support team'
)
or strings.icontains(body.current_thread.text, 'Unsubscribe')
or strings.icontains(body.current_thread.text, 'Manage Preferences')
)
)
)
)
or (
(
regex.icontains(body.html.raw,
'<font size="?[0-9]"?[^\>]*>DocuSign</font>'
)
or regex.icontains(body.html.raw, '\nDocu(?:<[^\>]+>\s*)+Sign<')
or regex.icontains(body.html.raw,
'<span[^>]*style="[^"]*">Docu.?Sign<\/span>'
)
or any(html.xpath(body.html, '//h1').nodes,
regex.icontains(.display_text, 'Docu.?Sign')
)
or regex.icontains(body.html.raw,
'<span[^>]*style="[^"]*">(Docu|D(?:ocu?)?)<\/span>(?:<[^\>]+\>){0,2}<span[^>]*style="[^"]*">(Sign|S(?:ign?)?)<\/span>'
)
// any bold text contains docusign
or any(html.xpath(body.html, '//strong').nodes,
regex.imatch(.display_text, 'Docu.?Sign')
)
// title starts with Docusign
or any(html.xpath(body.html, '//title').nodes,
regex.icontains(.display_text, '^docu.?sign')
)
// a div with a class of logo contains the display text of docusign
or any(html.xpath(body.html, '//div[@class="logo"]').nodes,
strings.icontains(.display_text, 'Docusign')
)
// image contains an alt text of docusign
or any(html.xpath(body.html, '//img/@alt').nodes, .raw =~ "docusign")
// Basic variations with HTML encoding
// use of regex extract allows
or any(regex.iextract(body.html.raw,
'(?:D|D|D)(?:&#?[0-9a-fA-F]{2,6};|\s|o|о|о|о)(?:&#?[0-9a-fA-F]{2,6};|\s|c|с|с|с)u(?:&#?[0-9a-fA-F]{2,6};|\s)?S(?:&#?[0-9a-fA-F]{2,6};|\s|i|і|і|і)(?:&#?[0-9a-fA-F]{2,6};|\s|g|ɡ|ɡ|ɡ)(?:n|n|n)'
),
.full_match !~ "docusign"
)
// Common homograph patterns
or any(regex.iextract(body.html.raw,
'(?:[DⅮᎠᗞᗡ𝐃𝐷𝑫𝒟𝓓𝔇𝔻𝕯𝖣])\s*(?:[oοоօ0Ооʘ◯])\s*(?:[cсçҫ¢ϲС])\s*u\s*(?:[sѕЅ5$])\s*(?:[iіІ1l!|])\s*(?:[gǵġģ9ɡ])\s*(?:[nոռℼη𝐧𝑛𝒏𝓃𝓷𝔫𝕟𝖓])'
),
.full_match !~ "docusign"
)
// Look for HTML entities for each letter in sequence
or any(regex.iextract(body.html.raw,
'(?:D|D|D)(?:o|о|o|o|о|о|ο|ο)(?:c|с|c|c|с|с|ϲ|ç|g|ĉ|ĉ)(?:u|u|u|у|у|υ|υ)(?:s|s|s|ѕ|ѕ)(?:i|і|i|i|і|і|ı|ı)(?:g|g|g|ɡ|ɡ|ğ|ğ)(?:n|n|n|н|н|η|η)'
),
.full_match !~ "docusign"
)
// Handle repeated HTML entities and variation selectors (using Unicode class)
or any(regex.iextract(body.html.raw,
'D(?:&#[0-9]{1,7};)*\p{Mn}*o(?:&#[0-9]{1,7};)*\p{Mn}*c(?:&#[0-9]{1,7};)*\p{Mn}*u(?:&#[0-9]{1,7};)*\p{Mn}*[Ss](?:&#[0-9]{1,7};)*\p{Mn}*i(?:&#[0-9]{1,7};)*\p{Mn}*g(?:&#[0-9]{1,7};)*\p{Mn}*n'
),
.full_match !~ "docusign"
)
)
and (
regex.icontains(body.html.raw,
'b(?:ackground(?:-color)?|g?color):\s*rgb\(30,\s*76,\s*161\)',
'b(?:ackground(?:-color)?|g?color):\s*rgb\(61,\s*170,\s*73\)'
)
or regex.icontains(body.html.raw,
'<(?:div|td|table)[^>]*b(?:ackground(?:-color)?|g?color)(?::|=)\s*\"?#1e4ca1[^>]*>',
)
or regex.icontains(body.html.raw,
'b(?:ackground(?:-color)?|g?color)(?::|=)\s*\"?#(?:214e9f|3260a7|0056b3|1e4ca1|214395|325bb8|3c60ad)'
)
)
)
)
// identifies the main CTA in the email, eg "Review now" or "Review document"
// this should always be a known docusign domain,
// even with branded docusign subdomains
and (
any(
// filter links that match docusign wording
filter(body.links,
// we've observed invisible characters in the display name
// such as U+034f(look carefully): "Revi͏ew Now"
(
strings.ilevenshtein(.display_text, "Review Now") <= 3
or strings.ilevenshtein(.display_text, "Review and Sign") <= 3
or (
strings.icontains(.display_text, "Review")
// negate benign uses of the "review" term
and not (
strings.icontains(.display_text, "Review Us")
or strings.icontains(.display_text, "leave us a review")
or regex.icontains(.display_text, '\bReviews\b')
// don't match microsoft quarantine messages
or (
strings.icontains(.display_text, "Review Message")
and (
.href_url.domain.domain == "security.microsoft.com"
and .href_url.path == "/quarantine"
)
)
)
)
or strings.icontains(.display_text, "document")
or strings.icontains(.display_text, "docusign")
or strings.icontains(.display_text, "Review on Docusign")
or (
strings.icontains(.display_text, "Sign")
and strings.icontains(.display_text, "Now")
)
)
),
// ensure those links aren't legit
not .href_url.domain.root_domain in (
"docusign.com",
"docusign.net",
'docusign.co.uk',
'docusign.com.br',
'docusign.fr',
// other e-signature companies which use simliar wording
"insuresign.com",
"clixsign.com",
"esignlive.com",
"clickcontracts.com",
"adobesign.com",
"hellosign.com",
)
and not (
.href_url.domain.root_domain == "mimecastprotect.com"
and (
.href_url.query_params is not null
and regex.icontains(.href_url.query_params,
'domain=(?:\w+\.)?docusign.(?:net|com|co\.uk|com\.br|fr)',
// other e-signature companies
'domain=(?:\w+\.)?(?:insuresign\.com|clixsign\.com|esignlive\.com|clickcontracts\.com|adobesign\.com|hellosign\.com)'
)
)
)
)
// Suspicious attachment
or any(attachments,
(
.file_extension in~ ("html", "htm", "shtml", "dhtml")
or .file_extension in~ $file_extensions_common_archives
or .file_type == "html"
or .content_type == "text/html"
)
and 1 of (
(
regex.icontains(file.parse_html(.).raw, '\s{0,}<script.*')
and regex.icontains(file.parse_html(.).raw, "</script>")
),
strings.ilike(file.parse_html(.).raw,
"*createElement*",
"*appendChild*",
"*createObjectURL*"
),
strings.icount(file.parse_html(.).raw, "/*") > 10,
any($free_subdomain_hosts, strings.icontains(..file_name, .))
)
)
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
coalesce(sender.email.domain.root_domain in $high_trust_sender_root_domains
and not headers.auth_summary.dmarc.pass,
false
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
// negation for messages traversing docusign.net
// happens with custom sender domains
and not (
any(headers.domains, .root_domain == "docusign.net")
and headers.auth_summary.spf.pass
and headers.auth_summary.dmarc.pass
)
// adding negation for messages originating from docusigns api
// and the sender.display.name contains "via"
and not (
any(headers.hops,
any(.fields,
.name == "X-Api-Host" and strings.ends_with(.value, "docusign.net")
)
)
and strings.contains(sender.display_name, "via")
)
Playground
Test against your own EMLs or sample data.