Multiple fingerprinting mitigations: removes unnecessary mitigation related to client rects as already covered by viewport protection (#2182 #521)

This commit is contained in:
Carmelo Messina
2025-08-20 09:49:48 +02:00
parent 16a3bb2571
commit 7fe8f0cac8
@@ -2,15 +2,10 @@ From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Fri, 30 Mar 2018 10:09:03 +0200
Subject: Multiple fingerprinting mitigations
1. getClientRects, getBoundingClientRect, measureText: add fingerprinting mitigation
1. measureText: add fingerprinting mitigation
Scale the result of Range::getClientRects, Element::getBoundingClientRect and
Canvas::measureText by a random +/-3/1000000th of the original value for each
float in the returned Rect/Quad.
It contains improvements from ungoogled-chromium which add two flags:
1. --fingerprinting-client-rects-noise to enable fingerprinting deception for Range::getClientRects and Element::getBoundingClientRect
2. --fingerprinting-canvas-measuretext-noise to enable fingerprinting deception for Canvas::measureText
Scale the result of Canvas::measureText by a random +/-3/1000000th of
the original value for each float in the returned Rect/Quad.
2. Canvas: fingerprinting mitigations for image data
@@ -29,32 +24,29 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
chrome/browser/BUILD.gn | 1 +
chrome/browser/about_flags.cc | 2 +
content/browser/BUILD.gn | 1 +
.../renderer_host/render_process_host_impl.cc | 4 +
.../renderer_host/render_process_host_impl.cc | 3 +
content/child/BUILD.gn | 1 +
content/child/runtime_features.cc | 8 +
.../Multiple-fingerprinting-mitigations.inc | 16 ++
.../public/platform/web_runtime_features.h | 3 +
.../blink/renderer/core/dom/document.cc | 20 +++
content/child/runtime_features.cc | 6 +
.../Multiple-fingerprinting-mitigations.inc | 12 ++
.../public/platform/web_runtime_features.h | 2 +
.../blink/renderer/core/dom/document.cc | 19 +++
.../blink/renderer/core/dom/document.h | 7 +
.../blink/renderer/core/dom/element.cc | 8 +
third_party/blink/renderer/core/dom/range.cc | 12 +-
.../html/canvas/canvas_async_blob_creator.cc | 4 +
.../renderer/core/html/canvas/text_metrics.cc | 18 ++
.../renderer/core/html/canvas/text_metrics.h | 2 +
.../renderer/core/svg/svg_graphics_element.cc | 2 +
.../core/svg/svg_text_content_element.cc | 28 +++-
.../canvas2d/base_rendering_context_2d.cc | 24 ++-
third_party/blink/renderer/platform/BUILD.gn | 5 +-
.../platform/exported/web_runtime_features.cc | 13 ++
.../platform/exported/web_runtime_features.cc | 9 +
.../platform/graphics/image_data_buffer.cc | 8 +
.../platform/graphics/static_bitmap_image.cc | 154 ++++++++++++++++++
.../platform/graphics/static_bitmap_image.h | 2 +
.../platform/runtime_enabled_features.json5 | 9 +
.../platform/runtime_enabled_features.json5 | 6 +
third_party/skia/include/core/SkPixmap.h | 16 +-
third_party/ungoogled/BUILD.gn | 10 ++
third_party/ungoogled/ungoogled_switches.cc | 18 ++
third_party/ungoogled/ungoogled_switches.h | 18 ++
28 files changed, 397 insertions(+), 17 deletions(-)
third_party/ungoogled/ungoogled_switches.cc | 15 ++
third_party/ungoogled/ungoogled_switches.h | 17 ++
25 files changed, 356 insertions(+), 16 deletions(-)
create mode 100755 cromite_flags/chrome/browser/about_flags_cc/Multiple-fingerprinting-mitigations.inc
create mode 100644 third_party/ungoogled/BUILD.gn
create mode 100644 third_party/ungoogled/ungoogled_switches.cc
@@ -105,11 +97,10 @@ diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content
#if BUILDFLAG(IS_ANDROID)
#include "base/android/child_process_binding_types.h"
#include "content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h"
@@ -3477,6 +3478,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
@@ -3477,6 +3478,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableBestEffortTasks,
switches::kDisableBreakpad,
switches::kDisableFileSystem,
+ switches::kFingerprintingClientRectsNoise,
+ switches::kFingerprintingCanvasMeasureTextNoise,
+ switches::kFingerprintingCanvasImageDataNoise,
switches::kDisableFrameRateLimit,
@@ -138,12 +129,10 @@ diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.
#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#endif
@@ -520,6 +522,12 @@ void SetRuntimeFeaturesFromCommandLine(const base::CommandLine& command_line) {
@@ -520,6 +522,10 @@ void SetRuntimeFeaturesFromCommandLine(const base::CommandLine& command_line) {
// as a last resort.
void SetCustomizedRuntimeFeaturesFromCombinedArgs(
const base::CommandLine& command_line) {
+ WebRuntimeFeatures::EnableFingerprintingClientRectsNoise(
+ !command_line.HasSwitch(switches::kFingerprintingClientRectsNoise));
+ WebRuntimeFeatures::EnableFingerprintingCanvasMeasureTextNoise(
+ !command_line.HasSwitch(switches::kFingerprintingCanvasMeasureTextNoise));
+ WebRuntimeFeatures::EnableFingerprintingCanvasImageDataNoise(
@@ -155,17 +144,13 @@ diff --git a/cromite_flags/chrome/browser/about_flags_cc/Multiple-fingerprinting
new file mode 100755
--- /dev/null
+++ b/cromite_flags/chrome/browser/about_flags_cc/Multiple-fingerprinting-mitigations.inc
@@ -0,0 +1,16 @@
@@ -0,0 +1,12 @@
+#ifdef FLAG_SECTION
+
+ {"fingerprinting-canvas-image-data-noise",
+ "Disable Canvas image data fingerprint deception",
+ "Slightly modifies at most 20 pixels in Canvas image data extracted via JS APIs",
+ kOsAll, SINGLE_DISABLE_VALUE_TYPE(switches::kFingerprintingCanvasImageDataNoise)},
+ {"fingerprinting-client-rects-noise",
+ "Disable get*ClientRects() fingerprint deception",
+ "Scale the output values of Range::getClientRects() and Element::getBoundingClientRect() with a randomly selected factor in the range -0.0003% to 0.0003%, which are recomputed on every document initialization.",
+ kOsAll, SINGLE_DISABLE_VALUE_TYPE(switches::kFingerprintingClientRectsNoise)},
+ {"fingerprinting-canvas-measuretext-noise",
+ "Disable Canvas::measureText() fingerprint deception",
+ "Scale the output values of Canvas::measureText() with a randomly selected factor in the range -0.0003% to 0.0003%, which are recomputed on every document initialization.",
@@ -175,11 +160,10 @@ new file mode 100755
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -66,6 +66,9 @@ class BLINK_PLATFORM_EXPORT WebRuntimeFeatures : public WebRuntimeFeaturesBase {
@@ -66,6 +66,8 @@ class BLINK_PLATFORM_EXPORT WebRuntimeFeatures : public WebRuntimeFeaturesBase {
static void UpdateStatusFromBaseFeatures();
static void EnableOverlayScrollbars(bool);
+ static void EnableFingerprintingClientRectsNoise(bool);
+ static void EnableFingerprintingCanvasMeasureTextNoise(bool);
+ static void EnableFingerprintingCanvasImageDataNoise(bool);
static void EnableFluentScrollbars(bool);
@@ -196,12 +180,11 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
@@ -984,6 +985,17 @@ Document::Document(const DocumentInit& initializer,
@@ -984,6 +985,16 @@ Document::Document(const DocumentInit& initializer,
TRACE_EVENT_WITH_FLOW0("blink", "Document::Document", TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(agent_);
+ if (RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled() ||
+ RuntimeEnabledFeatures::FingerprintingCanvasMeasureTextNoiseEnabled() ||
+ if (RuntimeEnabledFeatures::FingerprintingCanvasMeasureTextNoiseEnabled() ||
+ RuntimeEnabledFeatures::FingerprintingCanvasImageDataNoiseEnabled()) {
+ // Precompute -0.0003% to 0.0003% noise factor for get*ClientRect*() fingerprinting
+ noise_factor_x_ = 1.0 + (base::RandDouble() - 0.5) * 0.0003;
@@ -214,7 +197,7 @@ diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink
if (base::FeatureList::IsEnabled(features::kDelayAsyncScriptExecution) &&
features::kDelayAsyncScriptExecutionDelayByDefaultParam.Get()) {
script_runner_delayer_->Activate();
@@ -2647,6 +2659,14 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
@@ -2647,6 +2658,14 @@ void Document::UpdateStyleAndLayoutTreeForThisDocument() {
#endif
}
@@ -253,67 +236,6 @@ diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/
Member<ScriptRunner> script_runner_;
Member<ScriptRunnerDelayer> script_runner_delayer_;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2990,6 +2990,7 @@ void Element::ClientQuads(Vector<gfx::QuadF>& quads) const {
quads.push_back(element_layout_object->LocalToAbsoluteQuad(
gfx::QuadF(element_layout_object->ObjectBoundingBox())));
}
+ //TODO: cover this as well
return;
}
@@ -2998,6 +2999,10 @@ void Element::ClientQuads(Vector<gfx::QuadF>& quads) const {
element_layout_object->IsBR()) {
element_layout_object->AbsoluteQuads(quads);
}
+ if (RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled()) {
+ for (auto& quad : quads)
+ quad.Scale(GetDocument().GetNoiseFactorX(), GetDocument().GetNoiseFactorY());
+ }
}
DOMRectList* Element::getClientRects() {
@@ -3043,6 +3048,9 @@ gfx::RectF Element::GetBoundingClientRectNoLifecycleUpdate() const {
DCHECK(element_layout_object);
GetDocument().AdjustRectForScrollAndAbsoluteZoom(result,
*element_layout_object);
+ if (RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled()) {
+ result.Scale(GetDocument().GetNoiseFactorX(), GetDocument().GetNoiseFactorY());
+ }
return result;
}
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc
--- a/third_party/blink/renderer/core/dom/range.cc
+++ b/third_party/blink/renderer/core/dom/range.cc
@@ -1646,6 +1646,12 @@ DOMRectList* Range::getClientRects() const {
Vector<gfx::QuadF> quads;
GetBorderAndTextQuads(quads);
+ if (RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled()) {
+ for (auto& quad : quads) {
+ quad.Scale(owner_document_->GetNoiseFactorX(), owner_document_->GetNoiseFactorY());
+ }
+ }
+
return MakeGarbageCollected<DOMRectList>(quads);
}
@@ -1784,7 +1790,11 @@ gfx::RectF Range::BoundingRect() const {
// If all rects are empty, return the first rect.
if (result.IsEmpty() && !quads.empty())
- return quads.front().BoundingBox();
+ result = quads.front().BoundingBox();
+
+ if (!result.IsEmpty() && RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled()) {
+ result.Scale(owner_document_->GetNoiseFactorX(), owner_document_->GetNoiseFactorY());
+ }
return result;
}
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -375,18 +297,6 @@ diff --git a/third_party/blink/renderer/core/html/canvas/text_metrics.h b/third_
private:
void Update(const Font*,
const TextDirection& direction,
diff --git a/third_party/blink/renderer/core/svg/svg_graphics_element.cc b/third_party/blink/renderer/core/svg/svg_graphics_element.cc
--- a/third_party/blink/renderer/core/svg/svg_graphics_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_graphics_element.cc
@@ -167,6 +167,8 @@ SVGRectTearOff* SVGGraphicsElement::getBBoxFromJavascript() {
if (const auto* layout_object = GetLayoutObject()) {
bounding_box = GetBBox();
+ if (RuntimeEnabledFeatures::FingerprintingClientRectsNoiseEnabled())
+ bounding_box.Scale(GetDocument().GetNoiseFactorX(), GetDocument().GetNoiseFactorY());
if (layout_object->IsSVGInline()) {
UseCounter::Count(GetDocument(), WebFeature::kGetBBoxForText);
}
diff --git a/third_party/blink/renderer/core/svg/svg_text_content_element.cc b/third_party/blink/renderer/core/svg/svg_text_content_element.cc
--- a/third_party/blink/renderer/core/svg/svg_text_content_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_text_content_element.cc
@@ -543,15 +453,11 @@ diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/re
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -68,4 +68,17 @@ void WebRuntimeFeatures::EnableFluentScrollbars(bool enable) {
@@ -68,4 +68,13 @@ void WebRuntimeFeatures::EnableFluentScrollbars(bool enable) {
void WebRuntimeFeatures::EnableFluentOverlayScrollbars(bool enable) {
RuntimeEnabledFeatures::SetFluentOverlayScrollbarsEnabled(enable);
}
+
+void WebRuntimeFeatures::EnableFingerprintingClientRectsNoise(bool enable) {
+ RuntimeEnabledFeatures::SetFingerprintingClientRectsNoiseEnabled(enable);
+}
+
+void WebRuntimeFeatures::EnableFingerprintingCanvasMeasureTextNoise(bool enable) {
+ RuntimeEnabledFeatures::SetFingerprintingCanvasMeasureTextNoiseEnabled(enable);
+}
@@ -778,14 +684,11 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3367,6 +3367,15 @@
@@ -3367,6 +3367,12 @@
status: {"Mac": "test", "default": "stable"},
base_feature: "none",
},
+ {
+ name: "FingerprintingClientRectsNoise",
+ },
+ {
+ name: "FingerprintingCanvasMeasureTextNoise",
+ },
+ {
@@ -860,7 +763,7 @@ diff --git a/third_party/ungoogled/ungoogled_switches.cc b/third_party/ungoogled
new file mode 100644
--- /dev/null
+++ b/third_party/ungoogled/ungoogled_switches.cc
@@ -0,0 +1,18 @@
@@ -0,0 +1,15 @@
+// Copyright (c) 2018 The ungoogled-chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
@@ -869,9 +772,6 @@ new file mode 100644
+
+namespace switches {
+
+// Enable fingerprinting deception for getClientRects and getBoundingClientRect
+const char kFingerprintingClientRectsNoise[] = "fingerprinting-client-rects-noise";
+
+// Enable fingerprinting deception for measureText
+const char kFingerprintingCanvasMeasureTextNoise[] = "fingerprinting-canvas-measuretext-noise";
+
@@ -883,7 +783,7 @@ diff --git a/third_party/ungoogled/ungoogled_switches.h b/third_party/ungoogled/
new file mode 100644
--- /dev/null
+++ b/third_party/ungoogled/ungoogled_switches.h
@@ -0,0 +1,18 @@
@@ -0,0 +1,17 @@
+// Copyright (c) 2018 The ungoogled-chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
@@ -895,7 +795,6 @@ new file mode 100644
+
+namespace switches {
+
+extern const char kFingerprintingClientRectsNoise[];
+extern const char kFingerprintingCanvasMeasureTextNoise[];
+extern const char kFingerprintingCanvasImageDataNoise[];
+