BrowserDefense: The browser is part of the endpoint

Browser-side telemetry for detection and response, with a working demonstration of Shadow Detection following page structure across changing domains.

Security#security#browser-extensions#cryptography#blue-team

An employee can spend the whole workday in a browser. Email, shared documents, the admin console for half the company. A phishing link arrives in that same workspace, opens a convincing login page, and asks for credentials. Nothing needs to download or execute outside the browser for the attacker to get what they came for.

Traditional endpoint detection and response (EDR) centers on processes, files, and host activity. Some products also block malicious sites. But knowing that a browser made a connection leaves a lot unanswered: which redirects led there, what was in the tab, and whether that login form has shown up somewhere else.

I built BrowserDefense to make more of that context available. It’s a browser extension I’m making public, with local URL blocking and telemetry you can use to build browser detection and response. Block events can include the redirect chain and tab context, so an analyst has something to investigate beyond a destination address.

Shadow Detection adds another signal: the structure of the page itself. Move a cloned login page to a new domain and a URL blocklist needs another entry. The form can stay exactly the same. I wanted a way to follow that reuse without collecting the page’s text.

The URL check happens during navigation. Structural detection gets its turn once there’s a page to inspect:

From navigation to a detectionFirst-visit overview, with caches and independent similarity telemetry omitted. Known local signatures can act without a server request. Structural inspection cannot prevent the initial navigation.

A blocked URL produces a block event. Otherwise, once the DOM is available, BrowserDefense normalizes and hashes its structure, checks local signatures, and can query a configured fingerprint service. Known local matches and other verdicts follow their configured action; uncertain verdicts covered by shadow mode are logged for review without blocking.

Strip the page down

The extractor walks the DOM, retaining element nesting and selected attributes such as input types and form methods. It skips text, CSS, images, and script bodies. It also sorts the serialized children, so rearranging siblings doesn’t change the resulting tree.

In the active cached fingerprint path, that normalized tree goes through SHA-256. The hostname isn’t in it. Neither are the words on the submit button or the values someone typed into the form.

Try changing the example below. The first change moves the page to another domain. The next changes its heading and CSS. Both keep the same fingerprint. Adding a wrapper element changes the tree and produces a different hash.

A new domain can keep the same structural fingerprint
Synthetic test pages, evaluated with the actual extractor and active cached hash function. Hashes are shortened in the figure; source values retain every full hash and normalized tree. This demonstrates exact matching, not a phishing detection rate.

Compare four synthetic login pages evaluated by BrowserDefense's pinned extractor. The domain and text/CSS variants have the reference hash. Adding a div around the inputs changes it. The control selects a variant; all four results remain visible without JavaScript.

View source values
Synthetic fixtures evaluated by the pinned extractor and active SHA-256(tagTree) path. All full hashes are compared; this is not a malware classification.
VariantHostNormalized tag treeFull SHA-256Exact comparison
Original pageportal-a.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Different domainportal-b.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Different text + CSSportal-b.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Extra DOM wrapperportal-b.examplehtml(body(form[method=post](button[type=submit],div(input[type=email],input[type=password]),h2)),head)296c90feb1f92d2450614bb0ee9078ad534540fb5e5352f755f3891efeace8b3Different from reference
Synthetic fixtures evaluated by the pinned extractor and active SHA-256(tagTree) path. All full hashes are compared; this is not a malware classification.
VariantHostNormalized tag treeFull SHA-256Exact comparison
Original pageportal-a.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Different domainportal-b.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Different text + CSSportal-b.examplehtml(body(form[method=post](button[type=submit],h2,input[type=email],input[type=password])),head)a932db0f5055f054b4aa56b77bb83d12409d9086d87c5fd4623cdb89649ae67eSame as reference
Extra DOM wrapperportal-b.examplehtml(body(form[method=post](button[type=submit],div(input[type=email],input[type=password]),h2)),head)296c90feb1f92d2450614bb0ee9078ad534540fb5e5352f755f3891efeace8b3Different from reference

These are small test pages, not captured phishing sites. I like them for showing exactly what the comparison throws away. You can change the address and wording without changing the form underneath.

Adding the wrapper changes this exact hash. BrowserDefense also has a separate MinHash/LSH similarity path for variants, but the figure only tests exact equality. It doesn’t establish how well similarity matching handles a modified kit in the wild.

Recognize first, decide whether to block

Matching structure doesn’t prove that a page is malicious. Legitimate sites reuse login templates, too. Blocking every unfamiliar fingerprint would make a browser fairly unpleasant to use.

Shadow mode lets uncertain detections be logged for analyst review without blocking the page. The analyst can promote a detection or dismiss it. Known signatures can carry their own enforcement action; the point of shadow mode is to inspect uncertain matches before turning them into a rule.

The hash-only uplink sends a fingerprint and timestamp rather than a URL or HTML. That keeps the comparison payload small and avoids uploading page contents through that path. It isn’t a promise that a hash reveals nothing: someone who has a candidate template can fingerprint it and compare. Encrypted block-event reports are a separate path, with their own capture settings and the organization’s decryption key.

Structural detection also starts after the page’s DOM is available. It can’t prevent the first request to a previously unseen site. The URL filter still has work to do.

For a domain you already know about, there’s a shorter workflow. Select indicators in a threat report, right-click, and choose “Broadcast IOCs to Team.” An authenticated analyst can submit them to the team’s feed without copying them into another tool. Managed browsers receive signed updates and check navigations against the local list.

Installation mode matters. Managed policy installation enables the enterprise blocking path. An ordinary installation uses a different combination of browser rules and reactive redirects, where navigation can begin before the redirect intervenes.

Block reports travel back encrypted. The organization decrypts them with its own key; the analyst investigates and can submit confirmed URL indicators to the feed. Browsers verify the signed update before applying it.

From a block report to updated browser rulesDeployment overview: reporting and feed endpoints are configured separately. Submitting URL indicators is an analyst action; shadow promotion is a separate review path.

The managed browser captures a block event, encrypts the report, and uploads it. The security team retrieves the ciphertext and decrypts it with the organization's key to investigate. An analyst explicitly submits confirmed URL indicators, and browsers receive signed feed updates by push or pull, verifying the signature before updating local rules.

The repository includes the extension, CLI, and deployment instructions. To try Shadow Detection, start with two copies of a harmless login form on domains you control. Change the heading, change the styling, then add a wrapper around the inputs. Give each variant a fresh path: the extension caches fingerprints by URL, ignoring query strings and fragments. Watch which fingerprints stay equal. Reviewing those matches is where the experiment becomes useful.