<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feed/pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>Sagar Mohan - Blog</title>
  <subtitle>Notes on embedded security, firmware hacking, systems research and other miscellaneous things.</subtitle>
  <link href="https://sagar.systems/feed.xml" rel="self" />
  <link href="https://sagar.systems/" />
  <updated>2026-05-30T00:00:00Z</updated>
  <id>https://sagar.systems/</id>
  <author>
    <name>Sagar Mohan</name>
  </author>
  <entry>
    <title>Unravelling ACR on Samsung TVs</title>
    <link href="https://sagar.systems/blog/acr/" />
    <updated>2026-05-30T00:00:00Z</updated>
    <id>https://sagar.systems/blog/acr/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;Every frame on the screen, from Netflix, your console, broadcast TV, to even a screen-mirrored phone, is fingerprinted and sent to Samsung roughly once a minute, on a schedule Samsung can change remotely. Here&#39;s the evidence, pulled straight from the firmware of a 2024/2025 Samsung S90D.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;tl-dr&quot; tabindex=&quot;-1&quot;&gt;TL;DR &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#tl-dr&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The S90D runs &lt;strong&gt;Automatic Content Recognition (ACR)&lt;/strong&gt;: it samples the picture
~2× per second and uploads perceptual &lt;strong&gt;fingerprints&lt;/strong&gt; to Samsung&#39;s cloud
about &lt;strong&gt;every 60 seconds&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Capture happens at the &lt;strong&gt;display compositor inside TrustZone&lt;/strong&gt;, &lt;em&gt;before&lt;/em&gt; HDCP, so it is &lt;strong&gt;source-agnostic&lt;/strong&gt; and captures &lt;strong&gt;DRM-protected streaming&lt;/strong&gt;
(Netflix included) in the clear.&lt;/li&gt;
&lt;li&gt;Confirmed in-scope sources: &lt;strong&gt;Samsung TV+, third-party streaming apps, HDMI
inputs, antenna/broadcast (tuner)&lt;/strong&gt;; screen mirroring has its own recognition
path too. The one exemption: &lt;strong&gt;no fingerprinting at power-on&lt;/strong&gt;. The upload
engine is &lt;code&gt;on-boot=&amp;quot;false&amp;quot;&lt;/code&gt; and wakes when a source becomes active.&lt;/li&gt;
&lt;li&gt;Fingerprints upload to &lt;strong&gt;&lt;code&gt;acr-us-prd.samsungcloud.tv&lt;/code&gt;&lt;/strong&gt;, an address the TV is
&lt;strong&gt;handed at runtime&lt;/strong&gt; by the control plane
&lt;strong&gt;&lt;code&gt;osb-v2.samsungqbe.com/service/acr/v2&lt;/code&gt;&lt;/strong&gt;, so Samsung controls &lt;em&gt;where&lt;/em&gt; the
data goes, not just what&#39;s collected.&lt;/li&gt;
&lt;li&gt;The query &lt;strong&gt;interval is server-controlled&lt;/strong&gt;. The binary literally logs
&lt;code&gt;Query Int from server(60 is set)&lt;/code&gt;. Samsung can dial the cadence up or down
without a firmware update.&lt;/li&gt;
&lt;li&gt;Fingerprints are uploaded &lt;strong&gt;whether or not the server recognizes the
content&lt;/strong&gt;. Samsung receives the data either way.&lt;/li&gt;
&lt;li&gt;The same process holds your &lt;strong&gt;Samsung Account identity, ad PSID, and ad
targeting group&lt;/strong&gt;, so viewing data can be joined to who you are.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;acr-aint-anything-new&quot; tabindex=&quot;-1&quot;&gt;ACR ain&#39;t anything new &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#acr-aint-anything-new&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ACR turns your TV into a measurement device. It periodically samples what&#39;s on
screen, reduces each frame to a compact &lt;strong&gt;fingerprint&lt;/strong&gt;, and sends those
fingerprints to a cloud service that matches them against a reference database
to identify the show, channel, or ad. The result feeds viewing analytics and
ad targeting.&lt;/p&gt;
&lt;p&gt;This isn&#39;t hypothetical. In 2017 the FTC and New Jersey settled with &lt;strong&gt;Vizio&lt;/strong&gt;
for &lt;strong&gt;$2.2M&lt;/strong&gt; over ACR that tracked viewing without clear consent. The question
for any given TV is no longer &lt;em&gt;whether&lt;/em&gt; it has ACR, but &lt;strong&gt;exactly what it
captures, where it sends it, how often, and how it&#39;s tied to your identity.&lt;/strong&gt;
This post answers those four questions for the Samsung S90D with firmware-level
evidence.&lt;/p&gt;
&lt;h2 id=&quot;1-every-source-is-in-scope&quot; tabindex=&quot;-1&quot;&gt;1. Every source is in scope &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#1-every-source-is-in-scope&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The capture itself is &lt;strong&gt;source-agnostic&lt;/strong&gt;: the S90D grabs the final composited
image at the &lt;strong&gt;display compositor&lt;/strong&gt; through a &lt;strong&gt;TrustZone (TEE)&lt;/strong&gt; secure call
(&lt;code&gt;TZCAPTURE_Capture_screen&lt;/code&gt; in &lt;code&gt;libtzcapturec.so&lt;/code&gt;), at &lt;strong&gt;960×540 YUV&lt;/strong&gt;. Because
this happens &lt;em&gt;after&lt;/em&gt; rendering but &lt;em&gt;before&lt;/em&gt; HDCP output encryption, it sees
&lt;strong&gt;whatever is on the panel&lt;/strong&gt;, regardless of source and regardless of DRM.
Separate logic then &lt;em&gt;labels&lt;/em&gt; what produced that image, and the firmware has
explicit handling for each input type:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;In scope?&lt;/th&gt;
&lt;th&gt;What the firmware shows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Samsung TV+ (first-party)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;org.tizen.tv-viewer&lt;/code&gt; in the binary; live &lt;code&gt;source_APP_Id&lt;/code&gt; of &lt;code&gt;org.tizen.tv-viewer(tvplus)&lt;/code&gt; with a 7-stream match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming apps (Netflix, Max, Peacock, YouTube…)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;captured live during Netflix playback (labeled &lt;code&gt;ACR_SOURCE_EXT_1&lt;/code&gt;); IACR ships per-app metadata (e.g. YouTube)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDMI inputs (console, PC, cable box)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;IsHDMISource&lt;/code&gt;, &lt;code&gt;IsHDMIPort&lt;/code&gt;, &lt;code&gt;HDMIport : %d DeviceName : %s Device Type : %d&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Antenna / broadcast (tuner, STB)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;IsCUDSSTBAvailable&lt;/code&gt;, &lt;code&gt;IsStateSTBContent&lt;/code&gt;, tuner libraries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screen mirroring / cast&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Likely&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;dedicated &lt;code&gt;mirroring-recognition-manager&lt;/code&gt; (boot-resident service)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;At power-on (boot)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;upload service manifest &lt;code&gt;on-boot=&amp;quot;false&amp;quot;&lt;/code&gt;; nothing is fingerprinted until a source is active&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;It tracks &lt;strong&gt;up to six concurrent external-source slots&lt;/strong&gt;
(&lt;code&gt;ACR_SOURCE_EXT_1…6&lt;/code&gt;). During testing, a third-party streaming app showed up as
&lt;code&gt;ACR_SOURCE_EXT_1&lt;/code&gt;, confirming these slots cover external apps and HDMI inputs
alike.&lt;/p&gt;
&lt;h2 id=&quot;2-where-does-it-phone-home&quot; tabindex=&quot;-1&quot;&gt;2. Where does it phone home? &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#2-where-does-it-phone-home&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;acr&lt;/code&gt; binary doesn&#39;t fix the server it ultimately uploads to. It &lt;strong&gt;asks a
control server at runtime&lt;/strong&gt; and is handed the target. The binary contains the
bootstrap endpoint and the machinery for this (&lt;code&gt;GetAcrInfo&lt;/code&gt;,
&lt;code&gt;GetControlServerAddress&lt;/code&gt;, &lt;code&gt;MatchingServerURL&lt;/code&gt; / &lt;code&gt;IAMatchingServerURL&lt;/code&gt;,
&lt;code&gt;m_RequestDataToControlServer&lt;/code&gt;). On the live device, the hosts actually in use
were:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Where it was found&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;acr-us-stg.internetat.tv/getacrinfo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bootstrap &amp;quot;GetAcrInfo&amp;quot; endpoint&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Hardcoded&lt;/strong&gt; in the &lt;code&gt;acr&lt;/code&gt; binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;osb-v2.samsungqbe.com/service/acr/v2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Control plane&lt;/strong&gt;: config, app list, server URLs, query intervals&lt;/td&gt;
&lt;td&gt;Live process memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;acr0.samsungcloudsolution.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Control/status server (&lt;code&gt;ControlServer&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Live process memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;acr-us-prd.samsungcloud.tv:443&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Production fingerprint upload / matching&lt;/strong&gt; server&lt;/td&gt;
&lt;td&gt;Live process memory (delivered as &lt;code&gt;IAMatchingServerURL&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The control-plane request identifies the exact device and turns the pipeline on:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://osb-v2.samsungqbe.com/service/acr/v2
  ?countryCode=US&amp;amp;modelid=24_PTM_QD_T09
  &amp;amp;infolink=T-PTMDAKUC-0090-2123.9&amp;amp;internalacr=on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because the upload target is &lt;strong&gt;delivered by the control server rather than fixed
in firmware&lt;/strong&gt;, Samsung can change &lt;em&gt;where&lt;/em&gt; fingerprints go, just as it can
change &lt;em&gt;how often&lt;/em&gt; (next section). The &lt;code&gt;acr-us-*&lt;/code&gt; / &lt;code&gt;countryCode=US&lt;/code&gt; naming
indicates US-region servers.&lt;/p&gt;
&lt;h2 id=&quot;3-frequency-and-control-granularity&quot; tabindex=&quot;-1&quot;&gt;3. Frequency and Control Granularity &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#3-frequency-and-control-granularity&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The TEE captures frames frequently, &lt;strong&gt;as often as ~every half-second&lt;/strong&gt; (the
analyzer logs &lt;code&gt;Waiting for 480.333 ms&lt;/code&gt; and &lt;code&gt;497.181 ms&lt;/code&gt;; the interval varies).&lt;/li&gt;
&lt;li&gt;Fingerprints are bundled (&lt;strong&gt;2-3+ frames&lt;/strong&gt;) and uploaded on a &lt;strong&gt;main query
interval of 60 s by default&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Two more pipelines run in parallel: an &lt;strong&gt;ad query&lt;/strong&gt; (~&lt;strong&gt;120 s&lt;/strong&gt;) and a
&lt;strong&gt;broadcast query&lt;/strong&gt; (~&lt;strong&gt;300 s&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Crucially, &lt;strong&gt;these intervals are server-controlled.&lt;/strong&gt; The binary&#39;s own log line
is &lt;code&gt;Query Int from server(60 is set)&lt;/code&gt;, and the control-plane response carries
&lt;code&gt;queryIntervalSec&lt;/code&gt;, &lt;code&gt;adQueryIntervalSec&lt;/code&gt;, and &lt;code&gt;minQueryCount&lt;/code&gt;/&lt;code&gt;maxQueryCount&lt;/code&gt;.
Samsung can change how aggressively your TV fingerprints &lt;strong&gt;remotely, without a
firmware update&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;4-anatomy-of-a-query&quot; tabindex=&quot;-1&quot;&gt;4. Anatomy of a query &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#4-anatomy-of-a-query&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Each frame is reduced to &lt;strong&gt;4 Regions of Interest&lt;/strong&gt;, each a set of four 32-bit
integers (512 bits/frame), and every frame is stamped with &lt;strong&gt;millisecond UTC
plus your timezone offset&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;fps&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;raws&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;u32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;u32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;u32&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;u32&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;roi&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; … &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;roi&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;tvt&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;utc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1779224946340&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;tz&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;-300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two outcomes, both observed live:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Netflix (Arrested Development):&lt;/strong&gt; every frame came back &lt;code&gt;matching:false&lt;/code&gt;.
Samsung&#39;s database didn&#39;t recognize it. &lt;strong&gt;The fingerprints were uploaded
anyway.&lt;/strong&gt; The engine does &lt;em&gt;not&lt;/em&gt; stop on unrecognized content.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung TV+ (live news):&lt;/strong&gt; a single query matched &lt;strong&gt;seven streams at once&lt;/strong&gt;,
each with channel, &lt;strong&gt;program title, genre, and a &lt;code&gt;contentOffset&lt;/code&gt;&lt;/strong&gt;, e.g. an
offset of ~68m55s, which combined with the program&#39;s start time reveals
&lt;em&gt;exactly&lt;/em&gt; when you tuned in and how long you&#39;d been watching.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So matching is a &lt;em&gt;server-side&lt;/em&gt; step. Whether or not your content is in Samsung&#39;s
database, &lt;strong&gt;Samsung receives the fingerprints&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;5-it-captures-drm-protected-content&quot; tabindex=&quot;-1&quot;&gt;5. It captures DRM-protected content &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#5-it-captures-drm-protected-content&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because capture is &lt;strong&gt;pre-HDCP, at the compositor, inside TrustZone&lt;/strong&gt;, content
protection doesn&#39;t stop it. The live Netflix fingerprints are the proof: a
&lt;strong&gt;Widevine-DRM&lt;/strong&gt; stream was sampled and uploaded in cleartext YUV, invisible to
the Netflix app. ACR sees what the panel shows, not what the app &amp;quot;allows.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;6-tied-to-who-you-are&quot; tabindex=&quot;-1&quot;&gt;6. Tied to who you are &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#6-tied-to-who-you-are&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ACR isn&#39;t anonymous telemetry. The recognition process reads, and holds in
memory alongside the upload logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;your &lt;strong&gt;ad identifier&lt;/strong&gt; (&lt;code&gt;db/adagent/psid&lt;/code&gt;) and &lt;strong&gt;ad targeting group&lt;/strong&gt;
(&lt;code&gt;db/comss/targetgrouptag&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;your &lt;strong&gt;Samsung Account&lt;/strong&gt; state and a live &lt;strong&gt;SSO token&lt;/strong&gt; (the same token also
appears in the TV+ daemon, it&#39;s reused across subsystems),&lt;/li&gt;
&lt;li&gt;your &lt;strong&gt;country, device ID, timezone, and entered ZIP code&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means a viewing fingerprint can be joined to your account and your
advertising profile. The viewing record and the identity that makes it
&lt;em&gt;targetable&lt;/em&gt; live in the same place.&lt;/p&gt;
&lt;h2 id=&quot;7-consent-is-one-checkbox&quot; tabindex=&quot;-1&quot;&gt;7. Consent is one checkbox &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#7-consent-is-one-checkbox&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All of this is gated behind a &lt;strong&gt;single binary disclaimer flag&lt;/strong&gt;
(&lt;code&gt;HOMEDATACONTROL_DISCLAIMERAGREES&lt;/code&gt;). There&#39;s no separate control for the three
pipelines (content / ad / broadcast). You can&#39;t, for example, allow
program-recognition while refusing ad-break measurement. It&#39;s all-or-nothing,
and the &lt;em&gt;availability&lt;/em&gt; of ACR per app is decided by the server/scenario logic,
not a per-app user setting.&lt;/p&gt;
&lt;h2 id=&quot;8-why-it-matters&quot; tabindex=&quot;-1&quot;&gt;8. Why it matters &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#8-why-it-matters&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scope vs. expectation.&lt;/strong&gt; Most people expect ACR (if they know it exists) to
watch broadcast TV. Here it watches &lt;em&gt;everything on the panel&lt;/em&gt;, including
third-party DRM streaming and HDMI devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote-tunable surveillance.&lt;/strong&gt; A server-controlled cadence means the
data-collection rate isn&#39;t a fixed, auditable property of the device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regulatory exposure.&lt;/strong&gt; Continuous, identity-linked viewing capture with a
single coarse consent raises questions under &lt;strong&gt;GDPR&lt;/strong&gt; (specific, informed
consent; right to object) and &lt;strong&gt;CCPA/CPRA&lt;/strong&gt; (sharing/sale of personal
information). The Vizio precedent is directly on point.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-this-was-observed&quot; tabindex=&quot;-1&quot;&gt;How this was observed &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#how-this-was-observed&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These findings come from &lt;strong&gt;static analysis of the extracted firmware&lt;/strong&gt; and
&lt;strong&gt;memory forensics on a device under my control&lt;/strong&gt;. The fingerprint structure,
match results, and the production upload/control hosts were read directly from
the live ACR process; the bootstrap control endpoint and the server-controlled
query-interval logic are present as strings in the shipped &lt;code&gt;acr&lt;/code&gt; binary, which
fetches its actual upload target from a control server at runtime.
&lt;strong&gt;Security-specific details of how device access was obtained are deliberately
withheld pending coordinated disclosure&lt;/strong&gt; and are out of scope for this privacy
write-up.&lt;/p&gt;
&lt;h2 id=&quot;what-you-can-do&quot; tabindex=&quot;-1&quot;&gt;What you can do &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/acr/#what-you-can-do&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On current Samsung TVs, the ACR-related consent typically lives under
&lt;strong&gt;Settings → General &amp;amp; Privacy → Terms &amp;amp; Privacy&lt;/strong&gt; (look for &lt;strong&gt;Viewing
Information Services&lt;/strong&gt; / &lt;strong&gt;Customization Service&lt;/strong&gt;). Disabling it withdraws
consent for &lt;em&gt;use&lt;/em&gt; of the data. One caveat here is that toggling consent is not the same as proving capture has stopped; there could be a situation where samsung still stores the content in a SQlite DB on the TV and then siphons all significant identifiers if the user were to re-enable ACR agreement.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This is independent security/privacy research on a device the author owns. No
user data other than the author&#39;s own was accessed. Live credentials and
identifiers have been redacted. Citation and contact: Sagar Mohan.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Kagi: The New Kid on the Block?</title>
    <link href="https://sagar.systems/blog/kagi/" />
    <updated>2024-03-30T00:00:00Z</updated>
    <id>https://sagar.systems/blog/kagi/</id>
    <content type="html">&lt;p&gt;I recently switched to using Kagi as my main search engine. As of when this blog post is written, their charge for individual accounts is $10 per month. Considering how we&#39;ve been spoilt by the likes of Google and DuckDuckGo: is paying so much for search actually worth it? I&#39;ve not made up my mind about this; however, I do have to say that Kagi is slowly growing on me. In this post, I will list the stuff about Kagi I&#39;ve observed over the course of using it.&lt;/p&gt;
&lt;h2 id=&quot;search-results&quot; tabindex=&quot;-1&quot;&gt;Search Results &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#search-results&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kagi has been quite good at giving me the results I want. In fact, it gave me quite interesting links that Google and DuckDuckGo did not give me. For example, I was searching for the background behind &lt;a href=&quot;https://en.wikipedia.org/wiki/Andy_and_Bill%27s_law&quot;&gt;&amp;quot;What Andy Giveth, Bill Taketh Away&amp;quot;&lt;/a&gt; and Kagi gave me the wiki link first, but within the relevant links, it put &lt;a href=&quot;https://en.wikipedia.org/wiki/Wirth%27s_law&quot;&gt;Wirth&#39;s Law&lt;/a&gt; right there where I could see it. Other search engines also included it but not at the same rank. This is of course just one example, but there have been multiple instances where Kagi has ranked relevent pages far better than others.
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sagar.systems/blog/kagi/w45B_aVdNj-1246.avif&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sagar.systems/blog/kagi/w45B_aVdNj-1246.webp&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sagar.systems/blog/kagi/w45B_aVdNj-1246.png&quot; alt=&quot;&quot; width=&quot;1246&quot; height=&quot;805&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;search-lens&quot; tabindex=&quot;-1&quot;&gt;Search Lens &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#search-lens&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now this is an interesting feature I have not observed on other services before. Kagi give you the option of searching for something under a specific Lens. For example, I can search for a topic, say &amp;quot;How do Prions start folding incorrectly&amp;quot; and make it so that it gives me results from academic sources. Currently, it gives the options to use Fediverse Forums, News 360, Usenet/Archive, Kagi Documentation, Academic, Forums, Programming, PDFs by default. The best part is: &lt;a href=&quot;https://help.kagi.com/kagi/features/lenses.html&quot;&gt;You can create your own!&lt;/a&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sagar.systems/blog/kagi/CMiw_D2v_i-1175.avif&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sagar.systems/blog/kagi/CMiw_D2v_i-1175.webp&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sagar.systems/blog/kagi/CMiw_D2v_i-1175.png&quot; alt=&quot;&quot; width=&quot;1175&quot; height=&quot;503&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;utility-features&quot; tabindex=&quot;-1&quot;&gt;Utility Features &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#utility-features&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now since Google, and to some extent DuckDuckGo, offer features which directly answer your questions (like currency converion, time at place, etc), does Kagi do the same? I mean, kinda? It does somethings since Kagi &lt;a href=&quot;https://blog.kagi.com/kagi-wolfram&quot;&gt;recently integrated&lt;/a&gt; WolframAlpha into their platform so we get complex math features like so:
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sagar.systems/blog/kagi/DKIcf5xC5h-1172.avif&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sagar.systems/blog/kagi/DKIcf5xC5h-1172.webp&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sagar.systems/blog/kagi/DKIcf5xC5h-1172.png&quot; alt=&quot;alt text&quot; width=&quot;1172&quot; height=&quot;315&quot;&gt;&lt;/picture&gt;
Wolfram Alpha covers most similar stuff like Currency Conversion as well, but what about temperature?&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://sagar.systems/blog/kagi/sAnqCZq7zK-1214.avif&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://sagar.systems/blog/kagi/sAnqCZq7zK-1214.webp&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://sagar.systems/blog/kagi/sAnqCZq7zK-1214.png&quot; alt=&quot;&quot; width=&quot;1214&quot; height=&quot;720&quot;&gt;&lt;/picture&gt;
Nope, a pretty basic feature which is still not present. Probably some other features like this are lacking, you can find out based on features you use on other search engines.&lt;/p&gt;
&lt;h2 id=&quot;misc-features&quot; tabindex=&quot;-1&quot;&gt;Misc Features &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#misc-features&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kagi has some security feature which scans each search result. This can be accessed by clicking the shield icon after each search result. Most other services offer similar service so nothing special here. Maybe they offer a bit more in-depth analysis of each site? I don&#39;t know, I use my own wits to see if a website is worth clicking on. Hey, it&#39;s worked for me so far.&lt;/p&gt;
&lt;h2 id=&quot;things-about-kagi-i-dont-like&quot; tabindex=&quot;-1&quot;&gt;Things about Kagi I don&#39;t like &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#things-about-kagi-i-dont-like&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, the product alone is fine. It has a few rough edges but that&#39;s a given considering it&#39;s relatively new. However, the people behind them have done some &amp;quot;interesting&amp;quot; stuff. They raised $670k through multiple small investors and then proceeded to utilize one-thirds of that to giving away free tshirts to their first 20000 customers? I mean, I get they are appreciating their customers but spending so much money so early on for just that? It has raised some eyebrows for sure.&lt;/p&gt;
&lt;p&gt;They have their own &lt;a href=&quot;https://browser.kagi.com/&quot;&gt;browser&lt;/a&gt; in the Apple ecosystem which is pretty buggy. I assume the reasoning behind it is that Safari does not include Kagi as a Search enginer choice (yet) and their &lt;a href=&quot;https://apps.apple.com/us/app/kagi-for-safari/id1622835804&quot;&gt;extension&lt;/a&gt; whichs works around this issue is not really privacy friendly. Building and maintaining a good browser is not easy, and it is not cheap. If Apple decided to include Kagi as a Search Engine choice, maybe Kagi should let go of their own browser and focus on their search engine.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;heading-anchor&quot; href=&quot;https://sagar.systems/blog/kagi/#conclusion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kagi is a good product. However, given the rise of LLMs like ChatGPT, Claude and search focused products like &lt;a href=&quot;https://perplexity.ai&quot;&gt;Perplexity.ai&lt;/a&gt;, it is only a test of time if Kagi will survive the onslaught of the AI arms race. It is unfortunate timing for Kagi to have set up shop during but I think they are doing the right things so hopefully it all works out for them.&lt;/p&gt;
</content>
  </entry>
</feed>