Detection rules › Sublime MQL

Sublime MQL rules: fake

Brand impersonation: Canada Revenue Agency

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

Detects messages impersonating the Canada Revenue Agency (CRA) in English or French that contain credential theft indicators. The rule identifies senders claiming to be CRA through display names or subject line references, uses natural language understanding to detect credential theft intent, and excludes legitimate senders with proper authentication.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesImpersonation: Brand, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule body

type.inbound
and (
  // cred theft
  any(ml.nlu_classifier(body.current_thread.text).intents,
      .name == "cred_theft" and .confidence != 'low'
  )
  // contains a link not to the domain "canda.ca"
  or any(body.current_thread.links,
         .href_url.domain.root_domain not in ('canada.ca')
  )
  // contains any attachment that isn't an image
  or any(attachments, .file_type not in $file_types_images)
)

// sender claims to be CRA
and (
  strings.icontains(sender.display_name,
                    'canada revenue agency',
                    'agence du revenu du canada'
  )
  or (
    regex.icontains(sender.display_name, '\bcra\b')
    // limit it to samples that mention CRA by name in the body
    and regex.icontains(body.current_thread.text,
                        '(?:canada revenue|revenu du canada)'
    )
  )
)

// not a high trust or cra-arc.gc.ca
and not (
  (
    // negate highly trusted sender domains
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    // negate legit senders from legitimate cra
    or sender.email.domain.root_domain == "cra-arc.gc.ca"
  )
  // enforce authentication
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection logic

Scope: inbound message.

Detects messages impersonating the Canada Revenue Agency (CRA) in English or French that contain credential theft indicators. The rule identifies senders claiming to be CRA through display names or subject line references, uses natural language understanding to detect credential theft intent, and excludes legitimate senders with proper authentication.

  1. inbound message
  2. any of:
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence is not 'low'
    • any of body.current_thread.links where:
      • .href_url.domain.root_domain not in ('canada.ca')
    • any of attachments where:
      • .file_type not in $file_types_images
  3. any of:
    • sender.display_name contains any of 2 patterns
      • canada revenue agency
      • agence du revenu du canada
    • all of:
      • sender.display_name matches '\\bcra\\b'
      • body.current_thread.text matches '(?:canada revenue|revenu du canada)'
  4. not:
    • all of:
      • any of:
        • sender.email.domain.root_domain in $high_trust_sender_root_domains
        • sender.email.domain.root_domain is 'cra-arc.gc.ca'
      • coalesce(headers.auth_summary.dmarc.pass)

Inspects: attachments[].file_type, body.current_thread.links, body.current_thread.links[].href_url.domain.root_domain, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.display_name, sender.email.domain.root_domain, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.icontains. Reference lists: $file_types_images, $high_trust_sender_root_domains.

Indicators matched (5)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
strings.icontainssubstringcanada revenue agency
strings.icontainssubstringagence du revenu du canada
regex.icontainsregex\bcra\b
regex.icontainsregex(?:canada revenue|revenu du canada)

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(body.current_thread.links)
      not
        body.current_thread.links.href_url.domain.root_domain eq "canada.ca"
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence ne "low"
        ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
    any(attachments)
       macro "attachments[].file_type not in file_types_images"
  not
    and
      or
        sender.email.domain.root_domain eq "cra-arc.gc.ca"
         macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
  or
    and
      body.current_thread.text regex_match "(?:canada revenue|revenu du canada)"
      sender.display_name regex_match "\\bcra\\b"
    sender.display_name contains "agence du revenu du canada"
    sender.display_name contains "canada revenue agency"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
sender.email.domain.root_domaineqcra-arc.gc.caexcludes:sender.email.domain.root_domain field:"sender.email.domain.root_domain" value:"cra-arc.gc.ca"

Indicators

These rows show field, operator, and value matches.

Fake request for tax preparation

#
Severity
high
Type
rule
Source
github.com/sublime-security/sublime-rules

Unknown sender requesting assistance with tax preparation. This is associated with known threat actor activity, TA576.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud, Malware/Ransomware
Tactics and techniquesSocial engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.links
  • headers
  • headers.reply_to
  • headers.return_path
  • sender.email
  • subject
  • type

Rule body

type.inbound
and length(body.current_thread.text) < 1250
and any(beta.ml_topic(body.current_thread.text).topics,
        .name == "Financial Communications"
)
// there are no links, all the links are to aka.ms, or an extraction from a warning banner that match the senders domain
and (
  length(body.links) == 0
  or length(filter(body.links,
                   (
                     .display_text is null
                     and .display_url.url == sender.email.domain.root_domain
                   )
                   or .href_url.domain.domain == "aka.ms"
                   or network.whois(.display_url.domain).days_old < 30
            )
  ) == length(body.links)
)
and length(attachments) == 0
and (strings.ilike(subject.subject, "*tax*") or length(subject.subject) < 15)
and strings.icontains(body.current_thread.text, "tax")
and (
  strings.like(body.current_thread.text,
               "*return*",
               "*record*",
               "*CPA*",
               "*filing*",
               "*extension*"
  )
  or strings.ilike(body.current_thread.text,
                   "*tax preparer*",
                   "*tax*processing*"
  )
)
and (
  strings.ilike(body.current_thread.text,
                "*necessary documents*",
                "*required documents*",
                "*paperwork*",
                "*in search of*",
                "*tax service*",
                "*professional help*",
                "*prepare*tax return*",
                "*service*tax return*",
                "*seeking*tax preparer*",
                "*assist*processing*tax*",
                "*schedule*call*",
                "*zoom meeting*",
                "*discuss*fees*",
                "*W2*",
                "*CPA*"
  )
  // suspicious patterns
  or (
    strings.icontains(body.current_thread.text, sender.display_name)
    and 2 of (
      (
        length(headers.reply_to) > 0
        and all(headers.reply_to,
                .email.domain.root_domain != sender.email.domain.root_domain
        )
      ),
      (
        headers.return_path.email is not null
        and headers.return_path.email != sender.email.email
      ),
      headers.return_path.domain.root_domain in ("amazonses.com")
    )
  )
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

Unknown sender requesting assistance with tax preparation. This is associated with known threat actor activity, TA576.

  1. inbound message
  2. length(body.current_thread.text) < 1250
  3. any of beta.ml_topic(body.current_thread.text).topics where:
    • .name is 'Financial Communications'
  4. any of:
    • length(body.links) is 0
    • length(filter(body.links, .display_text is null and .display_url.url == sender.email.domain.root_domain or .href_url.domain.domain == 'aka.ms' or network.whois(.display_url.domain).days_old < 30)) is length(body.links)
  5. length(attachments) is 0
  6. any of:
    • subject.subject matches '*tax*'
    • length(subject.subject) < 15
  7. body.current_thread.text contains 'tax'
  8. any of:
    • body.current_thread.text matches any of 5 patterns
      • *return*
      • *record*
      • *CPA*
      • *filing*
      • *extension*
    • body.current_thread.text matches any of 2 patterns
      • *tax preparer*
      • *tax*processing*
  9. any of:
    • body.current_thread.text matches any of 15 patterns
      • *necessary documents*
      • *required documents*
      • *paperwork*
      • *in search of*
      • *tax service*
      • *professional help*
      • *prepare*tax return*
      • *service*tax return*
      • *seeking*tax preparer*
      • *assist*processing*tax*
      • *schedule*call*
      • *zoom meeting*
      • *discuss*fees*
      • *W2*
      • *CPA*
    • all of:
      • strings.icontains(body.current_thread.text)
      • at least 2 of:
        • all of:
          • length(headers.reply_to) > 0
          • all of headers.reply_to where:
            • .email.domain.root_domain is not sender.email.domain.root_domain
        • all of:
          • headers.return_path.email is set
          • headers.return_path.email is not sender.email.email
        • headers.return_path.domain.root_domain in ('amazonses.com')
  10. any of:
    • all of:
      • profile.by_sender().prevalence in ('new', 'outlier')
      • not:
        • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  11. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].display_url.domain, body.links[].display_url.url, body.links[].href_url.domain.domain, headers.reply_to, headers.reply_to[].email.domain.root_domain, headers.return_path.domain.root_domain, headers.return_path.email, sender.display_name, sender.email.domain.root_domain, sender.email.email, subject.subject, type.inbound. Sensors: beta.ml_topic, network.whois, profile.by_sender, strings.icontains, strings.ilike, strings.like.

Indicators matched (27)

FieldMatchValue
beta.ml_topic(body.current_thread.text).topics[].nameequalsFinancial Communications
body.links[].href_url.domain.domainequalsaka.ms
strings.ilikesubstring*tax*
strings.icontainssubstringtax
strings.likesubstring*return*
strings.likesubstring*record*
strings.likesubstring*CPA*
strings.likesubstring*filing*
strings.likesubstring*extension*
strings.ilikesubstring*tax preparer*
strings.ilikesubstring*tax*processing*
strings.ilikesubstring*necessary documents*
15 more
strings.ilikesubstring*required documents*
strings.ilikesubstring*paperwork*
strings.ilikesubstring*in search of*
strings.ilikesubstring*tax service*
strings.ilikesubstring*professional help*
strings.ilikesubstring*prepare*tax return*
strings.ilikesubstring*service*tax return*
strings.ilikesubstring*seeking*tax preparer*
strings.ilikesubstring*assist*processing*tax*
strings.ilikesubstring*schedule*call*
strings.ilikesubstring*zoom meeting*
strings.ilikesubstring*discuss*fees*
strings.ilikesubstring*W2*
strings.ilikesubstring*CPA*
headers.return_path.domain.root_domainmemberamazonses.com

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      or
        and
          headers.reply_to length_compare "0"
           macro "all(headers.reply_to)"
        and
          headers.return_path.email cross_field_compare "sender.email.email"
          headers.return_path.email is_not_null
        headers.return_path.domain.root_domain eq "amazonses.com"
      strings.icontains func_call "strings.icontains(body.current_thread.text)"
    body.current_thread.text match "CPA"
    body.current_thread.text match "W2"
    body.current_thread.text match "in search of"
    body.current_thread.text match "necessary documents"
    body.current_thread.text match "paperwork"
    body.current_thread.text match "professional help"
    body.current_thread.text match "required documents"
    body.current_thread.text match "tax service"
    body.current_thread.text match "zoom meeting"
    body.current_thread.text wildcard "*assist*processing*tax*"
    body.current_thread.text wildcard "*discuss*fees*"
    body.current_thread.text wildcard "*prepare*tax return*"
    body.current_thread.text wildcard "*schedule*call*"
    body.current_thread.text wildcard "*seeking*tax preparer*"
    body.current_thread.text wildcard "*service*tax return*"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (new, outlier)"
  any(beta.ml_topic(body.current_thread.text).topics)
    beta.ml_topic(body.current_thread.text).topics.name eq "Financial Communications"
  or
    body.current_thread.text match "CPA"
    body.current_thread.text match "extension"
    body.current_thread.text match "filing"
    body.current_thread.text match "record"
    body.current_thread.text match "return"
    body.current_thread.text match "tax preparer"
    body.current_thread.text wildcard "*tax*processing*"
  or
    body.links length_compare "0"
    length func_call "length(filter(body.links, .display_text is null and .display_url.url == sender.email.domain.root_domain or .href_url.domain.domain == 'aka.ms' or network.whois(.display_url.domain).days_old < 30)) == length(body.links)"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  or
    subject.subject length_compare "15"
    subject.subject match "tax"
  attachments length_compare "0"
  body.current_thread.text contains "tax"
  body.current_thread.text length_compare "1250"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • tax
field:"body.current_thread.text" kind:contains value:"tax"
body.current_thread.textwildcard
  • *CPA*
  • *W2*
  • *assist*processing*tax*
  • *discuss*fees*
  • *extension*
  • *filing*
  • *in search of*
  • *necessary documents*
  • *paperwork*
  • *prepare*tax return*
  • *professional help*
  • *record*
  • *required documents*
  • *return*
  • *schedule*call*
  • *seeking*tax preparer*
  • *service*tax return*
  • *tax preparer*
  • *tax service*
  • *tax*processing*
  • *zoom meeting*
field:"body.current_thread.text" kind:wildcard
headers.return_path.domain.root_domainin
  • amazonses.com
field:"headers.return_path.domain.root_domain" kind:in value:"amazonses.com"
headers.return_path.emailcross_field_compare
  • sender.email.email transforms: op:ne
field:"headers.return_path.email" kind:cross_field_compare value:"sender.email.email"
headers.return_path.emailis_not_null
  • (no value, null check)
field:"headers.return_path.email" kind:is_not_null
subject.subjectwildcard
  • *tax*
field:"subject.subject" kind:wildcard value:"*tax*"
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Fake scan-to-email message

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

Message resembles an email from a scan-to-email service or device, but does not contain any attachments, instead linking to an unknown domain.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree file host, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.links
  • sender.email
  • subject
  • type

Rule body

type.inbound
and length(attachments) == 0
and 0 < length(body.links) < 3
and strings.ilike(subject.subject, "*message from*")
and (
  (
    strings.ilike(body.current_thread.text, "*scan date*", "*was sent from*")
    and not strings.ilike(body.current_thread.text, "*unmonitored*")
  )
  or (
    //
    // This rule makes use of a beta feature and is subject to change without notice
    // using the beta feature in custom rules is not suggested until it has been formally released
    //
    strings.ilike(beta.ocr(file.message_screenshot()).text,
                  "*scan date*",
                  "*was sent from*"
    )
    and not strings.ilike(beta.ocr(file.message_screenshot()).text,
                          "*unmonitored*"
    )
  )
)
and (
  any(body.links, .href_url.domain.root_domain in~ $free_file_hosts)
  or any(body.links, .display_url.url != .href_url.url)
  or any(body.links, .display_url.url is null)
)
and all(body.links,
        .href_url.domain.domain not in~ $org_domains
        and .href_url.domain.domain not in ("aka.ms")
)
and sender.email.domain.domain not in~ $org_domains
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

Message resembles an email from a scan-to-email service or device, but does not contain any attachments, instead linking to an unknown domain.

  1. inbound message
  2. length(attachments) is 0
  3. all of:
    • length(body.links) > 0
    • length(body.links) < 3
  4. subject.subject matches '*message from*'
  5. any of:
    • all of:
      • body.current_thread.text matches any of 2 patterns
        • *scan date*
        • *was sent from*
      • not:
        • body.current_thread.text matches '*unmonitored*'
    • all of:
      • beta.ocr(file.message_screenshot()).text matches any of 2 patterns
        • *scan date*
        • *was sent from*
      • not:
        • beta.ocr(file.message_screenshot()).text matches '*unmonitored*'
  6. any of:
    • any of body.links where:
      • .href_url.domain.root_domain in $free_file_hosts
    • any of body.links where:
      • .display_url.url is not .href_url.url
    • any of body.links where:
      • .display_url.url is missing
  7. all of body.links where all hold:
    • .href_url.domain.domain not in $org_domains
    • .href_url.domain.domain not in ('aka.ms')
  8. sender.email.domain.domain not in $org_domains
  9. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  10. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.links, body.links[].display_url.url, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, body.links[].href_url.url, sender.email.domain.domain, subject.subject, type.inbound. Sensors: beta.ocr, file.message_screenshot, profile.by_sender, strings.ilike. Reference lists: $free_file_hosts, $org_domains.

Indicators matched (3)

FieldMatchValue
strings.ilikesubstring*message from*
strings.ilikesubstring*scan date*
strings.ilikesubstring*was sent from*

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      or
        beta.ocr(file.message_screenshot()).text match "scan date"
        beta.ocr(file.message_screenshot()).text match "was sent from"
      not
        beta.ocr(file.message_screenshot()).text match "unmonitored"
    and
      or
        body.current_thread.text match "scan date"
        body.current_thread.text match "was sent from"
      not
        body.current_thread.text match "unmonitored"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    any(body.links)
      body.links.display_url.url cross_field_compare "body.links.href_url.url"
    any(body.links)
      body.links.display_url.url is_null
    any(body.links)
       macro "body.links[].href_url.domain.root_domain in free_file_hosts"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  attachments length_compare "0"
  body.links length_compare "0"
  body.links length_compare "3"
  subject.subject match "message from"
  type.inbound eq "true"
   macro "all(body.links)"
   macro "sender.email.domain.domain not in org_domains"

Indicators

These rows show field, operator, and value matches.

Fake thread with suspicious indicators

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

Fake thread contains suspicious indicators, which can lead to BEC, credential phishing, and other undesirable outcomes.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud, Credential Phishing, Spam
Tactics and techniquesEvasion, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • body.links
  • body.plain
  • body.previous_threads
  • headers
  • headers.auth_summary
  • headers.domains
  • headers.hops[0]
  • headers.return_path
  • recipients
  • recipients.to
  • recipients.to[0]
  • sender.email
  • subject
  • type

Rule body

type.inbound
// fake thread check
and (length(headers.references) == 0 or headers.in_reply_to is null)
and (
  subject.is_reply
  or subject.is_forward
  // fake thread, but no indication in the subject line
  // current_thread pulls the recent thread, but the full body contains the fake "original" email
  or (
    not (subject.is_reply or subject.is_forward)
    and any([body.current_thread.text, body.html.display_text, body.plain.raw],
            3 of (
              strings.icontains(., "from:"),
              strings.icontains(., "to:"),
              strings.icontains(., "sent:"),
              strings.icontains(., "date:"),
              strings.icontains(., "cc:"),
              strings.icontains(., "subject:")
            )
    )
    and length(body.current_thread.text) + 100 < length(coalesce(body.html.display_text,
                                                                 body.plain.raw
                                                        )
    )
  )
)

// negating bouncebacks
and not any(attachments,
            .content_type in ("message/delivery-status", "message/rfc822")
)
// negating Google Calendar invites
and (
  (
    headers.return_path.domain.domain is not null
    and headers.return_path.domain.domain != 'calendar-server.bounces.google.com'
  )
  or headers.return_path.domain.domain is null
)
// not mimecast secure message from internal source
and not (
  strings.istarts_with(headers.message_id, '<Mimecast.')
  and strings.iends_with(headers.message_id, '.mimecast.lan>')
  and headers.hops[0].received.server.raw == "relay.mimecast.com"
  and strings.icontains(headers.hops[0].received.source.raw, 'mimecast.lan')
)

// and not solicited
and not profile.by_sender().solicited
and 4 of (
  // language attempting to engage
  (
    any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "request"
    )
    and any(ml.nlu_classifier(body.current_thread.text).entities,
            .name == "financial"
    )
  ),

  // invoicing language
  (
    any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice")
    or any(ml.nlu_classifier(body.current_thread.text).entities,
           .text == "invoice"
    )
  ),

  // urgency request
  any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency"),

  // cred_theft detection
  any(ml.nlu_classifier(body.current_thread.text).intents,
      .name == "cred_theft" and .confidence in~ ("medium", "high")
  ),

  // subject has multiple re: tags and suspicious indicators
  (
    regex.icontains(subject.subject, '\bre:\s+re:')
    and (
      regex.icontains(subject.base,
                      '(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)'
      )
    )
  ),

  // commonly abused sender TLD
  strings.ilike(sender.email.domain.tld, "*.jp"),

  // headers traverse abused TLD
  any(headers.domains, strings.ilike(.tld, "*.jp")),

  // known suspicious pattern in the URL path
  any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')),

  // link display text is in all caps
  any(body.links, regex.match(.display_text, '[A-Z ]+')),

  // link display text contains invisible characters (U+200F)
  any(body.links, strings.contains(.display_text, "\u{200F}")),

  // Low reputation link with display text ending in a document extension
  any(body.links,
      .href_url.domain.root_domain not in $tranco_1m
      and .href_url.domain.valid
      and .href_url.domain.root_domain not in $org_domains
      and .href_url.domain.root_domain not in $high_trust_sender_root_domains
      and (
        any($file_extensions_macros, strings.ends_with(..display_text, .))
        or strings.ends_with(.display_text, 'pdf')
      )
  ),

  // display name contains an email
  regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+'),

  // Sender domain is empty
  sender.email.domain.domain == "",

  // sender domain matches no body domains
  all(body.links,
      .href_url.domain.root_domain != sender.email.domain.root_domain
  ),

  // body contains name of VIP
  (
    any($org_vips, strings.icontains(body.html.inner_text, .display_name))
    or any($org_vips, strings.icontains(body.plain.raw, .display_name))
  ),

  // new body domain
  any(body.links, network.whois(.href_url.domain).days_old < 30),

  // new sender domain
  network.whois(sender.email.domain).days_old < 30,

  // new sender
  profile.by_sender().days_known < 7,

  // excessive whitespace
  (
    regex.icontains(body.html.raw, '((<br\s*/?>\s*){20,}|\n{20,})')
    or regex.icontains(body.html.raw, '(<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}')
    or regex.icontains(body.html.raw,
                       '(<p class=".*?"><span style=".*?"><o:p>&nbsp;</o:p></span></p>\s*){30,}'
    )
    or regex.icontains(body.html.raw, '(<p>&nbsp;</p>\s*){7,}')
    or regex.icontains(body.html.raw, '(<p>&nbsp;</p><br>\s*){7,}')
    or regex.icontains(body.html.raw, '(<p[^>]*>\s*&nbsp;<br>\s*</p>\s*){5,}')
    or regex.icontains(body.html.raw, '(<p[^>]*>&nbsp;</p>\s*){7,}')
  ),

  // body contains recipient SLD
  any(recipients.to,
      strings.icontains(body.current_thread.text, .email.domain.sld)
  ),
  (
    // bec
    any(ml.nlu_classifier(body.current_thread.text).intents,
        .name == "bec" and .confidence != "low"
    )
    // previous thread contains matching domain but mismatch local part in current thread
    and any(body.previous_threads,
            .sender.email.domain.root_domain == recipients.to[0].email.domain.root_domain
            and .sender.email.email != recipients.to[0].email.email
    )
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

Fake thread contains suspicious indicators, which can lead to BEC, credential phishing, and other undesirable outcomes.

  1. inbound message
  2. any of:
    • length(headers.references) is 0
    • headers.in_reply_to is missing
  3. any of:
    • subject.is_reply
    • subject.is_forward
    • all of:
      • none of:
        • subject.is_reply
        • subject.is_forward
      • any of [body.current_thread.text, body.html.display_text, body.plain.raw] where:
        • at least 3 of 6: . contains any of 6 patterns
          • from:
          • to:
          • sent:
          • date:
          • cc:
          • subject:
      • length(body.current_thread.text) + 100 < length(coalesce(body.html.display_text, body.plain.raw))
  4. not:
    • any of attachments where:
      • .content_type in ('message/delivery-status', 'message/rfc822')
  5. any of:
    • all of:
      • headers.return_path.domain.domain is set
      • headers.return_path.domain.domain is not 'calendar-server.bounces.google.com'
    • headers.return_path.domain.domain is missing
  6. not:
    • all of:
      • headers.message_id starts with '<Mimecast.'
      • headers.message_id ends with '.mimecast.lan>'
      • headers.hops[0].received.server.raw is 'relay.mimecast.com'
      • headers.hops[0].received.source.raw contains 'mimecast.lan'
  7. not:
    • profile.by_sender().solicited
  8. at least 4 of:
    • all of:
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .name is 'request'
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .name is 'financial'
    • any of:
      • any of ml.nlu_classifier(body.current_thread.text).tags where:
        • .name is 'invoice'
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .text is 'invoice'
    • any of ml.nlu_classifier(body.current_thread.text).entities where:
      • .name is 'urgency'
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence in ('medium', 'high')
    • all of:
      • subject.subject matches '\\bre:\\s+re:'
      • subject.base matches '(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)'
    • sender.email.domain.tld matches '*.jp'
    • any of headers.domains where:
      • .tld matches '*.jp'
    • any of body.links where:
      • .href_url.path matches '\\/[a-z]{3}\\d[a-z]'
    • any of body.links where:
      • .display_text matches '[A-Z ]+'
    • any of body.links where:
      • .display_text contains '\\u{200F}'
    • any of body.links where all hold:
      • .href_url.domain.root_domain not in $tranco_1m
      • .href_url.domain.valid
      • .href_url.domain.root_domain not in $org_domains
      • .href_url.domain.root_domain not in $high_trust_sender_root_domains
      • any of:
        • any of $file_extensions_macros where:
          • strings.ends_with(.display_text)
        • .display_text ends with 'pdf'
    • sender.display_name matches '[a-z0-9]+@[a-z]+'
    • sender.email.domain.domain is ''
    • all of body.links where:
      • .href_url.domain.root_domain is not sender.email.domain.root_domain
    • any of:
      • any of $org_vips where:
        • strings.icontains(body.html.inner_text)
      • any of $org_vips where:
        • strings.icontains(body.plain.raw)
    • any of body.links where:
      • network.whois(.href_url.domain).days_old < 30
    • network.whois(sender.email.domain).days_old < 30
    • profile.by_sender().days_known < 7
    • body.html.raw matches any of 7 patterns
      • ((<br\s*/?>\s*){20,}|\n{20,})
      • (<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}
      • (<p class=".*?"><span style=".*?"><o:p>&nbsp;</o:p></span></p>\s*){30,}
      • (<p>&nbsp;</p>\s*){7,}
      • (<p>&nbsp;</p><br>\s*){7,}
      • (<p[^>]*>\s*&nbsp;<br>\s*</p>\s*){5,}
      • (<p[^>]*>&nbsp;</p>\s*){7,}
    • any of recipients.to where:
      • strings.icontains(body.current_thread.text)
    • all of:
      • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
        • .name is 'bec'
        • .confidence is not 'low'
      • any of body.previous_threads where all hold:
        • .sender.email.domain.root_domain is recipients.to[0].email.domain.root_domain
        • .sender.email.email is not recipients.to[0].email.email
  9. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  10. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, body.current_thread.text, body.html.display_text, body.html.inner_text, body.html.raw, body.links, body.links[].display_text, body.links[].href_url.domain, body.links[].href_url.domain.root_domain, body.links[].href_url.domain.valid, body.links[].href_url.path, body.plain.raw, body.previous_threads, body.previous_threads[].sender.email.domain.root_domain, body.previous_threads[].sender.email.email, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].tld, headers.hops[0].received.server.raw, headers.hops[0].received.source.raw, headers.in_reply_to, headers.message_id, headers.references, headers.return_path.domain.domain, recipients.to, recipients.to[0].email.domain.root_domain, recipients.to[0].email.email, recipients.to[].email.domain.sld, sender.display_name, sender.email.domain, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.domain.tld, subject.base, subject.is_forward, subject.is_reply, subject.subject, type.inbound. Sensors: ml.nlu_classifier, network.whois, profile.by_sender, regex.contains, regex.icontains, regex.match, strings.contains, strings.ends_with, strings.icontains, strings.iends_with, strings.ilike, strings.istarts_with. Reference lists: $file_extensions_macros, $high_trust_sender_root_domains, $org_domains, $org_vips, $tranco_1m.

Indicators matched (31)

FieldMatchValue
strings.icontainssubstringfrom:
strings.icontainssubstringto:
strings.icontainssubstringsent:
strings.icontainssubstringdate:
strings.icontainssubstringcc:
strings.icontainssubstringsubject:
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsfinancial
ml.nlu_classifier(body.current_thread.text).tags[].nameequalsinvoice
ml.nlu_classifier(body.current_thread.text).entities[].textequalsinvoice
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsurgency
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
19 more
ml.nlu_classifier(body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh
regex.icontainsregex\bre:\s+re:
regex.icontainsregex(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)
strings.ilikesubstring*.jp
regex.matchregex\/[a-z]{3}\d[a-z]
regex.matchregex[A-Z ]+
strings.containssubstring\u{200F}
strings.ends_withsuffixpdf
regex.containsregex[a-z0-9]+@[a-z]+
sender.email.domain.domainequals
regex.icontainsregex((<br\s*/?>\s*){20,}|\n{20,})
regex.icontainsregex(<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}
regex.icontainsregex(<p class=".*?"><span style=".*?"><o:p>&nbsp;</o:p></span></p>\s*){30,}
regex.icontainsregex(<p>&nbsp;</p>\s*){7,}
regex.icontainsregex(<p>&nbsp;</p><br>\s*){7,}
regex.icontainsregex(<p[^>]*>\s*&nbsp;<br>\s*</p>\s*){5,}
regex.icontainsregex(<p[^>]*>&nbsp;</p>\s*){7,}
ml.nlu_classifier(body.current_thread.text).intents[].nameequalsbec

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(body.links)
      and
        or
          any($file_extensions_macros)
            strings.ends_with func_call "strings.ends_with(body.links[].display_text)"
          body.links.display_text ends_with "pdf"
        body.links.href_url.domain.valid eq "true"
         macro "body.links[].href_url.domain.root_domain not in high_trust_sender_root_domains"
         macro "body.links[].href_url.domain.root_domain not in org_domains"
         macro "body.links[].href_url.domain.root_domain not in tranco_1m"
    and
      any(body.previous_threads)
        and
          body.previous_threads.sender.email.domain.root_domain cross_field_compare "recipients.to[0].email.domain.root_domain"
          body.previous_threads.sender.email.email cross_field_compare "recipients.to[0].email.email"
      any(ml.nlu_classifier(body.current_thread.text).intents)
        and
          ml.nlu_classifier(body.current_thread.text).intents.confidence ne "low"
          ml.nlu_classifier(body.current_thread.text).intents.name eq "bec"
    and
      any(ml.nlu_classifier(body.current_thread.text).entities)
        ml.nlu_classifier(body.current_thread.text).entities.name eq "financial"
      any(ml.nlu_classifier(body.current_thread.text).entities)
        ml.nlu_classifier(body.current_thread.text).entities.name eq "request"
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence in ["high", "medium"]
        ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
    any(body.links)
      body.links.display_text contains "\\u{200F}"
    any(body.links)
      body.links.display_text regex_match "[A-Z ]+"
    any(body.links)
      body.links.href_url.path regex_match "\\/[a-z]{3}\\d[a-z]"
    any(headers.domains)
      headers.domains.tld ends_with ".jp"
    any(ml.nlu_classifier(body.current_thread.text).entities)
      ml.nlu_classifier(body.current_thread.text).entities.name eq "urgency"
    any(ml.nlu_classifier(body.current_thread.text).entities)
      ml.nlu_classifier(body.current_thread.text).entities.text eq "invoice"
    any(ml.nlu_classifier(body.current_thread.text).tags)
      ml.nlu_classifier(body.current_thread.text).tags.name eq "invoice"
    any(body.links)
      network.whois func_call "network.whois(body.links[].href_url.domain).days_old < 30"
    any(recipients.to)
      strings.icontains func_call "strings.icontains(body.current_thread.text)"
    any($org_vips)
      strings.icontains func_call "strings.icontains(body.html.inner_text)"
    any($org_vips)
      strings.icontains func_call "strings.icontains(body.plain.raw)"
    and
      subject.base regex_match "(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)"
      subject.subject regex_match "\\bre:\\s+re:"
    body.html.raw regex_match "((<br\\s*/?>\\s*){20,}|\\n{20,})"
    body.html.raw regex_match "(<p class=\".*?\"><span style=\".*?\"><o:p>&nbsp;</o:p></span></p>\\s*){30,}"
    body.html.raw regex_match "(<p>&nbsp;</p><br>\\s*){7,}"
    body.html.raw regex_match "(<p>&nbsp;</p>\\s*){7,}"
    body.html.raw regex_match "(<p[^>]*>&nbsp;</p>\\s*){7,}"
    body.html.raw regex_match "(<p[^>]*>\\s*&nbsp;<br>\\s*</p>\\s*){5,}"
    body.html.raw regex_match "(<p[^>]*>\\s*<br\\s*/?>\\s*</p>\\s*){30,}"
    network.whois func_call "network.whois(sender.email.domain).days_old < 30"
    profile.by_sender func_call "profile.by_sender().days_known < 7"
    sender.display_name regex_match "[a-z0-9]+@[a-z]+"
    sender.email.domain.domain eq ""
    sender.email.domain.tld ends_with ".jp"
     macro "all(body.links)"
  or
    and
      any([body.current_thread.text, body.html.display_text, body.plain.raw])
        or
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "cc:"
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "date:"
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "from:"
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "sent:"
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "subject:"
          [body.current_thread.text, body.html.display_text, body.plain.raw] contains "to:"
      not
        or
          subject.is_forward eq "true"
          subject.is_reply eq "true"
       macro "(length(body.current_thread.text) + 100) < length(coalesce(body.html.display_text, body.plain.raw))"
    subject.is_forward eq "true"
    subject.is_reply eq "true"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "message/rfc822"]
  not
    and
      headers.hops[0].received.server.raw eq "relay.mimecast.com"
      headers.hops[0].received.source.raw contains "mimecast.lan"
      headers.message_id ends_with ".mimecast.lan>"
      headers.message_id starts_with "<Mimecast."
  or
    and
      headers.return_path.domain.domain is_not_null
      headers.return_path.domain.domain ne "calendar-server.bounces.google.com"
    headers.return_path.domain.domain is_null
  or
    headers.in_reply_to is_null
    headers.references length_compare "0"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
headers.hops[0].received.server.raweqrelay.mimecast.comexcludes:headers.hops[0].received.server.raw field:"headers.hops[0].received.server.raw" value:"relay.mimecast.com"
headers.hops[0].received.source.rawcontainsmimecast.lanexcludes:headers.hops[0].received.source.raw field:"headers.hops[0].received.source.raw" value:"mimecast.lan"
headers.message_idends_with.mimecast.lan>excludes:headers.message_id field:"headers.message_id" value:".mimecast.lan>"
headers.message_idstarts_with<Mimecast.excludes:headers.message_id field:"headers.message_id" value:"<Mimecast."

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.html.rawregex_match
  • ((<br\s*/?>\s*){20,}|\n{20,})
  • (<p class=".*?"><span style=".*?"><o:p> </o:p></span></p>\s*){30,}
  • (<p> </p><br>\s*){7,}
  • (<p> </p>\s*){7,}
  • (<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}
  • (<p[^>]*>\s* <br>\s*</p>\s*){5,}
  • (<p[^>]*> </p>\s*){7,}
field:"body.html.raw" kind:regex_match
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
headers.return_path.domain.domainis_not_null
  • (no value, null check)
field:"headers.return_path.domain.domain" kind:is_not_null
headers.return_path.domain.domainis_null
  • (no value, null check)
field:"headers.return_path.domain.domain" kind:is_null
headers.return_path.domain.domainne
  • calendar-server.bounces.google.com
field:"headers.return_path.domain.domain" kind:ne value:"calendar-server.bounces.google.com"
sender.display_nameregex_match
  • [a-z0-9]+@[a-z]+
field:"sender.display_name" kind:regex_match value:"[a-z0-9]+@[a-z]+"
sender.email.domain.tldwildcard
  • *.jp
field:"sender.email.domain.tld" kind:wildcard value:"*.jp"
subject.baseregex_match
  • (?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)
field:"subject.base" kind:regex_match value:"(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)"
subject.is_forwardeq
  • true transforms: boolean
field:"subject.is_forward" kind:eq value:"true"
subject.is_replyeq
  • true transforms: boolean
field:"subject.is_reply" kind:eq value:"true"
subject.subjectregex_match
  • \bre:\s+re:
field:"subject.subject" kind:regex_match value:"\bre:\s+re:"
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Fake warning banner using confusable characters

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

Detects messages containing fake security banners that use visually similar characters to impersonate legitimate sender verification text, potentially to bypass security controls and deceive recipients.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesEvasion, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • type

Rule body

type.inbound
and (
  regex.contains(strings.replace_confusables(body.current_thread.text),
                 'This sender has been verified fro(?:m|rn) safe senders list'
  )
  or any(body.current_thread.banners,
         regex.contains(strings.replace_confusables(.text),
                        'This sender has been verified fro(?:m|rn) safe senders list'
         )
  )
)

Detection logic

Scope: inbound message.

Detects messages containing fake security banners that use visually similar characters to impersonate legitimate sender verification text, potentially to bypass security controls and deceive recipients.

  1. inbound message
  2. any of:
    • strings.replace_confusables(body.current_thread.text) matches 'This sender has been verified fro(?:m|rn) safe senders list'
    • any of body.current_thread.banners where:
      • strings.replace_confusables(.text) matches 'This sender has been verified fro(?:m|rn) safe senders list'

Inspects: body.current_thread.banners, body.current_thread.banners[].text, body.current_thread.text, type.inbound. Sensors: regex.contains, strings.replace_confusables.

Indicators matched (1)

FieldMatchValue
regex.containsregexThis sender has been verified fro(?:m|rn) safe senders list

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(body.current_thread.banners)
      strings.replace_confusables(body.current_thread.banners[].text) regex_match "This sender has been verified fro(?:m|rn) safe senders list"
    strings.replace_confusables(body.current_thread.text) regex_match "This sender has been verified fro(?:m|rn) safe senders list"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

Impersonation: Fake product discount promotion

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

Detects messages containing fake product discount offers that leads to a googleapis.com domain.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesSocial engineering, Free file host

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule body

type.inbound
and strings.icontains(body.current_thread.text,
                      "hi {email}",
                      "participation is voluntary",
                      "limit one discount",
                      "limited time offer",
                      "code",
                      "survey"
)
and (
  regex.icontains(body.current_thread.text, 'claim \d+% off')
  or regex.icontains(body.current_thread.text, '\d+ question')
)
and any(body.current_thread.links,
        .href_url.domain.root_domain == "googleapis.com"
)
and any(ml.nlu_classifier(body.current_thread.text).topics,
        .name in ("Advertising and Promotions")
)
// negate highly trusted sender domains unless they fail DMARC authentication
and not (
  sender.email.domain.root_domain in $high_trust_sender_root_domains
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection logic

Scope: inbound message.

Detects messages containing fake product discount offers that leads to a googleapis.com domain.

  1. inbound message
  2. body.current_thread.text contains any of 6 patterns
    • hi {email}
    • participation is voluntary
    • limit one discount
    • limited time offer
    • code
    • survey
  3. any of:
    • body.current_thread.text matches 'claim \\d+% off'
    • body.current_thread.text matches '\\d+ question'
  4. any of body.current_thread.links where:
    • .href_url.domain.root_domain is 'googleapis.com'
  5. any of ml.nlu_classifier(body.current_thread.text).topics where:
    • .name in ('Advertising and Promotions')
  6. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass)

Inspects: body.current_thread.links, body.current_thread.links[].href_url.domain.root_domain, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators matched (10)

FieldMatchValue
strings.icontainssubstringhi {email}
strings.icontainssubstringparticipation is voluntary
strings.icontainssubstringlimit one discount
strings.icontainssubstringlimited time offer
strings.icontainssubstringcode
strings.icontainssubstringsurvey
regex.icontainsregexclaim \d+% off
regex.icontainsregex\d+ question
body.current_thread.links[].href_url.domain.root_domainequalsgoogleapis.com
ml.nlu_classifier(body.current_thread.text).topics[].namememberAdvertising and Promotions

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  any(body.current_thread.links)
    body.current_thread.links.href_url.domain.root_domain eq "googleapis.com"
  or
    body.current_thread.text contains "code"
    body.current_thread.text contains "hi {email}"
    body.current_thread.text contains "limit one discount"
    body.current_thread.text contains "limited time offer"
    body.current_thread.text contains "participation is voluntary"
    body.current_thread.text contains "survey"
  or
    body.current_thread.text regex_match "\\d+ question"
    body.current_thread.text regex_match "claim \\d+% off"
  any(ml.nlu_classifier(body.current_thread.text).topics)
    ml.nlu_classifier(body.current_thread.text).topics.name eq "Advertising and Promotions"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • code
  • hi {email}
  • limit one discount
  • limited time offer
  • participation is voluntary
  • survey
field:"body.current_thread.text" kind:contains
body.current_thread.textregex_match
  • \d+ question
  • claim \d+% off
field:"body.current_thread.text" kind:regex_match
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"