Prompt injection: Hidden instructions to an AI in body HTML

Detects instructions a human recipient never sees but an AI assistant reads: text in unrendered HTML elements or HTML comments that addresses an AI, where NLU finds a request and the prompt injection model agrees, or long runs of invisible Unicode tag or variation-selector characters. Excludes email preheaders. Restricted to senders with low prevalence and no benign history, and excludes graymail from senders passing DMARC.

Sublime rule (View on GitHub)

 1name: "Prompt injection: Hidden instructions to an AI in body HTML"
 2description: "Detects instructions a human recipient never sees but an AI assistant reads: text in unrendered HTML elements or HTML comments that addresses an AI, where NLU finds a request and the prompt injection model agrees, or long runs of invisible Unicode tag or variation-selector characters. Excludes email preheaders. Restricted to senders with low prevalence and no benign history, and excludes graymail from senders passing DMARC."
 3type: "rule"
 4severity: "low"
 5source: |
 6  type.inbound
 7  //
 8  // This rule makes use of a beta feature and is subject to change without notice
 9  // using the beta feature in custom rules is not suggested until it has been formally released
10  //
11  and (
12    any(html.xpath(body.html,
13                   "//*[contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';display:none') or contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';visibility:hidden') or contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';font-size:0;') or contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';font-size:0px;') or (contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';opacity:0;') and not(contains(concat(';', translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz'), ';'), ';transform:'))) or @hidden]"
14        ).nodes,
15        not (
16          length(.inner_text) > 0
17          and regex.icount(.inner_text,
18                           '[\x{034F}\x{00AD}\x{200C}\x{2007}\x{FEFF}]'
19          ) * 100 / length(.inner_text) >= 25
20        )
21        and regex.icontains(.inner_text,
22                            '(?:(?:^|\n)[ \t]*-?|[\[(>*\x27\"])[ \t]*(?:[\w-]+[ \t]+){0,3}(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|mailbot)[ \t]*(?:note[ \t]*)?[:—–]|(?:^|\n)[ \t]*[*>-]?[ \t]*(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|mailbot)s?[ \t]*,|\b(?:note|notice|instructions?|reminder|message)\s+(?:to|for)\s+(?:(?:the|any|all|your|this)\s+(?:[\w\x27\x{2019}-]+\s+){0,2}(?:(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)|ai|models?)|(?:ai\s+)?(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot))s?\b|\bif\s+you\s+are\s+an?\s+(?:ai|llm|language\s+model)\b|\bif\s+you\s+are\s+an?\s+(?:[\w-]+\s+)?(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)(?:[ \t]*[,:;.)—]|\s+(?:reading|processing|handling|summari[sz]ing|parsing|triaging|indexing|preparing|condensing|that|which|with\s+access)\b)|\b(?:(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)|ai|model)s?\s+(?:that\s+is\s+|is\s+)?(?:reading|processing|handling|summari[sz]ing|parsing|triaging|indexing|preparing)\s+this\b|<\|im_start\|>'
23        )
24        and any(ml.nlu_classifier(.inner_text).entities, .name == "request")
25        and beta.prompt_injection_detection(.inner_text).detection == "injection"
26        and beta.prompt_injection_detection(.inner_text).confidence in (
27          "medium",
28          "high"
29        )
30    )
31    or any(html.xpath(body.html, "//comment()").nodes,
32           length(.raw) >= 80
33           and regex.icontains(.raw,
34                               '(?:(?:^|\n|<!--)[ \t]*-?|[\[(>*\x27\"])[ \t]*(?:[\w-]+[ \t]+){0,3}(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|mailbot)[ \t]*(?:note[ \t]*)?[:—–]|(?:^|\n|<!--)[ \t]*[*>-]?[ \t]*(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|mailbot)s?[ \t]*,|\b(?:note|notice|instructions?|reminder|message)\s+(?:to|for)\s+(?:(?:the|any|all|your|this)\s+(?:[\w\x27\x{2019}-]+\s+){0,2}(?:(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)|ai|models?)|(?:ai\s+)?(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot))s?\b|\bif\s+you\s+are\s+an?\s+(?:ai|llm|language\s+model)\b|\bif\s+you\s+are\s+an?\s+(?:[\w-]+\s+)?(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)(?:[ \t]*[,:;.)—]|\s+(?:reading|processing|handling|summari[sz]ing|parsing|triaging|indexing|preparing|condensing|that|which|with\s+access)\b)|\b(?:(?:assistant|agent|bot|llm|summari[sz]er|screener|classifier|copilot|mailbot)|ai|model)s?\s+(?:that\s+is\s+|is\s+)?(?:reading|processing|handling|summari[sz]ing|parsing|triaging|indexing|preparing)\s+this\b|<\|im_start\|>'
35           )
36           and any(ml.nlu_classifier(.raw).entities, .name == "request")
37           and beta.prompt_injection_detection(.raw).detection == "injection"
38           and beta.prompt_injection_detection(.raw).confidence in (
39             "medium",
40             "high"
41           )
42    )
43    or any([subject.subject, body.plain.raw, body.html.raw],
44           regex.contains(.,
45                          '[\x{E0020}-\x{E007F}]{32,}|[\x{E0100}-\x{E01EF}]{16,}'
46           )
47    )
48  )
49  
50  // an injection arrives from outside the recipient's correspondence... the profile
51  // is unauthenticated, so a spoofed known correspondent is suppressed too
52  and profile.by_sender_email().prevalence in ("new", "outlier", "rare")
53  and not profile.by_sender_email().any_messages_benign
54  
55  // graymail from authenticated senders... AI-product newsletters and webinars
56  and not coalesce(beta.attack_score_flash().verdict == "graymail"
57                   and headers.auth_summary.dmarc.pass,
58                   false
59  )  
60tags:
61  - "Attack surface reduction"
62  - "Email prompt injection"
63attack_types:
64  - "BEC/Fraud"
65tactics_and_techniques:
66  - "Evasion"
67  - "Social engineering"
68detection_methods:
69  - "Content analysis"
70  - "HTML analysis"
71  - "Natural Language Understanding"
72  - "Sender analysis"
73id: "8c09455a-ae6a-57c9-83a8-bf4d827725a5"

Related rules

to-top