1
0
mirror of https://github.com/PrivSec-dev/privsec.dev synced 2024-12-22 21:01:34 -05:00
privsec.dev/public/apps/f-droid-security-analysis/index.html

41 lines
84 KiB
HTML
Raw Normal View History

<!doctype html><html lang=en dir=auto><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=robots content="index, follow"><title>F-Droid Security Analysis | PrivSec.dev</title><meta name=keywords content="software,android,security"><meta name=description content="F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.
Before we start, a few things to keep in mind:
The main goal of this write-up was to inform users so they can make responsible choices, not to trash someone else&rsquo;s work."><meta name=author content="Wonderfall"><link rel=canonical href=https://wonderfall.dev/fdroid-issues><link crossorigin=anonymous href=/assets/css/stylesheet.8b523f1730c922e314350296d83fd666efa16519ca136320a93df674d00b6325.css integrity="sha256-i1I/FzDJIuMUNQKW2D/WZu+hZRnKE2MgqT32dNALYyU=" rel="preload stylesheet" as=style><script defer crossorigin=anonymous src=/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA=" onload=hljs.initHighlightingOnLoad()></script>
<link rel=icon href=https://privsec.dev/%3Clink%20/%20abs%20url%3E><link rel=icon type=image/png sizes=16x16 href=https://privsec.dev/%3Clink%20/%20abs%20url%3E><link rel=icon type=image/png sizes=32x32 href=https://privsec.dev/%3Clink%20/%20abs%20url%3E><link rel=apple-touch-icon href=https://privsec.dev/%3Clink%20/%20abs%20url%3E><link rel=mask-icon href=https://privsec.dev/%3Clink%20/%20abs%20url%3E><meta name=theme-color content="#2e2e33"><meta name=msapplication-TileColor content="#2e2e33"><noscript><style>#theme-toggle,.top-link{display:none}</style></noscript><meta property="og:title" content="F-Droid Security Analysis"><meta property="og:description" content="F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.
Before we start, a few things to keep in mind:
The main goal of this write-up was to inform users so they can make responsible choices, not to trash someone else&rsquo;s work."><meta property="og:type" content="article"><meta property="og:url" content="https://privsec.dev/apps/f-droid-security-analysis/"><meta property="article:section" content="apps"><meta name=twitter:card content="summary"><meta name=twitter:title content="F-Droid Security Analysis"><meta name=twitter:description content="F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.
Before we start, a few things to keep in mind:
The main goal of this write-up was to inform users so they can make responsible choices, not to trash someone else&rsquo;s work."><script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":2,"name":"Applications","item":"https://privsec.dev/apps/"},{"@type":"ListItem","position":3,"name":"F-Droid Security Analysis","item":"https://privsec.dev/apps/f-droid-security-analysis/"}]}</script><script type=application/ld+json>{"@context":"https://schema.org","@type":"BlogPosting","headline":"F-Droid Security Analysis","name":"F-Droid Security Analysis","description":"F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.\nBefore we start, a few things to keep in mind:\nThe main goal of this write-up was to inform users so they can make responsible choices, not to trash someone else\u0026rsquo;s work.","keywords":["software","android","security"],"articleBody":"F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.\nBefore we start, a few things to keep in mind:\nThe main goal of this write-up was to inform users so they can make responsible choices, not to trash someone elses work. I have respect for any work done in the name of good intentions. Likewise, please dont misinterpret the intentions of this article. You have your own reasons for using open-source or free/libre/whatever software which wont be discussed here. A development model shouldnt be an excuse for bad practices and shouldnt lure you into believing that it can provide strong guarantees it cannot. A lot of information in this article is sourced from official and trusted sources, but youre welcome to do your own research. These analyses do not account for threat models and personal preferences. As the author of this article, Im only interested in facts and not ideologies. This is not an in-depth security review, nor is it exhaustive.\n1. The trusted party problem To understand why this is a problem, youll have to understand a bit about F-Droids architecture, the things it does very differently from other app repositories, and the Android platform security model (some of the issues listed in this article are somewhat out of the scope of the OS security model, but the majority is).\nUnlike other repositories, F-Droid signs all the apps in the main repository with its own signing keys (unique per app) at the exception of the very few reproducible builds. A signature is a mathematical scheme that guarantees the authenticity of the applications you download. Upon the installation of an app, Android pins the signature across the entire OS (including user profiles): thats what we call a trust-on-first-use model since all subsequent updates of the app must have the corresponding signature to be installed.\nNormally, the developer is supposed to sign their own app prior to its upload on a distribution channel, whether that is a website or a traditional repository (or both). You dont have to trust the source (usually recommended by the developer) except for the first installation: future updates will have their authenticity cryptographically guaranteed. The issue with F-Droid is that all apps are signed by the same party (F-Droid) which is also not the developer. Youre now adding another party youll have to trust since you still have to trust the developer anyway, which isnt ideal: the fewer parties, the better.\nOn the other ha
&nbsp;|&nbsp;<span>Originally published at&nbsp;<a href=https://wonderfall.dev/fdroid-issues title=https://wonderfall.dev/fdroid-issues target=_blank rel="noopener noreferrer">wonderfall.dev</a></span></div></header><div class=toc><details><summary accesskey=c title="(Alt + C)"><span class=details>Table of Contents</span></summary><div class=inner><ul><li><a href=#1-the-trusted-party-problem aria-label="1. The trusted party problem">1. The trusted party problem</a></li><li><a href=#2-slow-and-irregular-updates aria-label="2. Slow and irregular updates">2. Slow and irregular updates</a></li><li><a href=#3-low-target-api-level-sdk-for-client--apps aria-label="3. Low target API level (SDK) for client &amp;amp; apps">3. Low target API level (SDK) for client & apps</a></li><li><a href=#4-general-lack-of-good-practices aria-label="4. General lack of good practices">4. General lack of good practices</a></li><li><a href=#5-confusing-ux aria-label="5. Confusing UX">5. Confusing UX</a></li><li><a href=#6-misleading-permissions-approach aria-label="6. Misleading permissions approach">6. Misleading permissions approach</a></li><li><a href=#conclusion-what-should-you-do aria-label="Conclusion: what should you do?">Conclusion: what should you do?</a></li></ul></div></details></div><div class=post-content><p>F-Droid is a popular alternative app repository for Android, especially known for its main repository dedicated to free and open-source software. F-Droid is often recommended among security and privacy enthusiasts, but how does it stack up against Play Store in practice? This write-up will attempt to emphasize major security issues with F-Droid that you should consider.</p><p>Before we start, a few things to keep in mind:</p><ul><li>The main goal of this write-up was to inform users so they can make responsible choices, not to trash someone else&rsquo;s work. I have respect for any work done in the name of good intentions. Likewise, please don&rsquo;t misinterpret the intentions of this article.</li><li>You have your own reasons for using open-source or free/libre/whatever software which won&rsquo;t be discussed here. A development model shouldn&rsquo;t be an excuse for bad practices and shouldn&rsquo;t lure you into believing that it can provide strong guarantees it cannot.</li><li>A lot of information in this article is sourced from official and trusted sources, but you&rsquo;re welcome to do your own research.</li><li>These analyses do not account for threat models and personal preferences. As the author of this article, I&rsquo;m only interested in facts and not ideologies.</li></ul><p><em>This is not an in-depth security review, nor is it exhaustive.</em></p><h2 id=1-the-trusted-party-problem>1. The trusted party problem<a hidden class=anchor aria-hidden=true href=#1-the-trusted-party-problem>#</a></h2><p>To understand why this is a problem, you&rsquo;ll have to understand a bit about F-Droid&rsquo;s architecture, the things it does very differently from other app repositories, and the <a href=https://arxiv.org/pdf/1904.05572.pdf>Android platform security model</a> (some of the issues listed in this article are somewhat out of the scope of the OS security model, but the majority is).</p><p>Unlike other repositories, F-Droid signs all the apps in the main repository with <strong>its own signing keys</strong> (unique per app) at the exception of the very few <a href=https://f-droid.org/en/docs/Reproducible_Builds/>reproducible builds</a>. A signature is a mathematical scheme that guarantees the authenticity of the applications you download. Upon the installation of an app, Android pins the signature across the entire OS (including user profiles): that&rsquo;s what we call a <em>trust-on-first-use</em> model since all subsequent updates of the app must have the corresponding signature to be installed.</p><p>Normally, the developer is supposed to sign their own app prior to its upload on a distribution channel, whether that is a website or a traditional repository (or both). You don&rsquo;t have to trust the source (usually recom
# This will go away in a future Android release
allow untrusted_app_25 proc_misc:file r_file_perms;
# Access to /proc/tty/drivers, to allow apps to determine if they
# are running in an emulated environment.
# b/33214085 b/33814662 b/33791054 b/33211769
# https://github.com/strazzere/anti-emulator/blob/master/AntiEmulator/src/diff/strazzere/anti/emulator/FindEmulator.java
# This will go away in a future Android release
allow untrusted_app_25 proc_tty_drivers:file r_file_perms;
</code></pre><p>This is a mere sample of the <a href=https://android.googlesource.com/platform/system/sepolicy/+/refs/tags/android-12.0.0_r21/private>SELinux exceptions</a> that have to be made on older API levels so that you can understand why it matters.</p><p>It turns out the official F-Droid client doesn&rsquo;t care much about this since it lags behind quite a bit, <strong><a href=https://gitlab.com/fdroid/fdroidclient/-/blob/2a8b16683a2dbee16d624a58e7dd3ea1da772fbd/app/build.gradle#L33>targeting the API level 25</a></strong> (Android 7.1) of which some SELinux exceptions were shown above. As a workaround, some users recommended third-party clients such as <a href=https://f-droid.org/en/packages/nya.kitsunyan.foxydroid/>Foxy Droid</a> or <a href=https://f-droid.org/en/packages/com.aurora.adroid/>Aurora Droid</a>. While these clients might be technically better, they&rsquo;re poorly maintained for some, and they also introduce yet another party to the mix. <a href=https://github.com/Iamlooker/Droid-ify>Droid-ify</a> (recently rebreanded to Neo-Store) seems to be a better option than the official client in most aspects.</p><p>Furthermore, F-Droid <strong>doesn&rsquo;t enforce a minimum target SDK</strong> for the official repository. Play Store <a href=https://developer.android.com/google/play/requirements/target-sdk>does that quite aggressively</a> for new apps and app updates:</p><ul><li>Since August 2021, Play Store requires new apps to target at least API level 30.</li><li>Since November 2021, existing apps must at least target API level 30 for updates to be submitted.</li></ul><p>While it may seem bothersome, it&rsquo;s a necessity to keep the <strong>app ecosystem modern and healthy</strong>. Here, F-Droid sends the wrong message to developers (and even users) because they should care about it, and this is why many of us think it may be even harmful to the FOSS ecosystem. Backward compatibility is often the enemy of security, and while there&rsquo;s a middle-ground for convenience and obsolescence, it shouldn&rsquo;t be exaggerated. As a result of this philosophy, the main repository of F-Droid is filled with obsolete apps from another era, just for these apps to be able to run on the more than ten years old Android 4.0 Ice Cream Sandwich. Let&rsquo;s not make the same mistake as the desktop platforms: instead, complain to your vendors for selling devices with no decent OS/firmware support.</p><p>There is little practical reason for developers not to increase the target SDK version (<code>targetSdkVersion</code>) along with each Android release. This attribute matches the version of the platform an app is targeting, and allows access to modern improvements, rules and features on a modern OS. The app can still ensure backwards compatibility in such a way that it can run on older platforms: the <code>minSdkVersion</code> attribute informs the system about the minimum API level required for the application to run. Setting it too low isn&rsquo;t practical though, because this requires having a lot of fallback code (most of it is handled by common libraries) and separate code paths.</p><p>At the time of writing:</p><ul><li>Android 9 is the oldest Android version that is <a href=https://endoflife.date/android>getting security updates</a>.</li><li><a href=https://developer.android.com/about/dashboards>~80% of the Android devices</a> used in the world are <strong>at least</strong> running 8.0 Oreo.</li></ul><p><em>Overall statistics do not reflect real-world usage of a given app (people using old devices are not necessarily using your app). If anything, it should be viewed as an underestimation.</em></p><h2 id=4-general-lack-of-good-practices>4. General lack of good practices<a hidden class=anchor aria-hidden=true href=#4-general-lack-of-good-practices>#</a></h2><p>The F-Droid client allows multiple repositories to coexist within the same app. Many of the issues highlighted above were focused on the main official repository which most of the F-Droid users will use anyway. However, having <strong>other repositories in a
&lt;network-security-config&gt;
&lt;base-config cleartextTrafficPermitted=&#34;false&#34;/&gt;
&lt;domain-config&gt;
&lt;domain includeSubdomains=&#34;true&#34;&gt;apps.grapheneos.org&lt;/domain&gt;
&lt;pin-set&gt;
&lt;!-- ISRG Root X1 --&gt;
&lt;pin digest=&#34;SHA-256&#34;&gt;C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M=&lt;/pin&gt;
&lt;!-- ISRG Root X2 --&gt;
&lt;pin digest=&#34;SHA-256&#34;&gt;diGVwiVYbubAI3RW4hB9xU8e/CH2GnkuvVFZE8zmgzI=&lt;/pin&gt;
&lt;!-- Let&#39;s Encrypt R3 --&gt;
&lt;pin digest=&#34;SHA-256&#34;&gt;jQJTbIh0grw0/1TkHSumWb+Fs0Ggogr621gT3PvPKG0=&lt;/pin&gt;
&lt;!-- Let&#39;s Encrypt E1 --&gt;
&lt;pin digest=&#34;SHA-256&#34;&gt;J2/oqMTsdhFWW/n85tys6b4yDBtb6idZayIEBx7QTxA=&lt;/pin&gt;
...
&lt;/pin-set&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</code></pre><p>To be fair, they&rsquo;ve thought several times about adding certificate pinning to their client <a href=https://gitlab.com/fdroid/fdroidclient/-/issues/105>at least for the default repositories</a>. <a href=https://gitlab.com/fdroid/fdroidclient/-/blob/1.14-alpha4/app/src/main/java/org/fdroid/fdroid/FDroidCertPins.java>Relics of preliminary work</a> can even be found in their current codebase, but it&rsquo;s unfortunate that they haven&rsquo;t been able to find <a href=https://github.com/f-droid/fdroidclient/commit/7f78b46664981b9b73cadbfdda6391f6fe939c77>any working implementation</a> so far. Given the overly complex nature of F-Droid, that&rsquo;s largely understandable.</p><p>F-Droid also has a problem regarding the adoption of <strong><a href=https://source.android.com/security/apksigning>new signature schemes</a></strong> as they <a href=https://forum.f-droid.org/t/why-f-droid-is-still-using-apk-signature-scheme-v1/10602>held out on the v1 signature scheme</a> (which was <a href=https://www.xda-developers.com/janus-vulnerability-android-apps/>horrible</a> and deprecated since 2017) until they were forced by Android 11 requirements to support the newer v2/v3 schemes (v2 was introduced in Android 7.0). Quite frankly, this is straight-up bad, and <strong>signing APKs with GPG</strong> is no better considering <a href=https://latacora.micro.blog/2019/07/16/the-pgp-problem.html>how bad PGP and its reference implementation GPG are</a> (even Debian <a href=https://wiki.debian.org/Teams/Apt/Spec/AptSign>is trying to move away from it</a>). Ideally, F-Droid should fully move on to newer signature schemes, and should completely phase out the legacy signature schemes which are still being used for some apps and metadata.</p><h2 id=5-confusing-ux>5. Confusing UX<a hidden class=anchor aria-hidden=true href=#5-confusing-ux>#</a></h2><p>It is worth mentioning that their website has (for some reason) always been hosting an <a href=https://forum.f-droid.org/t/why-does-the-f-droid-website-nearly-always-host-an-outdated-f-droid-apk/6234>outdated APK of F-Droid</a>, and this is still the case today, leading to many users wondering why they can&rsquo;t install F-Droid on their secondary user profile (due to the downgrade prevention enforced by Android). &ldquo;Stability&rdquo; seems to be the main reason mentioned on their part, which doesn&rsquo;t make sense: either your version isn&rsquo;t ready to be published in a stable channel, or it is and new users should be able to access it easily.</p><p>F-Droid should enforce the approach of prefixing the package name of their alternate builds with <code>org.f-droid</code> for instance (or add a <code>.fdroid</code> suffix as some already have). Building and signing while <strong>reusing the package name</strong> (<a href=https://developer.android.com/studio/build/configure-app-module>application ID</a>) is bad practice as it causes <strong>signature verification errors</strong> when some users try to update/install these apps from other sources, even directly from the developer. That is again due to the security model of Android which enforces a signature check when installing app updates (or installing them again in a secondary user profile). Note that this is going to be an issue with Play App Signing as well, and developers are encouraged to follow this approach should they intend to distribute their apps through different distribution channels.</p><p>This results in a confusing user experience where it&rsquo;s hard to keep track of who signs each app, and from which repository the app should be downloaded or updated.</p><h2 id=6-misleading-permissions-approach>6. Misleading permissions approach<a hidden class=anchor aria-hidden=true href=#6-misleading-permissions-approach>#</a></h2><p>F-Droid shows a list of the <a href=https://developer.android.com/reference/android/Manifest.permission>low-level permissions</a> for each app: these low-level permissions are usually grouped in the standard high-level permissions (Location, Microphone, Camera, etc.) and special toggles (n
</code></pre><p>Also, as written above: the OS pins the app signature (for all profiles) upon installation, and enforces signature check for app updates. In practice, this means the source doesn&rsquo;t matter as much after the initial installation.</p><p>For most people, I&rsquo;d recommend just <strong>sticking with Play Store</strong>. Play Store isn&rsquo;t quite flawless, but emphasises the adoption of modern security standards which in turn encourages better privacy practices; as strange as it may sound, Google is not always doing bad things in that regard.</p><p><em>Note: this article obviously can&rsquo;t address all the flaws related to Play Store itself. Again, the main topic of this article is about F-Droid and should not be seen as an exhaustive comparison between different app repositories.</em></p><blockquote><p>Should I really care?</p></blockquote><p><strong>It&rsquo;s up to your threat model</strong>, and of course your personal preferences. Most likely, your phone won&rsquo;t turn into a nuclear weapon if you install F-Droid on it - and this is far from the point that this article is trying to make. Still, I believe the information presented will be valuable for anyone who values a <strong>practical approach to privacy</strong> (rather than an ideological one). Such an approach is partially described below.</p><blockquote><p>But there is more malware in Play Store! How can you say that it&rsquo;s more secure?</p></blockquote><p>As explained above, it doesn&rsquo;t matter as you shouldn&rsquo;t really rely on any quality control to be the sole guarantee that a software is free of malicious or exploitable code. Play Store and even the Apple App Store may have a considerable amount of malware because a full reverse-engineering of any uploaded app isn&rsquo;t feasible realistically. However, they fulfill their role quite well, and that is all that is expected of them.</p><blockquote><p>With Play App Signing being effectively enforced for new apps, isn&rsquo;t Play Store as &ldquo;flawed&rdquo; as F-Droid?</p></blockquote><p>I&rsquo;ve seen this comment repeatedly, and it would be dismissing all the other points made in this article. Also, I strongly suggest that you carefully read the sections related to Play App Signing, and preferably the official documentation on this matter. It&rsquo;s not a black and white question and there are many more nuances to it.</p><blockquote><p>Aren&rsquo;t open-source apps more secure? Doesn&rsquo;t it make F-Droid safer?</p></blockquote><p>You can still find and get your open-source apps elsewhere. And no, open-source apps <a href=https://seirdy.one/2022/02/02/floss-security.html>aren&rsquo;t necessarily more private or secure</a>. Instead, you should rely on the strong security and privacy guarantees provided by a modern operating system with <strong>a robust sandboxing/permission model</strong>, namely modern Android, GrapheneOS and iOS. Pay close attention to the permissions you grant, and avoid legacy apps as they could require invasive permissions to run.</p><p>When it comes to <em>trackers</em> (this really comes up a lot), you shouldn&rsquo;t believe in the flawed idea that you can enumerate all of them. The <em>enumerating badness</em> approach is <a href=https://www.ranum.com/security/computer_security/editorials/dumb/>known to be flawed in the security field</a>, and the same applies to privacy. You shouldn&rsquo;t believe that a random script can detect every single line of code that can be used for data exfiltration. Data exfiltration can be properly prevented in the first place by the permission model, which again <strong>denies access to sensitive data by default</strong>: this is a simple, yet rigorous and effective approach.</p><p>No app should be unnecessarily entrusted with any kind of permission. It is only if you deem it necessary that you should allow access to a type of data, and this access should be as fine-grained as possible. That&rsquo;s the way the Android platform works (regular apps run in the explicit <code>untrusted_app</code> domain) and co
<span>Powered by
<a href=https://gohugo.io/ rel="noopener noreferrer" target=_blank>Hugo</a> &
<a href=https://github.com/adityatelange/hugo-PaperMod/ rel=noopener target=_blank>PaperMod</a></span></footer><a href=#top aria-label="go to top" title="Go to Top (Alt + G)" class=top-link id=top-link accesskey=g><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentcolor"><path d="M12 6H0l6-6z"/></svg></a><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script><script>document.querySelectorAll("pre > code").forEach(e=>{const n=e.parentNode.parentNode,t=document.createElement("button");t.classList.add("copy-code"),t.innerHTML="copy";function s(){t.innerHTML="copied!",setTimeout(()=>{t.innerHTML="copy"},2e3)}t.addEventListener("click",t=>{if("clipboard"in navigator){navigator.clipboard.writeText(e.textContent),s();return}const n=document.createRange();n.selectNodeContents(e);const o=window.getSelection();o.removeAllRanges(),o.addRange(n);try{document.execCommand("copy"),s()}catch{}o.removeRange(n)}),n.classList.contains("highlight")?n.appendChild(t):n.parentNode.firstChild==n||(e.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName=="TABLE"?e.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(t):e.parentNode.appendChild(t))})</script></body></html>