File Attack Deep Dives
File Attack Deep Dives, Part 2: HTML Smuggling

File Attack Deep Dives, Part 2: HTML Smuggling

How attackers assemble malware inside the browser with Blob URLs, and the URL and script tells that catch it.

HTML smuggling never sends the malware. It sends a recipe: encoded text plus a small script that rebuilds the file inside your browser. Catch it by watching what the page builds, not what crosses the wire.

Part 1 of this series, the field guide, mapped the file attack families and named HTML smuggling as the one that assembles its payload after inspection. This part opens up that family: the exact browser flow, why gateways miss it, and the tells that catch it.

This is the family I see most often in the wild, so it is the one I would learn first if I were building detection tomorrow.

How does HTML smuggling land?

The delivery is an HTML page or HTML attachment. Inside it sits the payload as encoded text, usually Base64, plus a short script. When the victim opens the page, the browser follows the recipe and writes the real file to disk. The canonical flow, documented as MITRE T1027.006:

  1. The page carries the payload as an encoded string, often Base64 inside a JavaScript block.
  2. The script decodes it, typically with atob(), into raw bytes.
  3. It wraps the bytes in a Blob, an in-memory file-like object.
  4. It calls URL.createObjectURL(blob) to mint a temporary blob: URL.
  5. It creates an anchor element, sets href to the Blob URL and the download attribute to the chosen filename, and clicks it programmatically.
  6. The browser treats it as a download and saves the assembled file.

The whole sequence fits in a few lines:

const bytes = Uint8Array.from(atob(encodedPayload), (c) => c.charCodeAt(0));
const blob = new Blob([bytes], { type: "application/octet-stream" });
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "invoice.iso";
a.click();

On older Internet Explorer and legacy Edge builds, the same outcome goes through window.navigator.msSaveBlob(blob, filename) instead of the anchor flow, so smuggling kits probe for it as a fallback path.

Strip the script away and what is left is a base64 string. Paste a sample into the Base64 workbench and you can decode it by hand to see the file it rebuilds. That is the whole trick: the malware is a text file until the browser turns it into a binary.

Why do gateways miss HTML smuggling?

A gateway inspects what crosses the wire. In HTML smuggling, what crosses the wire is benign-looking HTML and JavaScript plus encoded text. There is no executable, no archive, no container to detonate at the choke point. Microsoft's writeup of the technique puts it plainly: gateways only see benign HTML and JavaScript traffic while the malicious file is created on the endpoint after the page loads (HTML smuggling surges).

Three properties combine to make that gap reliable:

  • Assembly happens after inspection. Decoding and Blob construction run at render time, on the victim's machine, past every transit scanner.
  • The page looks ordinary. Encoded strings and Blob calls are also what legitimate export-to-CSV and document-preview features use, so naive pattern blocks drown in false positives.
  • The payload shape is free. Attackers split the encoded text across variables, nest encodings, or serve it as fragments, so no single static signature survives rotation.

This is not theoretical. In May 2024, Huntress documented a mass campaign that paired an HTML smuggling payload with an injected iframe proxying the Outlook login portal, stealing sessions when victims logged in (Smuggler's Gambit).

What does HTML smuggling look like to detection?

Detection lives where the file materializes: the endpoint and the browser, not the wire. Work through these in order of signal quality.

  • Script pattern in the page. atob() or equivalent decoding feeding new Blob(), followed by URL.createObjectURL() and a programmatic .click() on an anchor with a download attribute. Any one call is common; the chained sequence in a single page is the tell.
  • Oversized HTML with encoded weight. An HTML attachment carrying a large Base64 block or concatenated string fragments, especially paired with obfuscated script, deserves sandbox detonation rather than a static pass.
  • Download with no matching fetch. The browser writes a file, often an ISO, ZIP, or LNK, to Downloads or temp with no corresponding network object of that type. A download that appears from nowhere was built locally.
  • Browser-as-parent file writes. A browser process writing an executable, archive, or disk image, followed within seconds by execution, is the behavioral pair that survives obfuscation.
  • Missing Mark of the Web. A payload that runs without the Zone.Identifier marker it should carry suggests a container stripped provenance on the way in. Treat absent MOTW on an internet-born file as an anomaly, not a detail.

Pick a pattern below, see how it lands, then reveal the tell and the detection.

HTML smuggling

How it lands. An HTML page or attachment carries Base64-encoded bytes plus script. On open, the browser decodes them, builds a Blob, mints a blob: URL, and triggers a download with the anchor download attribute.

How do you defend against it?

The fix follows the tell. Detonate HTML attachments in a sandbox that actually runs the script and watches what gets written, alert on the browser-writes-then- executes pair at the endpoint, and treat missing Mark of the Web as a signal. Blocking external HTML attachments outright is the blunt version of the same idea and fits some environments.

Does blocking HTML attachments stop HTML smuggling?

Mostly, for the email path. No HTML attachment means no in-browser assembly from mail. But the same recipe works from a link to a hosted page, so endpoint behavioral detection still matters.

Why not just alert on every Blob and download call?

Because legitimate web apps build files the same way: exports, previews, and generated reports all use Blob plus the download attribute. Alert on the full chain, decoding into Blob construction into a programmatic download, ideally paired with a file write the endpoint did not fetch.

Test yourself

A quick self-check on HTML smuggling. Pick an option to see the answer.

0/2 answered · 0 correct
  1. 1. Where is the malicious file assembled in HTML smuggling?

  2. 2. Which API sequence is the core smuggling tell?

Next in this series: Document macros, then PDF URL actions, then LNK and ISO smuggling, each with its own payload pattern and detection.

Useful references:

Written by

Mohit Khare

Senior software lead at Abnormal.AI, prev. CRED and Gojek. Backend engineer working on AI, security, and engineering leadership. Based in Bangalore.

Connect on LinkedInMore writing