Skip to content
Undetect Research
Research Intelligence

Fingerprinting in Style

A review of a 2021 USENIX Security paper showing how browser extensions can be detected through CSS rules they inject into pages, even when extension style sheets themselves are hidden.

Paper analyzed: Fingerprinting in Style: Detecting Browser Extensions via Injected Style Sheets, USENIX Security 2021. HAL: hal-03152176.

Extension corpus
116,485

Chrome Web Store extensions collected in April 2019 after excluding themes and apps

Any-domain CSS injectors
6,645

Combined declarative and dynamic CSS-injecting set considered potentially fingerprintable

Uniquely identifiable
4,446

Extensions identified through CSS-triggered style or dimension changes

CSS-only vs prior methods
1,074

Extensions detectable only by CSS among the compared WAR, DOM, and postMessage methods

1. Executive Summary

This paper identifies a browser-extension fingerprinting channel that does not need web-accessible extension resources, privileged APIs, or visible DOM artifacts. A page can create hidden DOM triggers that match extension-injected CSS selectors and then compare computed styles or layout dimensions against baseline elements.

The authors collected 116,485 Chrome Web Store extensions in April 2019 and found 6,645 extensions that could inject CSS on any domain. Their pipeline generated and confirmed trigger elements, removed collisions, and reported 4,446 uniquely identifiable extensions, or 3.8% of the measured corpus.

Operational takeaway: extension privacy cannot stop at hiding extension URLs or DOM mutations. If extension-origin CSS affects page-visible computed style or layout APIs, installed extensions can still become stable browser-profile signals.

2. Attack Surface

Browser implementations hide extension-injected style sheets from document.styleSheets, but the resulting styles still change page elements. The attack page supplies matching selectors, hides the elements off-screen, and reads the result through standard APIs such as getComputedStyle, getBoundingClientRect, offsetWidth, and offsetHeight.

Declarative styles

Extensions can list CSS files in manifest.json content scripts. Broad match patterns make those styles available on arbitrary pages.

Dynamic styles

Extensions can also call chrome.tabs.insertCSS; the authors used Mystique to observe those programmatic injections.

Trigger elements

The test page translates selectors into hidden DOM structures with matching IDs, classes, and hierarchy.

Observable side effects

The page compares baseline and trigger elements, then treats changed style properties or dimensions as extension evidence.

Figure showing declarative and programmatic ways that browser extensions inject CSS into pages.
Figure 1 crop: extension CSS can be injected declaratively or through tabs.insertCSS, while page JavaScript can still observe the style result.
Dr.Web extension example showing a CSS rule, trigger element, and computed style changes.
Figure 2 crop: the Dr.Web example shows how one class trigger can expose an installed extension through computed style differences.

3. Method

The large-scale evaluation focuses on extensions whose CSS can apply on any domain, because any visited site could host the corresponding triggers. The paper also distinguishes that universal case from extensions that inject CSS only on specific sites such as Gmail, Twitter, or YouTube.

StagePaper methodReview significance
Collect extensionsCustom Chrome Web Store crawler collected 116,485 extensions in April 2019 after excluding themes and apps.The headline rates are historical Chrome Web Store measurements, not current ecosystem rates.
Extract CSSParse declarative content_scripts CSS and use Mystique to observe dynamic tabs.insertCSS injection.The technique is limited to extensions that inject CSS visible to page layout and style APIs.
Generate triggersTranslate selectors into decoy DOM structures; skip pseudo-classes and pseudo-elements that require interaction or are hard to trigger in the background.The trigger database is intentionally biased toward background fingerprinting that can run without user gestures.
Confirm dynamicallyRun extensions against generated test pages with Selenium, compare trigger elements to baseline elements, and repeat collection three times.Repeated confirmation filters nondeterministic style changes before uniqueness analysis.
Check uniquenessExpose extensions to confirmed triggers, compare style and dimension signatures, and remove triggers that collide across extensions.The final count is about uniquely identifiable extensions, not merely extensions that affect CSS.
Extension analysis pipeline from CSS extraction through trigger generation, dynamic confirmation, and fingerprint evaluation.
Figure 3 crop: the paper pipeline moves from extension CSS extraction to trigger generation, confirmation, and collision-aware fingerprint evaluation.

4. Fingerprintability Results

Table 2 is the core evidence for the paper's prevalence claim. It narrows the measured corpus from CSS-injecting extensions to confirmed triggers and then to uniquely identifiable extensions.

17,712 CSS injectors15.2% of the 116,485-extension corpus injected at least one CSS file through content scripts.
6,543 declarative any-domainExtensions whose manifest CSS could apply across all domains.
137 dynamic injectorsMystique found dynamic tabs.insertCSS use; 35 were already in the declarative set.
40,722 final triggersConfirmed triggers that remained after collision filtering, covering 4,446 uniquely identifiable extensions.
Table 2 showing extension and trigger counts across each pipeline stage.
Table 2 crop: pipeline statistics for CSS-injecting extensions, generated triggers, confirmed triggers, and collision-filtered fingerprints.

The final 4,446 extensions are identifiable on any webpage under the authors' model because their styles can apply globally. That number should not be generalized to all extensions or to the current Chrome Web Store without rerunning the measurement.

5. Strategies and Collisions

The paper evaluates progressively richer fingerprinting strategies. A unique trigger alone identifies 3,866 extensions. Including changed style properties identifies 4,090. Including both changed properties and their values, across computed-style and dimension APIs, identifies 4,446.

Table 3 comparing trigger-only, trigger plus properties, and trigger plus properties plus values strategies.
Table 3 crop: trigger, property, and value collection strategies increase the number of uniquely identifiable extensions.
  • Direct uniqueness. 3,475 of the 4,446 identifiable extensions had at least one trigger not shared with any other extension.
  • Property/value uniqueness. Another 846 extensions shared all triggers but became unique after considering changed properties and values.
  • Combination uniqueness. The remaining 125 were identifiable through a unique combination of non-unique trigger effects.
  • Collision context. The authors found 218 collision clusters among non-unique fingerprints; most were small and often reflected duplicated extensions, variants from the same developer, copies, or shared libraries.
  • Dimension sensitivity. Dimension-based fingerprints may vary with screen size and device conditions, so those signatures need careful database and replay handling.
Table 6 listing the most commonly modified CSS properties in generated fingerprints.
Table 6 crop: high-frequency modified properties include layout and transform-origin values that can produce precise signatures.

6. Overlap and Stability

CSS fingerprinting overlaps only partly with prior extension-fingerprinting techniques. Compared against web-accessible resources, DOM modification, and postMessage methods, the paper reports 1,074 CSS-only extensions. It also notes that if web-accessible resource probing disappeared through UUID randomization similar to Firefox's design, CSS would become the only compared method for an additional 1,325 extensions.

Venn diagram comparing CSS fingerprinting with web-accessible resource, DOM modification, and postMessage techniques.
Figure 7 crop: CSS fingerprinting detects many extensions outside the overlap of earlier methods.

The proof-of-concept benchmark used random subsets of 1 to 20 installed extensions and ran at window.onload. The reported detection time was around 15 ms even for 20 installed extensions on the authors' laptop setup.

Benchmark chart showing extension detection time as the number of installed extensions increases.
Figure 6 crop: the proof-of-concept detection script stayed within tens of milliseconds for the tested extension counts.

For longitudinal context, the authors also collected 501,349 extension versions from mid-2014 to mid-2019, reduced to 426,807 after excluding themes and apps. In a June 2020 retest, 940 of the 4,446 universally fingerprintable extensions had updated; 776 of those 940 still triggered at least one previously discovered trigger.

7. Countermeasures

The paper rejects removing getComputedStyle as a practical mitigation because the authors observed broad legitimate use: 61,414 unique scripts using the API across 76,638 of the Alexa top 100K sites in their VisibleV8 crawl. Their manual review did not find evidence that this exact extension-fingerprinting technique was already being used in the sampled scripts.

The proposed prototype defense uses a Shadow DOM mirror. Page styles are copied into the mirror, extension-origin content styles are excluded, and selected getComputedStyle calls are rerouted to corresponding mirror elements.

Shadow DOM countermeasure design showing a mirror document used to compute styles without extension CSS.
Figure 9 crop: the prototype defense uses a mirrored DOM to answer style queries without extension-origin CSS effects.
Loading-time distributions for pages with and without the Shadow DOM countermeasure.
Figure 10 crop: the Tranco top-200 evaluation showed mean loading-time differences below 0.5% for the prototype.
  • Prototype scope. The defense is a browser extension prototype evaluated on the Tranco top 200, not a shipped browser mitigation.
  • Compatibility observations. The authors initially saw six additional JavaScript errors on reuters.com, fixed them with an extra check, and then observed no notable screenshot differences beyond dynamic content.
  • Browser-native sketch. Appendix A proposes maintaining extension-inclusive and extension-excluding computed styles, with a retrieval switch for getComputedStyle.

8. Code Artifacts

These browser-console helpers are reconstructed from the paper's figures, listings, and methodology. They are not the authors' original implementation or the 4,446-extension trigger database.

CSS trigger probe Inferred from Figure 2 and Listing 1
Purpose
Create local baseline and trigger elements, compare selected computed style and layout properties, and report whether the trigger changed.
Paper basis
The Dr.Web example uses a drwebThreatLink class and detects style and dimension changes when the extension is installed.
Caveat
This is a minimal local sanity probe and does not include the authors' trigger database.
;(async () => {
  const host = document.createElement("div");
  host.style.cssText = [
    "position:fixed",
    "left:-10000px",
    "top:-10000px",
    "width:1px",
    "height:1px",
    "overflow:hidden"
  ].join(";");

  const baseline = document.createElement("div");
  baseline.textContent = "(baseline)";
  baseline.setAttribute("data-style-fingerprint-baseline", "drwebThreatLink");

  const trigger = document.createElement("div");
  trigger.textContent = "(trigger)";
  trigger.className = "drwebThreatLink";
  trigger.setAttribute("data-style-fingerprint-trigger", "drwebThreatLink");

  host.append(baseline, trigger);
  document.documentElement.append(host);

  await new Promise((resolve) => requestAnimationFrame(resolve));

  const selectedProperties = [
    "backgroundImage",
    "backgroundPosition",
    "backgroundRepeat",
    "width",
    "height",
    "inlineSize",
    "blockSize",
    "transformOrigin",
    "perspectiveOrigin"
  ];

  const read = (element) => {
    const style = getComputedStyle(element);
    const rect = element.getBoundingClientRect();

    return {
      styles: Object.fromEntries(selectedProperties.map((name) => [name, style[name]])),
      dimensions: {
        offsetWidth: element.offsetWidth,
        offsetHeight: element.offsetHeight,
        rectWidth: rect.width,
        rectHeight: rect.height
      }
    };
  };

  const baselineSnapshot = read(baseline);
  const triggerSnapshot = read(trigger);
  const styleDiffs = selectedProperties.filter(
    (name) => baselineSnapshot.styles[name] !== triggerSnapshot.styles[name]
  );
  const dimensionDiffs = Object.keys(baselineSnapshot.dimensions).filter(
    (name) => baselineSnapshot.dimensions[name] !== triggerSnapshot.dimensions[name]
  );

  host.remove();

  const result = {
    artifact: "css-trigger-probe",
    triggerClass: "drwebThreatLink",
    changedStyleProperties: styleDiffs,
    changedDimensions: dimensionDiffs,
    possibleExtensionStyleApplied: styleDiffs.length > 0 || dimensionDiffs.length > 0,
    baseline: baselineSnapshot,
    trigger: triggerSnapshot
  };

  console.log(result);
  return result;
})()
Selector-to-trigger builder example Reconstructed from Listings 3-5
Purpose
Translate a simple CSS selector into a trigger DOM hierarchy plus a baseline hierarchy that omits matching IDs and classes.
Paper basis
The paper converts the Wikiwand selector #ww_hovercard .ww_image img into nested trigger and baseline elements.
Caveat
This handles only simple ID, class, tag, and descendant-selector forms; it is not a full CSS selector parser.
;(async () => {
  const selector = "#ww_hovercard .ww_image img";

  const parseToken = (token) => {
    const match = token.match(/^(?<tag>[a-z][a-z0-9-]*)?(?<rest>.*)$/i);
    const rest = match?.groups?.rest || token;
    const id = rest.match(/#([a-z0-9_-]+)/i)?.[1] || null;
    const classes = [...rest.matchAll(/\.([a-z0-9_-]+)/gi)].map((item) => item[1]);

    return {
      tag: match?.groups?.tag || "div",
      id,
      classes
    };
  };

  const buildTree = ({ baseline }) => {
    const root = document.createElement("div");
    root.className = "style-fingerprint-trigger-root";
    let parent = root;

    for (const part of selector.split(/\s+/).map(parseToken)) {
      const element = document.createElement(part.tag);

      if (baseline) {
        if (part.id) element.setAttribute("data-orig-id", part.id);
        if (part.classes.length > 0) element.setAttribute("data-orig-class", part.classes.join(" "));
        element.setAttribute("data-trigger", "no");
      } else {
        if (part.id) element.id = part.id;
        if (part.classes.length > 0) element.className = part.classes.join(" ");
        element.setAttribute("data-trigger", "yes");
      }

      parent.append(element);
      parent = element;
    }

    return root;
  };

  const host = document.createElement("div");
  host.style.cssText = "position:fixed;left:-10000px;top:-10000px";
  const baselineTree = buildTree({ baseline: true });
  const triggerTree = buildTree({ baseline: false });
  host.append(baselineTree, triggerTree);
  document.documentElement.append(host);

  await new Promise((resolve) => requestAnimationFrame(resolve));

  const readLeaf = (tree) => {
    const leaf = tree.querySelector("[data-trigger]");
    const style = getComputedStyle(leaf);
    const rect = leaf.getBoundingClientRect();

    return {
      tagName: leaf.tagName.toLowerCase(),
      id: leaf.id,
      className: leaf.className,
      display: style.display,
      width: style.width,
      height: style.height,
      rectWidth: rect.width,
      rectHeight: rect.height
    };
  };

  const result = {
    artifact: "selector-to-trigger-builder-example",
    selector,
    baselineLeaf: readLeaf(baselineTree),
    triggerLeaf: readLeaf(triggerTree),
    html: {
      baseline: baselineTree.outerHTML,
      trigger: triggerTree.outerHTML
    }
  };

  host.remove();
  console.log(result);
  return result;
})()
Shadow DOM computed-style mirror sketch Inferred from Section 6.2
Purpose
Demonstrate the core defense idea by comparing computed style from a page element with style from a cloned element inside a Shadow DOM mirror.
Paper basis
The authors' prototype copies the DOM and page styles into a Shadow DOM and reroutes selected getComputedStyle calls to the clone.
Caveat
This does not monkey-patch getComputedStyle and is not a production defense.
;(async () => {
  const target = document.body.querySelector("[id], [class]") || document.body;
  const sandboxHost = document.createElement("div");
  sandboxHost.style.cssText = "position:fixed;left:-10000px;top:-10000px";
  const shadow = sandboxHost.attachShadow({ mode: "closed" });

  for (const sheet of document.styleSheets) {
    try {
      const style = document.createElement("style");
      style.textContent = [...sheet.cssRules].map((rule) => rule.cssText).join("\n");
      shadow.append(style);
    } catch {
      // Cross-origin style sheets are not readable from page JavaScript.
    }
  }

  const clone = target.cloneNode(true);
  shadow.append(clone);
  document.documentElement.append(sandboxHost);
  await new Promise((resolve) => requestAnimationFrame(resolve));

  const properties = ["display", "position", "width", "height", "color", "backgroundColor"];
  const snapshot = (element) => {
    const style = getComputedStyle(element);
    return Object.fromEntries(properties.map((name) => [name, style[name]]));
  };

  const result = {
    artifact: "shadow-dom-computed-style-mirror-sketch",
    target: {
      tagName: target.tagName.toLowerCase(),
      id: target.id || null,
      className: String(target.className || "") || null
    },
    pageComputedStyle: snapshot(target),
    mirrorComputedStyle: snapshot(clone),
    note: "A full defense would patch selected getComputedStyle calls and maintain a synchronized mirror, as described in the paper."
  };

  sandboxHost.remove();
  console.log(result);
  return result;
})()

9. Limitations

  • Historical corpus. The headline measurement comes from Chrome Web Store extensions collected in April 2019.
  • Technique ceiling. CSS fingerprinting only applies to extensions that inject CSS rules into pages; the paper treats the 6,645 any-domain CSS-injecting extensions as the ceiling in the measured corpus.
  • Browser ecosystem scope. The technique targets the WebExtension model used across Chromium-family browsers and others, but the large-scale corpus is Chrome Web Store centered.
  • Discarded selectors. The trigger builder excludes pseudo-classes such as :hover, :focus, and :active because the authors focus on background fingerprinting without user interaction.
  • Screen and layout sensitivity. Dimension-based signatures can vary with device and viewport conditions; the paper suggests multiple dimension databases but does not evaluate that approach.
  • Collision interpretation. Collision clusters can add identifying entropy without uniquely naming one installed extension.
  • Countermeasure maturity. The Shadow DOM defense is a prototype and Appendix A is a browser-vendor design sketch, not a deployed browser fix in the paper.

10. Reviewer Notes

The extracted PDF identifies Pierre Laperdrix, Oleksii Starov, Quan Chen, Alexandros Kapravelos, and Nick Nikiforakis as authors of Fingerprinting in Style: Detecting Browser Extensions via Injected Style Sheets, published at the 30th USENIX Security Symposium in August 2021. The extracted artifacts include a HAL page and an author artifact repository: HAL hal-03152176 and fingerprinting-in-style on GitHub.

  • No DOI or arXiv URL was visible in the extracted metadata, so this page does not add one.
  • The extracted metadata does not include a stable R2 PDF URL, so this page intentionally renders without a PDF download link.
  • Keep prevalence statements scoped to the April 2019 Chrome Web Store corpus unless a current crawl is performed.
  • Do not imply active in-the-wild use of this exact attack; the paper reports no evidence in manually reviewed getComputedStyle samples.
  • The code artifacts are reconstructed browser-console examples, not source code from the authors' artifact repository.
Appendix
Updated 2026-06-20

Glossary

Linked terms for the CSS-based browser-extension fingerprinting report: page-visible style APIs, extension injection mechanics, fingerprint uniqueness, collisions, measurement tooling, and browser-level countermeasure concepts.
DOM and Browser APIs
window.getComputedStyle()
Context: The attack reads extension-origin style effects by calling `getComputedStyle` on hidden trigger and baseline elements.
Meaning: `getComputedStyle()` returns resolved CSS property values after active style sheets and layout-dependent computation have been applied.
document.styleSheets
Context: The paper notes that extension-injected style sheets are hidden from `document.styleSheets`, even though their computed effects remain observable.
Meaning: `document.styleSheets` exposes the style sheets explicitly associated with a document through the CSSOM.
Element.getBoundingClientRect()
Context: The proof method compares trigger and baseline dimensions when extension CSS changes layout rather than only style property values.
Meaning: `getBoundingClientRect()` returns the size and viewport-relative position of an element's border box.
HTMLElement.offsetWidth and offsetHeight
Context: The Dr.Web example and reconstructed probe include `offsetWidth` and `offsetHeight` as dimension channels for extension detection.
Meaning: `offsetWidth` and `offsetHeight` report integer layout dimensions for rendered HTML elements, including borders and padding.
CSS selectors, pseudo-classes, and pseudo-elements
Context: The trigger builder translates extension selectors into decoy DOM structures and intentionally skips many pseudo selectors that require state or interaction.
Meaning: Selectors match DOM elements for CSS rules; pseudo-classes and pseudo-elements extend matching to element states or generated/abstract parts of the rendering tree.
Shadow DOM
Context: The prototype defense mirrors the page into a Shadow DOM so selected style reads can exclude extension-origin content styles.
Meaning: Shadow DOM attaches an encapsulated DOM tree to a host element so its markup and styles are isolated from the regular document tree.
Page load and Performance APIs
Context: The benchmark runs detection after `window.onload` with `performance.now`, and the countermeasure evaluation uses navigation timing metrics.
Meaning: The load event indicates that a page and its dependent resources have loaded, while Performance APIs expose high-resolution timing and navigation milestones.
window.postMessage()
Context: Figure 7 compares CSS fingerprinting with prior extension-fingerprinting techniques based on `postMessage` behavior.
Meaning: `postMessage()` enables controlled message passing between Window objects, including cross-origin communication when the receiver validates origin and data.
Browser Extension and Fingerprinting Concepts
Browser fingerprinting
Context: The paper frames extension detection as a stateless tracking signal that can add identifying information to a browser profile.
Meaning: Browser fingerprinting identifies or correlates a browser by combining observable browser, device, and environment characteristics.
Extension fingerprinting
Context: The report reviews CSS-based detection alongside WAR probing, DOM modification, and `postMessage` extension-fingerprinting methods.
Meaning: Extension fingerprinting infers which browser extensions are installed by observing extension resources, DOM behavior, messages, timing, or page-visible side effects.
WebExtension content scripts and match patterns
Context: The pipeline parses `content_scripts` manifest entries and URL match patterns to find extensions whose CSS applies on any domain.
Meaning: Content scripts are extension-provided JavaScript or CSS files injected into matching pages, with match patterns defining the URL set where they run.
manifest.json
Context: Declarative CSS injection is detected by reading each extension's `manifest.json` and its `content_scripts` CSS declarations.
Meaning: A browser-extension manifest describes an extension's metadata, permissions, resources, scripts, and other behavior that the browser should apply.
Programmatic CSS injection
Context: The paper uses Mystique to observe dynamic CSS insertion through `chrome.tabs.insertCSS`; current Chrome extension documentation uses the Manifest V3 `chrome.scripting.insertCSS()` API.
Meaning: Programmatic CSS injection lets extension code insert style sheets into a target tab or frame at runtime instead of only declaring CSS statically in the manifest.
The paper's `tabs.insertCSS` terminology reflects the Chrome extension API surface used by the measured 2019 extension corpus; Manifest V3 documentation points developers to `scripting.insertCSS()`.
Web accessible resources (WAR)
Context: WAR probing is one of the prior extension-fingerprinting methods used in the overlap comparison against CSS fingerprinting.
Meaning: Web accessible resources are extension-bundled files that web pages or other extensions are allowed to request directly.
CSS cascade origins and extension-origin styles
Context: Appendix A proposes marking extension rules as `ExtensionAuthor` or `ExtensionUser` origins while preserving normal cascade priority.
Meaning: CSS cascade origins describe where style declarations come from, such as author, user, and user-agent origins; the paper extends that model as a browser-vendor defense sketch.
Needs review: the Chromium link is a component-level source lead for Blink rendering stages, not evidence that the paper's proposed `ExtensionAuthor` or `ExtensionUser` names exist in Chromium.
:visited history-leak mitigation
Context: The background section compares this extension-style leak to older history-sniffing attacks through `getComputedStyle` on visited links.
Meaning: Browsers restrict what pages can learn from `:visited` styling and may return privacy-preserving style values to script APIs.
Statistics and Measurement Concepts
Uniquely identifiable fingerprint
Context: The headline result is 4,446 extensions uniquely identifiable after trigger confirmation and collision filtering.
Meaning: A uniquely identifiable fingerprint is a signal or signal combination that maps to one measured entity in the evaluated corpus under the paper's matching rules.
Fingerprint collision and collision cluster
Context: The method removes triggers that collide across extensions and later analyzes clusters of non-unique style fingerprints.
Meaning: In this report, a collision occurs when distinct extensions produce the same observed trigger, property, and value signature.
The reference explains collision as a general computer-science concept; the report applies the idea to style-fingerprint signatures rather than hash-table entries.
Entropy
Context: The report cautions that collision clusters can still add identifying information even when they do not identify a single extension.
Meaning: Entropy is a measure of uncertainty or information; in fingerprinting discussions, rarer observations can contribute more identifying information than common ones.
95% confidence interval
Context: Figure 6 reports detection-time benchmark whiskers as 95% confidence intervals over repeated measurements.
Meaning: A confidence interval estimates a range of plausible values for a population parameter under a specified statistical procedure and confidence level.
Longitudinal analysis
Context: The authors use historical Chrome extension versions from 2014 to 2019 and a 2020 retest to evaluate stability over time.
Meaning: A longitudinal study follows observations over time so changes and persistence can be measured rather than inferred from one snapshot.
Correlation
Context: The report notes that the paper does not observe a clear relationship between extension popularity and CSS fingerprintability.
Meaning: Correlation measures association between variables; absence of a clear observed correlation should not be read as proof that no relationship can exist in every population or later dataset.
Tools, Datasets, and Browser Internals
Chrome Web Store corpus
Context: The measurement corpus is 116,485 Chrome Web Store extensions collected in April 2019 after excluding themes and apps.
Meaning: The Chrome Web Store is Google's distribution channel for Chrome extensions and themes; the paper's corpus is a historical crawl, not a current store snapshot.
Selenium
Context: The pipeline uses Selenium to run each extension against generated test pages during dynamic trigger confirmation.
Meaning: Selenium is a browser automation project centered on WebDriver, which drives real browsers through standardized automation commands.
Puppeteer
Context: The countermeasure evaluation uses Puppeteer to pilot Chrome while loading the Tranco top 200 homepages.
Meaning: Puppeteer is a browser automation library for controlling Chrome or Chromium from Node.js.
Tranco
Context: The prototype defense is evaluated on the Tranco top 200 homepages.
Meaning: Tranco is a research-oriented top-sites ranking designed to be more robust against manipulation than simple popularity lists.
VisibleV8
Context: The authors use VisibleV8 to crawl the Alexa top 100K and measure how often scripts access `getComputedStyle`.
Meaning: VisibleV8 is an instrumented V8 variant that logs JavaScript API calls and selected property accesses for browser measurement studies.
Blink rendering and style pipeline
Context: Appendix A discusses a browser-native defense that would modify style computation and retrieval inside Chromium-family browsers.
Meaning: Blink is Chromium's rendering engine, and its core rendering stages include DOM, style, layout, and paint work.
Needs review: these are component-level leads for the rendering pipeline, not a precise source-file mapping for the paper's proposed browser changes.
fingerprinting-in-style artifact repository
Context: The report links the authors' companion artifact and keeps reconstructed code snippets separate from the original implementation.
Meaning: The repository is the paper's companion artifact, including materials for the style-fingerprinting work and defense prototype.