Console Fingerprinting: Not a Big Threat, But We'll Do It Anyway

2023-09-28

The web console provided by modern browsers offers developers invaluable insight into their web applications. However, variances between browser implementations also introduce the possibility of using the console as a fingerprinting vector. While console fingerprinting is unlikely to be deployed in the wild, here at personaldata.info, we try to fingerprint everything we can get our hands on. It serves as an illustrative example of how nearly any browser feature can aid fingerprinting efforts.

Accessing the Console

The console is accessible via the global console object in any browser context. For example:

console.log("Hello world!");

Will output the string “Hello world!” to the console in all major browsers.

Beyond logging output, the console object also exposes various utility methods like console.error(), console.warn(), and console.time(). The full set of methods available varies between browsers.

Styling Console Output

One simple test is styling console output using CSS. For example:

console.log("%cBlue text", "color: blue;");

Will output the text “Blue text” colored blue in supporting browsers. Support for styled output differs across browsers. Most modern browsers support css styled console logs, but some older browsers may not. So this simple test already allows distinguishing between some browsers.

Emoji Support

Just like styled output, printing emoji characters to the console is another area where browser support may vary. Some older browsers may lack support for logging emoji characters to the console. Testing for emoji support simply involves logging a test emoji to the console:

console.log("🎉 Party time!");

If this throws an error, emojis are not supported. Being able to print emojis to the console indicates a more modern browser build. So testing for emoji support produces another variance that aids fingerprinting efforts.

Console Methods

The set of functions exposed by the console object creates significant potential for fingerprinting. Looping through the console object reveals the available methods:

for (let method in console) {
  if (typeof console[method] === "function") {
    console.log(method);
  }
}

Running this in various browsers demonstrates small differences in exposed functions between Chrome, Firefox, and Safari.

For example, Firefox lacks support for console.createTask(), where Chrome supports it. Another example is in Firefox console.exception is an alias for error(). Along with those, the order in which these methods appear in the console object can also aid in fingerprinting because, in most hashing algorithms, the order in which items appear will result in different hashes.

Fingerprinting Method

To create a console-based fingerprint:

  1. Test for styled output support.
  2. Print an emoji character.
  3. Loop through available console methods.
  4. Output sample data to test for extension behaviors.
  5. Hash the results into a fingerprint string.

For example:

// Helper to hash text with SHA-256
function hash(text) {
  return crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))
    .then(buffer => {
      return Array.from(new Uint8Array(buffer))
        .map(b => b.toString(16).padStart(2, "0"))
        .join("");
    });
}

async function getConsoleFingerprint() {

  let results = [];

  // Test styled output
  console.log("%cStyling test", "font-size: 2em");

  if (/%c/.test(console.log.toString())) {
    results.push("styled");
  } else {
    results.push("plain");
  }

  // Test emoji output
  try {
    console.log("🎉");
    results.push("emoji");
  } catch {
    results.push("no emoji");
  }

  // Log methods
  let methods = [];
  for (let method in console) {
    if (typeof console[method] === "function") {
      methods.push(method);
    }
  }
  results.push(`methods: ${methods.join(",")}`);

  // Test for React DevTools
  console.log({name: "John", age: 30});

  // Hash and return fingerprint
  const fp = await hash(results.join(";"));
  return fp;

}

getConsoleFingerprint().then(fp => {
  console.log("Fingerprint:", fp);
});

This provides a simple characterization of the console environment, fingerprinting both browser differences and extension behaviors.

Limitations

While illustrative of the fingerprinting potential inherent in nearly any browser feature, console fingerprinting has limitations as a practical fingerprinting vector:

  • The console API is not available in all browsing contexts.
  • Very limited fingerprinting potential.
  • Just like any other fingerprinting method, console fingerprinting, while limited, still raises privacy concerns.

Nonetheless, the console exemplifies the fingerprinting risks inherent in common browser APIs, even those intended for developers. Virtually any feature from CSS support to audio contexts to device sensors can be probed for identifying variances. With privacy and fingerprinting concerns on the rise, browser vendors face increasing pressure to limit access to APIs or reduce the fidelity of their implementations.

Conclusion

While the browser console may initially appear to be an unlikely vector for fingerprinting, it harbors distinctive traits like styling peculiarities, emoji compatibility, unique API methods, and extension adaptations that can reveal identifying information. However, the question of whether console fingerprinting should cause alarm leads us to a reassuring answer: No, it typically reveals a minimal amount of information and is rarely employed in commercial applications.

The primary objective of this brief post was to shed light on the latent fingerprinting potential concealed within most browser features. The console exemplifies how even unlikely features can aid in fingerprinting if there are variations between different devices and browsers. Browser vendors should follow the principle of data minimization, granting access only to information essential for web applications. With privacy and fingerprinting concerns on the rise, developers and vendors alike must make privacy and security foundational priorities in all aspects of browser design.